# Services

> Full-stack PostgreSQL & open source consulting: database optimization, Linux administration, Python/Ruby development, Ansible automation & 24/7 support services.

# Expert and Professional Consulting

Surrounding PostgreSQL and your Open Source stack

[ Consult an Expert ](</contact-us/>) [ Get Support ](</support/>)

## Expert PostgreSQL and Open Source Services, Built Around Your Stack

Since 1997, Command Prompt has enabled enterprises run PostgreSQL reliably — from legacy EOL environments to regulated cloud deployments. Whether you need a one-time performance audit or a long-term operational partner, we work the way you need. 

  * [Success Stories and Case Studies](</about/success-stories-case-studies/>)
  * [Alternatives](</alternatives/>): Honest comparison betwen CMD and others



## Postgres and Open Source services

![24x7 Support](/media/images/24-7.height-300.format-webp.webp)

## 24x7 Support

[Support for your Postgres and Open Source](</support/>) needs including [PostgreSQL EOL](</support/support-for-eol-versions-of-postgres/>) support.

![Postgres Consulting](/media/images/man-with-briefcase.height-300.format-webp.webp)

## Postgres Consulting

Including architecture, best practices, deployment, performance, custom development and high availability.

![Full Stack](/media/images/full-stack.height-300.format-webp.webp)

## Full Stack

Open Source consulting including architecture, best practices, deployment and project management.

![Postgres Training](/media/images/square-hat_19OpHL2.height-300.format-webp.webp)

## Postgres Training

Including administration, maintenance, performance and cloud options

[ Learn More ](</services/training/>)

![Cloud Migration](/media/images/cloud-migration.height-300.format-webp.webp)

## Cloud Migration

Our migration assessment focuses on the complete system, not just one component. Where others may focus on only one part of the puzzle, i.e. the database OR the application and only development, our migration experts look at your entire stack and the entire migration lifecycle

[ Learn More ](</products/cloud-migration-assessment/>)

![Postgres Migration](/media/images/migration_kU2jVRN.height-300.format-webp.webp)

## Postgres Migration

If you're looking to move to Postgres from another database system, we can help you plan and execute a smooth transition.

[ Learn More ](</services/database-migration/>)

## Get in touch

We understand that every business is unique, which is why we offer customized solutions tailored to your specific needs. Our team of experts will work with you to develop a comprehensive plan that meets your goals and budget.

[Learn More](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/services/)

---

# Full Stack Offerings

> Command Prompt Full Stack Offerings

## Command Prompt Full Stack Offerings

Expand and strengthen your capabilities with Command Prompt's full stack offerings. Common services include:  
  


  *  **PostgreSQL Administration**
  *  **PostgreSQL Design**
    * Architecture
    * Modeling
    * High Availability
  *  **PostgreSQL Solutions**
    * Version upgrades
    * Cloud Migrations
      * AWS RDS
      * AWS EC2
      * Etc.
      * Google Cloud
    * Migrations to Postgres
      * Oracle
      * MySQL/MariaDB
      * Etc.
    * Conversions
      * Greenplum
      * Redshift
      * Etc.
  *  **Databases and Storage**
    * AWS
      * EC2
      * RDS
      * Aurora
    * Microsoft Azure PostgreSQL
    * Cloud SQL for PostgreSQL (Google Cloud Platform)
    * AlloyDB
    * Time-series SQL
      * TimescaleDB
    * Etc.
  *  **Data Migration**
  *  **Operating System Optimization and Configuration**
    * Linux
      * Debian
      * Ubuntu
      * Centos
      * Red Hat Enterprise Linux
    * Solaris
    * FreeBSD
    * Windows Server
  *  **Professional Project Management**
    * Project Scope
    * Project Lead/Organization
    * Project Planning
    * Resource Allocation
    * Task Estimation
    * Scheduling
    * Requirements Building
    * Risk Assessment



* * *

##  **Additional Service Areas Available:**

  *  **Technical Business Requirements Assessment and Optimization**
  *  **Software Evaluation**
  *  **Application Development**
  *  **Business Advisory Services**
  *  **Business Intelligence**
  *  **Infrastructure/Engineering**
  *  **Web and User Interface Development**
    * HTML
    * CSS/SASS/LESS
    * PHP
    * XML
    * XSLT
  *  **Programming Languages**
    * Javascript
    * Python
    * Ruby
    * SQL
    * C
    * C++
    * Bash
  *  **Web Server**
    * Apache
    * NGINX
  *  **Operating System Design**
    * Configuration
    * Tuning
    * Development
    * Installation
    * Optimization
    * Partitioning
  *  **Network Configuration**
    * DNS
    * SMTP/Postfix
    * VPN
    * SSH
  *  **Configuration Management**
    * Ansible
    * Puppet
    * etc...
  *  **Database Monitoring**
  *  **Operating System Monitoring**
  *  **Virtualization**
    * Containerization
  *  **High Availability Clusters**
  *  **Central Authentication/SSO**
    * FreeIPA
    * LDAP
    * SAML
  *  **Cisco Networking**
    * Auditing
    * Routing
    * Security



 _(last updated: January 1, 2021)_

 _  
_

Please note if there is a service or product you are looking for that is not on this list, we are able to offer custom services to you based on your needs.[Contact us](</contact-us/>) today!

---
[View this page online](https://www.commandprompt.com/services/fullstack/)

---

# Training

> Command Prompt On-Demand Training for PostgreSQL

# Learn from PostgreSQL and Open Source Experts

PostgreSQL and Open Source training that matters.

[ Contact us ](</contact-us/>) [ Get support ](</support/>)

## Training

Command Prompt has been providing on-demand training since 1997 and unlike most training providers Command Prompt can cater the training to your specific business requirements.  
  


Do you only need a short course on backup and recovery, or a multiple day course on overall PostgreSQL Administration? How about an interactive on-line course on configuring Point-in-Time Recovery? Whatever your PostgreSQL Training needs are, we can help.

  


###  **Intro to PostgreSQL**

The introduction to PostgreSQL course is for people unfamiliar with topics such as relational databases, norm forms, transactional control and MVCC. We also discuss basic security including network access and user/group (role) interaction with objects. In short, users of PICK or NoSQL database developers with no firm understanding of how traditional RDMS operate should start with this course.  
  


###  **Postgres Administration**

This training is a minimal introduction on PostgreSQL for DBAs who are already competent within other relational database systems such as Oracle.This training assumes a good working knowledge of SQL and basics of database administration. Required prerequisite course or equivalent knowledge: Intro to PostgreSQL. The training is run on a Linux operating system, therefore a good working knowledge of UNIX/Linux is required.

  


###  **Postgres Performance And Maintenance**

Get a comprehensive look at proper PostgreSQL maintenance, how it relates to Performance and tying the two together for proper provisioning and stringent uptime requirements. Students will leave this talk with full understanding of topics such as the background writer, wal writer, shared buffers, system views for monitoring, and provisioning properly within a Linux LTS environment.  
  


###  **Intro to Backup and Recovery**

Learn the basics of PostgreSQL's built in backup and restore capabilities, including logical backups with pg_dump and pg_restore, as well as physical backups and continuous archiving.Required prerequisite course or equivalent knowledge: Intro to PostgreSQL.  
  


###  **Postgres For Oracle People**

A highly popular talk discussing the in and out of PostgreSQL for Oracle folks. This training is for technical folks considering making the switch from Oracle. It discusses the subtle differences of Oracle from a business and technical standpoint. How to work with differences between data types, and other features such as replication.  
  


###  **POSTGRESQL.CONF from A to Z**

Everybody uses it, almost nobody knows what each parameter means. Most people have heard of it but few people have taken the time to understand the ins and outs of postgresql.conf. Explore the postgresql.conf as we cover memory settings, the background writer, autovacuum, random_page_cost, effective_cache_size and many more topics. From A-Z, you will walk away from this training with a firm understanding of the postgresql.conf.  
  


###  **Elevating Your Confidence With Postgresql's Restoration Capabilities**

Learn the nuances of PostgreSQL's built in backup and restore capabilities as well as external abilities brought about by technologies such as snapshots and pgBackrest. There will be instruction on pg_dump/all and restore including a full understanding of the different backup/restore formats, when to use them and how to reduce potential production issues running long backups. Lastly, the students will be shown how to use base backups, PITR as well as filesystem snapshots and other well known utilities to properly manage data.  
  


###  **The Power of Postgres Replication**

Learn the standard replication options within Postgres including binary and logical replication in this half-day training. Students are expected to have an intermediate level or above skills working with PostgreSQL.

---
[View this page online](https://www.commandprompt.com/services/training/)

---

# Nutanix Products

## Nutanix Products

![pgBackRest](/media/images/MX4rk2b2_400x400.height-300.format-webp.webp)

## pgBackRest

pgBackRest aims to be a reliable, easy-to-use backup and restore solution that can seamlessly scale up to the largest databases and workloads by utilizing algorithms that are optimized for database-specific requirements.

![pgLogical](/media/images/pglogical.height-300.format-webp.webp)

## pgLogical

pglogical is a logical replication system implemented entirely as a PostgreSQL extension. Fully integrated, it requires no triggers or external programs. This alternative to physical replication is a highly efficient method of replicating data using a publish/subscribe model for selective replication.

## Contact Us!

[Contact Us Today](</contact-us/>) to configure pgBackRest and/or pgLogical with Nutanix!

---
[View this page online](https://www.commandprompt.com/services/nutanix-products/)

---

# Database Migration

> Migrating from Oracle or MySQL to PostgreSQL? Command Prompt has managed source-to-Postgres migrations for organizations of all sizes. Expert project management, proven methodology, on-prem or cloud.

# Database Migration

Increase your database value, migrate to PostgreSQL for Performance and increased ROI.

[ Contact us ](</contact-us/>) [ Get support ](</support/>)

Command Prompt has managed source-to-PostgreSQL migrations across Oracle, MySQL, and SQL Server for organizations of all sizes and industries, from SMBs to global companies, including highly regulated FinTech and HealthTech sectors.

  
We plan for the hard parts, including schema conversion edge cases, stored procedure rewrites, application-layer compatibility, data validation at scale, long before the work begins, not during or after the process.  


## Your Migration, Done Right

Moving to PostgreSQL is one of the smartest infrastructure decisions you can make, but only if the migration itself doesn't become the problem.

  
Command Prompt brings both project management discipline and deep technical expertise to every engagement, so your transition stays on schedule and your team stays focused on what matters.

  
The result: lower licensing and support costs, a thriving open source ecosystem at your fingertips, and a database built to last.  
  


## Benefits of Migrating to PostgreSQL

  * Zero license fees
  * Reasonable support costs
  * Lower personnel costs
  * Proven adoption and growth of industry
  * Proven reliability and data integrity with true ACID compliance
  * Pure, Free, Open and BSD licensed
  * Active ecosystem and community
  * Zero vendor lock-in
  * Cloud friendly
  * Scalable and High Performance
  * The most standards compliant database
  * Extensible  




## Why Most Migrations Stall

Organizations that attempt Oracle-to-PostgreSQL migrations without a specialist tend to hit the same friction points:

  * Schema conversion is straightforward; stored procedure and trigger rewrites are not
  * Application code assumes Oracle-specific syntax and behavior
  * Testing at scale surfaces data integrity issues late in the process
  * Cutover planning underestimates downtime risk
  * Post-go-live performance is worse than expected because PostgreSQL tuning was an afterthought



We address all of these issues before they become blockers.  


## What the Migration Covers

### Assessment Phase

  * Review of business functionality, availability, and security requirements
  * Analysis of tables, stored procedures, triggers, including the number and complexity
  * Identification of syntax and functionality differences between source and PostgreSQL
  * Extension evaluation: what PostgreSQL extensions can replace source-DB functionality
  * Testing strategy design: data, code, and application correctness validation
  * Deployment options: on-premises, AWS, GCP, hybrid
  * Data conversion and synchronization planning: size, downtime tradeoffs, parallel operation
  * Skills and training gap identification for post-migration operations  




### Migration Execution

  * Schema conversion and stored procedure rewriting
  * Application-layer compatibility work
  * Data migration and validation
  * Cutover planning and execution support
  * Post-migration performance tuning and stabilization  




## What You Receive

At the end of the assessment phase you receive a written report with:

  * Findings and complexity rating
  * Recommended migration approach
  * Estimated effort and cost for full migration execution
  * Identified risks and mitigation recommendations



We review the report with you in detail. You leave with everything you need to make a go/no-go decision and plan your migration process.

## Source databases we support

## Source databases

  * EDB Postgres
  * Oracle
  * MySQL / MariaDB
  * Microsoft SQL Server  




## Target environments

### Hybrid on-prem/cloud

  * On-premises Linux (RHEL, Rocky, Ubuntu, Debian and more)
  * Google Cloud Platform (Cloud SQL)
  * Microsoft Azure
  * Amazon Web Services (AWS) including Amazon Linux, Amazon EC2, Amazon RDS for PostgreSQL, Amazon Aurora PostgreSQL



## Ready to get started?

Let's have a call about how we can migrate you to the world's standard database.

[Contact Us](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/services/database-migration/)

---

# Advanced Monitoring Solutions

> Monitoring designed and run by the engineers who answer the alerts. We deploy Open Source Zabbix specialized for Postgres and the stack around it.

# Postgres & Full-Stack Monitoring

Monitoring designed and run by the engineers who answer the alerts.

[ Contact Us ](</contact-us/>) [ Get Support ](</support/>)

## Monitoring That Catches Problems Before Your Customers Do

Most monitoring fails one of two ways: it stays silent while the disk fills, or it cries wolf until everyone stops reading the alerts. We build monitoring that does neither. We design, tune, and deploy monitoring that is (optionally) run by the same engineers who answer when something actually breaks.

## Built on Open Source Zabbix, specialized for PostgreSQL

Our standard deployment is Zabbix. It is open source, carries no per-host licensing, and goes deep enough to cover Postgres internals and everything underneath. Already invested in Datadog, New Relic, or pganalyze? We work with those too, and we can feed CloudWatch and Google Cloud telemetry into whichever platform you keep.

## What we deliver

### **Design and Deployment**

We instrument what matters: replication lag, bloat, checkpoint behavior, connection saturation, the Linux hosts underneath, and the application signals that tell you users are hurting. Then we set thresholds an on-call engineer can trust. Every alert is actionable, or it does not page.

###  **Managed Monitoring**

With a [Proactive SLA](</support/>), we watch it for you. Our engineers answer your alerts 24x7x365. We tuned the thresholds, so we know what each one means before we pick it up.

## Why Command Prompt

We have run production Postgres since 1997. Monitoring configured by people who get paged at 3 a.m. is stingy with false alarms and paranoid about the silent failures: the replication slot quietly filling a disk, the autovacuum that stopped keeping up two weeks ago.

## Getting started

Tell us what you run and what woke you up last week. A person answers, not a sales sequence.

[Get at monitoring assessment](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/services/advanced-monitoring-solutions/)

---

# About

> North America's oldest PostgreSQL & open source provider since 1997. Full-stack expertise: database, Linux, Python, Ruby, Ansible. Serving companies of all sizes that want first-class PostgreSQL support.

## About Command Prompt

Command Prompt, Inc. is the oldest dedicated Postgres support provider in North America. Since 1997, we have been developing, supporting, deploying and advocating the use of the World's Most Advanced Open Source Database. We are an Oregon corporation who enjoys the benefits of no outside investors, no debt, and being profitable, since our first day of business in 1997.

## Success Stories and Case Studies

We document our case studies and success stories for potential clients. We want you to know the real facts about who we are and what we can do for you.

[Read more](</about/success-stories-case-studies/>)

## Facts about Command Prompt

1

We only provide services around and for Postgres. It is our technical love and passion. No company has made Postgres their sole priority longer.

2

Started in 1997, we are the oldest and most experienced Postgres company with a client and team member retention that is second to none.

3

We have a strong and growing customer base, residing in all current demand markets including FinTech, HealthTech, EdTech and Gaming.

4

We have a very strong relationship with the People, Postgres, Data community. Providing leadership and critical support services to that community.

5

As a private corporation, with no outside investors, we are only accountable to our families and our clients. When you call Command Prompt, you are greeted by knowledgeable staff who are trained and have experience with Postgres and the environments that Postgres operates with.

## Meet the team

We have a fantastic team that strives to provide white-glove service to every client, big and small.

[Our Team](</about/our-team/>)

## Ready for PostgreSQL success?

Let's get on the phone and have a human-to-human conversation.

[Request a Call](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/about/)

---

# Support Options

> Postgres and Open Source Support form the Leader in the Industry

## Support Options

Your partner in Postgres and Open Source support and consulting. All of our options enable the use of consulting and/or 24x7 support. Find a refreshing experience in working with best in class professionals. [Contact us today](</contact-us/>) and have a refreshing partnership experience with the success of your technical projects.

## Support and Consulting Options

![On-Demand](/media/images/ondemand.height-300.format-webp.webp)

## On-Demand

On-Demand or ad-hoc consulting available to any potential client with the execution of a services agreement. Rates are variable based on time, day and severity. As with all of our offerings, we offer consulting and support on Postgres and other Open Source technologies.

[Get On-Demand](</support/>)

![Service Level Agreement](/media/images/sla.height-300.format-webp.webp)

## Service Level Agreement

An comprehensive enterprise wide option with an **SLA, 24x7x365 response** and a fixed rate. Partners wishing for known costs, known response times, and flexible full stack support should chose this option.

[Get Service Level Agreement](</support/>)

![Proactive SLA](/media/images/proactive.height-300.format-webp.webp)

## Proactive SLA

Our most popular Support and Consulting subscription that includes an Proactive Response, SLA, 24x7x365 response, intimate knowledge of your production and development requirements. It also enables the optional " **Best In Industry** " Proactive Monitoring. If you want a team of experts and predictive costs this is your option. The Proactive SLA provides industry leading service from the only white glove service firm in the full stack Postgres market.

[Get Proactive Support](</support/>)

---
[View this page online](https://www.commandprompt.com/about/support-options/)

---

# Success Stories: Case Studies

> Dozen's of case studies and success stories surrounding PostgreSQL deployments with Command Prompt.

# Success Stories: Case Studies

The truth behind 3 decades of experience with Postgres and Open Source

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

## Healthtech / Health Care

  * [The 5 TB Data Diet: Shrinking a Database Until It Fit Its New Cloud](</about/success-stories-case-studies/the-5-tb-data-diet-shrinking-a-database-until-it-fit-its-new-cloud/>)
  * [Eighteen Years on Call: From PostgreSQL 8.1 to 17, and a Nine-Minute Report Cut to 30 Seconds](</about/success-stories-case-studies/eighteen-years-on-call-from-postgresql-81-to-17-and-a-nine-minute-report-cut-to-30-seconds/>)
  * [The Migration the Monitoring Could Not See: PostgreSQL 11 to AlloyDB, Live](</about/success-stories-case-studies/the-migration-the-monitoring-could-not-see/>)
  * [Won on Features, Kept on Plumbing: Fifteen Years of Enterprise Identity Federation Behind a National Medical-Coding Platform](</about/success-stories-case-studies/fifteen-plus-years-as-the-full-stack-engineering-partner-behind-a-national-medical-coding-platform/>)
  * [From Zero Backups to a Safety Net Under a Live EMR](</about/success-stories-case-studies/from-zero-backups-to-a-safety-net-under-a-live-emr/>)
  * [From Unrecoverable to Under Control: Taming Multi-Tenant PostgreSQL at 17,000 Schemas](</about/success-stories-case-studies/from-unrecoverable-to-under-control-taming-multi-tenant-postgresql-at-17000-schemas/>)



## Fintech and Financial

  * [Two Hours, Zero Surprises: Retiring End-of-Life PostgreSQL Inside a Bank's Change Window](</about/success-stories-case-studies/two-hours-zero-surprises-retiring-end-of-life-postgres-inside-a-banks-change-window/>)
  * [Thirteen Minutes on a Saturday: Disaster Recovery a Hedge Fund Can Actually Trust](</about/success-stories-case-studies/thirteen-minutes-on-a-saturday-disaster-recovery-a-hedge-fund-can-actually-trust/>)
  * [One Outage, Zero Recurrences: Retiring PostgreSQL's Hidden Capacity Limits at a Global Financial Services Firm](</about/success-stories-case-studies/one-outage-zero-recurrences-retiring-postgresqls-hidden-capacity-limits-at-a-global-financial-services-firm/>)
  * [Audit Data Grows Forever. The Databases Stopped Growing With It: Partitioning, Archiving, and Upgrading a Core-Banking Fleet](</about/success-stories-case-studies/audit-data-grows-forever-the-databases-stopped-growing-with-it-partitioning-archiving-and-upgrading-a-core-banking-fleet/>)
  * [From Weeks to 0.8 Seconds: Planner Engineering at Billions of Rows](</about/success-stories-case-studies/from-weeks-to-08-seconds-planner-engineering-at-billions-of-rows/>)



## Contact Us

Reach out! We would love to connect and explore how we can partner for your PostgreSQL and Open Source success.

[Learn More](</contact-us/>)

## General Industries

  * [Restored to the Millisecond: An 18 TB Point-in-Time Recovery, Straight Through an Unreleased PostgreSQL Bugfix](</about/success-stories-case-studies/restored-to-the-millisecond-an-18-tb-point-in-time-recovery-straight-through-an-unreleased-postgresql-bugfix/>)
  * [Breaking the 20 TB Ceiling: A Zero-Data-Loss Exit from AWS RDS to Self-Managed PostgreSQL](</about/success-stories-case-studies/breaking-the-20-tb-ceiling-a-zero-data-loss-exit-from-aws-rds-to-self-managed-postgresql/>)
  * [240 IDs From the Wall: A Zero-Downtime bigint Rescue for a Two-Billion-Row Table](</about/success-stories-case-studies/ahead-of-the-21-billion-wall-bigint-migrations-delivered-as-pull-requests/>)
  * [Every Emergency Resolved, None Caused by PostgreSQL: Fifteen Years Running the Full Stack for a Vacation-Rental Marketplace](</about/success-stories-case-studies/case_study_emergency_resolved_none_by_postgres/>)
  * [Fifteen Years, Seven Emergencies, Zero Data Loss: Managed PostgreSQL Behind a Major Public Library Catalog](</about/success-stories-case-studies/fifteen-years-seven-emergencies-zero-data-loss-managed-postgresql-behind-a-major-public-library-catalog/>)

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/)

---

# The 5 TB Data Diet: Shrinking a Database Until It Fit Its New Cloud

> You cannot lift-and-shift what you refuse to clean up. A database that has grown for a decade carries everything: mail logs nobody queries, indexes nobody uses, history nobody reads but everybody is afraid to delete. The migration deadline turned that comfortable clutter into a blocker. Either the database lost terabytes, or the platform stayed where it was.

# The 5 TB Data Diet

Shrinking a Database Until It Fit Its New Cloud

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Post-acute care technology (home-care SaaS)
  *  **Organization:** A leading U.S. post-acute-care technology company whose home-care platform coordinates daily care at national scale
  *  **Environment:** Self-managed PostgreSQL on AWS EC2, migrating to Google Cloud on local NVMe storage
  *  **Engagement:** Proactive DBA managed services
  *  **Services:** Cloud-to-cloud migration, Data lifecycle engineering , Proactive audits, 24×7 incident response



Metric  |  Before  |  After   
---|---|---  
Mail-activity log data living in PostgreSQL  |  4.89 TB (3.37 TB + 1.52 TB)  |  0 (offloaded to S3 and DynamoDB)   
Database size after the mail-log offload  |  11.7 TB  |  6.81 TB   
Fit against the new cloud's 9 TB local-NVMe ceiling  |  Over the limit  |  8.2 TB proven in test; production cut over   
186 High and Emergency tickets resolved  |  186 raised  |  186 resolved   
Results at a glance

## Contact Us

Reach out! This is your best opportunity to build a partnership with a leader in Postgres and Open Source support.

[Learn More](</contact-us/>)

## The Client

The client's platform: home care for agencies across the United States. Every shift schedule, every caregiver clock-in, every visit note and message between an agency and a family lands in one PostgreSQL database. When that database is slow, a coordinator cannot see who is standing in a patient's kitchen this morning. When it is down, care stops being coordinated at national scale.

## The Challenge

The client decided to move the platform from AWS to Google Cloud. The plan called for local NVMe storage, with one hard limit: the local disk array topped out at 9 TB. The production database was well past it.

You cannot lift-and-shift what you refuse to clean up. A database that has grown for a decade carries everything: mail logs nobody queries, indexes nobody uses, history nobody reads but everybody is afraid to delete. The migration deadline turned that comfortable clutter into a blocker. Either the database lost terabytes, or the platform stayed where it was.

## The Solution

  * **Move the mail out.** Two log tables held 3.37 TB and 1.52 TB including indexes, nearly 5 TB of message history inside a transactional database. The history went to S3, live traffic went to DynamoDB. The database size reduced from 11.7 TB to 6.81 TB in one weekend.
  *  **Archive the history.** Ahead of the cutover we built a retention program: copy the current year of high-churn tables into new lean tables and ship the older data to Redshift where the analytics team could still reach them.
  *  **Drop the dead weight.** We verified indexes across every stack, primary, read, worker, and reporting. Then we dropped them CONCURRENTLY and production never noticed.
  *  **Tier the cold data.** After the move, we kept the NVMe volume lean by relocating cold tables to slower, cheaper disk in planned phases, using pg_repack during low-traffic windows.



Proactive discipline paid off elsewhere. During a routine audit we found four-byte integer primary keys quietly running out. The worst was at 2,029,172,512 of a maximum 2,147,483,647, filling at 15 inserts per second. Ninety-one days to overflow on a table with two billion rows. We migrated the columns to eight-byte integers using live mirror tables, with no downtime, long before the deadline arrived.

## The Results

The production database left AWS and landed on Google Cloud local NVMe. The cutover went to plan. The client's reliability team reported the site online and stable afterward, with no major database incident.

 _"Thank you for the successful production cutover this weekend. Our site has been online, stable, and without major incident." (Client)_

## Why it Matters

Every cloud migration plan starts with the destination and works backward to the data. The data usually loses. This engagement proves the reverse order works: decide what actually belongs in your transactional database, move the rest to storage built for it, and the migration you thought was impossible becomes a maintenance window.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/the-5-tb-data-diet-shrinking-a-database-until-it-fit-its-new-cloud/)

---

# Eighteen Years on Call: From PostgreSQL 8.1 to 17, and a Nine-Minute Report Cut to 30 Seconds

> In 2008 it was autovacuum failing to keep up on PostgreSQL 8.1. In the early 2010s it was uptime: the platform needed real high availability and point-in-time recovery, not a single box and a prayer. In 2013 it was a production-down emergency, submissions failing with a numeric-overflow error nobody could explain. In 2021 it was a cloud upgrade gone wrong: an RDS jump from 9.6 to 13, performed without us, left the production database nearly unusable. And in 2026 it was speed at the finish line of a 13-to-17 upgrade: the company set a goal that every custom client report return in under one minute, and the worst one took more than nine.

# Eighteen Years on Call

From PostgreSQL 8.1 to 17, bringing a client current

[ Learn More ](</contact-us/>) [ Get Support ](</support/postgres-support/>)

* **Industry:** Clinical-trial medical imaging (life sciences technology)
  *  **Organization:** A clinical-trial imaging network provider whose platform moves trial images between hospitals and sponsors
  *  **Environment:** Self-managed PostgreSQL and AWS RDS across the engagement; currently PostgreSQL 17 in production
  *  **Engagement:** PostgreSQL support and consulting, ongoing since April 2008 (18 years, 134 tickets)
  *  **Services:** Major-version upgrades · Performance engineering · High availability & PITR · Emergency incident response



Metric  |  Before  |  After   
---|---|---  
Slowest client-facing QC report  |  9+ minutes on PostgreSQL 13  |  ~30 seconds on PostgreSQL 17 after our rewrite (18x)   
Payment report  |  ~4 minutes on PostgreSQL 13  |  ~1.5 minutes on PostgreSQL 17   
PostgreSQL major version  |  13  |  17, live in production February 2026   
Results at a Glance

## Contact us

Reach out! This is your best opportunity to build a partnership with a leader in Postgres and Open Source support.

[Learn More](</contact-us/>)

## The Client

The client runs a clinical-trial imaging network. When a hospital scans a trial patient, the platform carries that image to the trial sponsor, with the chain of custody a regulated study demands. PostgreSQL sits under all of it: the submissions, the audit trail, the reports sponsors read. A slow database is a slow trial. They have been our client since April 2008.

## The Challenge

The challenge changed every few years, which is the point of this story. In 2008 it was autovacuum failing to keep up on PostgreSQL 8.1. In the early 2010s it was uptime: the platform needed real high availability and point-in-time recovery, not a single box and a prayer. In 2013 it was a production-down emergency, submissions failing with a numeric-overflow error nobody could explain. In 2021 it was a cloud upgrade gone wrong: an RDS jump from 9.6 to 13, performed **without us** , left the production database nearly unusable. And in 2026 it was speed at the finish line of a 13-to-17 upgrade: the company set a goal that every custom client report return in under one minute, and the worst one took more than nine.

## The Solution

We solved each era's problem as it arrived.

  *  **Foundation and forensics.** We tuned vacuum and maintenance and pushed the upgrade path forward. When a high-churn table kept growing despite aggressive vacuuming, we traced the free-space accounting instead of guessing.
  *  **High availability.** We built their DRBD and corosync failover stack, reconfigured it as the platform grew to multiple PostgreSQL instances, and put point-in-time recovery underneath it.
  *  **The 2013 emergency.** Image submissions were failing with "numeric value out of range". We traced it the same day: large-object IDs are unsigned 32-bit values, and a signed 32-bit cast in the application stack turned any ID past 2.1 billion into garbage.
  *  **Security design.** Over several years we designed and tuned the row-level-security policies that keep one sponsor's trial data invisible to another, including the complex-join policies and the performance work to make them affordable.



## The Results

The QC report went from 9+ minutes to roughly 30 seconds, an 18x improvement, and the payment report from 4 minutes to 1.5. PostgreSQL 17 went live in production in February 2026 with our engineers on the tickets before and after cutover. Eleven emergencies over the years, all resolved. And a platform that started on PostgreSQL 8.1 is now on 17 without ever losing its database along the way.

## Why it Matters

Nobody at Command Prompt had to be told what this database does, how the imaging workflow behaves under load, or why the row-level-security policies look the way they do. We wrote that history, and we were still here to use it. Eighteen years is not a vendor relationship, it is a partnership.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/eighteen-years-on-call-from-postgresql-81-to-17-and-a-nine-minute-report-cut-to-30-seconds/)

---

# The Migration the Monitoring Could Not See

> The destination was clear: AlloyDB, Google's managed PostgreSQL-compatible service on a PostgreSQL 15 engine. The path was not. The vendor-recommended migration tooling had stalled. Replication slots grew during incremental sync without explanation, the procedure kept sprouting workarounds, and the estimate for the initial production sync stood at more than two weeks. Two weeks of retained WAL on a busy production primary is not a plan. It is a countdown.

# PostgreSQL 11 to AlloyDB, Live

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Post-acute care technology (home care)
  *  **Organization:** A leading U.S. post-acute-care technology company whose home-care platform coordinates daily care at national scale
  *  **Environment:** PostgreSQL 11 on GCP VMs migrating to AlloyDB (PostgreSQL 15 compatible); PgBouncer; native logical replication
  *  **Engagement:** Migration engineering and hands-on DBA support
  *  **Services:** Cloud database migration · Logical replication engineering · Incident response



Metric  |  Before  |  After   
---|---|---  
Initial production data sync  |  14+ days estimated on the stalled path  |  Nearly 6 TB in under 48 hours with native logical replication   
First region initial sync  |  Expected around 12 hours  |  Under 7 hours using three parallel replication streams   
Production cutover impact  |  Live platform, thousands of agencies  |  Monitoring showed no change in throughput or response time   
Mid-migration slot backlog  |  170 GB of WAL queued on one slot  |  Fixed and drained to kilobytes the same day   
  
## Contact Us

Reach out! We would love to hear from you.

[Learn More](</contact-us/>)

## The Client

The client's home-care coordination platform decides who knocks on whose door. Every morning, agencies across the country open it to schedule visits, match caregivers to clients, and bill for care delivered. All of that sat on PostgreSQL 11, self-managed on cloud VMs with an aging operating system. ]

## The Challenge

The destination was clear: AlloyDB, Google's managed PostgreSQL-compatible service on a PostgreSQL 15 engine. The path was not. The vendor-recommended migration tooling had stalled. Replication slots grew during incremental sync without explanation, the procedure kept sprouting workarounds, and the estimate for the initial production sync stood at more than two weeks. Two weeks of retained WAL on a busy production primary is not a plan. It is a countdown.

And the platform could not stop. Agencies schedule real people into real homes every day. The migration had to happen underneath them, with a rollback path open at every step.

## The Solution

  * **Proof of concept.** We replicated the full application database from PostgreSQL 11 to AlloyDB, synchronized sequences, then flipped replication and streamed changes back. The client updated live records through the UI, routed through PgBouncer to AlloyDB, and watched the changes land. The rollback path was real before production was touched.
  *  **Staged routing through PgBouncer.** Application traffic already flowed through PgBouncer, so moving the platform meant changing where PgBouncer pointed, not redeploying the application. Each region cut over in three phases: establish replication, route reporting and worker reads to AlloyDB, then flip the primary.
  *  **Rehearsal.** We flipped replication back and forth in staging until the client's SRE could drive a flip solo from the runbook. We restored an AlloyDB backup to a fresh cluster and documented the disaster-recovery takeaways. A backup you have never restored is a hope, not a plan.
  *  **Respect for production.** The first sync attempt in the larger region delayed the streaming replicas, so we aborted, re-planned, ran a targeted vacuum freeze, and split the biggest tables into their own scheduled syncs. The second attempt moved nearly 6 TB in under 48 hours with replication delay held in milliseconds; a 3 TB table followed in 11 hours.



## The Results

Both production regions cut over on schedule. The first region's final cutover went cleanly on a Friday night, and the client's monitoring showed no week-over-week change in throughput or response time.

The client kept more than a new database. They kept the runbooks, the replication scripts, the schema-check procedure that catches DDL drift before it breaks a slot, and an SRE team that had flipped replication themselves.

 _"This was a huge milestone. We could not have done this without you." (Client)_

## Why it Matters

Migration vendors sell certainty and ship complexity. PostgreSQL ships logical replication in the box. When the shiny tool stalls, the boring and reliable built-in is sitting right there, already documented, already understood by the engine on both ends. Ask what your database can do before you ask what you can buy.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/the-migration-the-monitoring-could-not-see/)

---

# Fifteen-Plus Years as the Full-Stack Engineering Partner Behind a National Medical-Coding Platform

> Most consultancies are handed a database. This client handed us the entire platform: hosting, application development, authentication, search, monitoring, and the regulatory data pipeline.
The original stack, Apache fronting a JBoss/Java application, was showing its age. Application crashes were being band-aided with scheduled nightly restarts. Connection-pool exhaustion periodically blocked all logins. Un-rotated logs filled disks and took servers down. Quarterly regulatory data loads (Medicare fee schedules and code-set updates) were manual and error-prone, occasionally requiring emergency hand-entered corrections from late-breaking federal bulletins. Meanwhile the platform lived on aging bare-metal hardware whose RAID arrays, NICs, and power supplies were beginning to fail. In healthcare, every one of those risks converts directly into clinicians who cannot code and claims that cannot bill.

# Every Emergency Resolved

Fifteen-Plus Years: the Full-Stack Engineering Partner Behind a National Medical-Coding Platform

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Healthcare IT (medical-coding reference and billing software)
  *  **Organization:** A healthcare-IT publisher whose medical-coding software is used by clinicians and billing teams nationwide
  *  **Environment:** Python web application on PostgreSQL with LDAP/SAML single sign-on and full-text search, dual-site high-availability clusters in two US data centers, now running on Google Cloud Platform
  *  **Engagement:** Full-stack hosting, development, and managed operations, client since 2010
  *  **Services:** Application development · Managed hosting & HA · PostgreSQL operations · 24×7 incident response



1,227 of 1,227 Emergency- and High-priority issues resolved: a 100% closure rate across roughly 2,850 tickets   
---  
9 of 12 production emergencies resolved the same day they were opened   
Zero customer downtime through real RAID, NIC, and power-supply hardware failures, absorbed by dual-site failover   
Complete re-platform from legacy Java/JBoss to Python + PostgreSQL, delivered through a clean cutover with no user disruption   
Annual incident-and-request volume down from a peak of ~780 tickets to under 25: a platform that now largely runs itself   
Results at a Glance

## Contacts Us

Reach out and let's build a partnership around Postgres and Open Source!

[Learn More](</contact-us/>)

## The Client

The client is a healthcare-IT publisher whose medical-coding reference product is consulted daily by clinicians and billing teams nationwide to select and validate procedure, diagnosis, and fee-schedule codes. The same platform powers white-label editions for major healthcare organizations, including a national health insurer. An outage does not inconvenience one company. It stalls coding and claims workflows across many. PostgreSQL is the system of record for the code sets, quarterly Medicare fee data, and licensing entitlements the entire product depends on.

## The Challenge

Most consultancies are handed a database. This client handed us the entire platform: hosting, application development, authentication, search, monitoring, and the regulatory data pipeline.

The original stack, Apache fronting a JBoss/Java application, was showing its age. Application crashes were being band-aided with scheduled nightly restarts. Connection-pool exhaustion periodically blocked all logins. Un-rotated logs filled disks and took servers down. Quarterly regulatory data loads (Medicare fee schedules and code-set updates) were manual and error-prone, occasionally requiring emergency hand-entered corrections from late-breaking federal bulletins. Meanwhile the platform lived on aging bare-metal hardware whose RAID arrays, NICs, and power supplies were beginning to fail. In healthcare, every one of those risks converts directly into clinicians who cannot code and claims that cannot bill.

## The Solution

We executed a multi-year modernization program while operating the production platform without interruption:

  *  **Re-platformed the application** from JBoss/Java to Python on PostgreSQL: schema normalization, a rebuilt fee-calculation engine validated by roughly 120 passing test cases, an integration API, and full-text search. Alpha releases went to customer testers before a clean legacy-to-modern cutover. The old login path redirected transparently, and a final legacy data update extended more than 1,500 expiring user accounts so no one fell through the gap.
  *  **Delivered enterprise SSO** for the national-insurer edition: SAML/Shibboleth federation with browser-matrix testing and a fallback login path. After a provisioning defect caused an access outage, we hardened attribute synchronization and put annual certificate renewals on a routine cadence.
  *  **Built and battle-tested high availability** : dual-site clusters with documented, rehearsed failover procedures and a quorum observer node added with no downtime. When hardware actually failed (a degraded RAID array, a failing NIC, a dead power supply), each event was absorbed by failover, including a power-supply replacement performed with zero downtime against a pre-synced standby.
  *  **Matured operations** : centralized logging with one-year retention and automated pgBadger reports, fleet-wide NTP, a fleet-wide unused-index cleanup shipped as a tagged release, session-limit enforcement added after a login-storm incident, same-day mitigation of an abuse run that hit one endpoint with ~570,000 requests in a day (versus ~3,000 normal), prompt responses to industry security events, and proactive PostgreSQL version advisories.
  *  **Migrated the platform to Google** , retiring the bare-metal footprint and moving backups to cloud snapshots. That quietly ended years of recurring storage-capacity and backup-failure churn.



## The Results

Across more than fifteen years and roughly 2,850 tickets, every Emergency and every High-priority issue, 1,227 in all, was resolved, with 9 of 12 emergencies closed the same day. Hardware failures that would have meant outages elsewhere produced zero customer downtime.

The clearest evidence the modernization worked is the ticket curve itself. Annual volume fell from a peak of about 780 during the build years to fewer than 25 today, with no open incidents: a mature platform in inexpensive steady-state operation. The relationship keeps compounding. In the engagement's second decade, the client began onboarding another major healthcare organization onto a new white-label edition of the platform we built and run.

## Why it Matters

A database consultancy that can also design, build, host, and operate the application around the database changes the economics of a niche software product. The publisher keeps its focus on content and customers while a single accountable partner owns the full stack. The proof is longitudinal: declining ticket volume, emergencies that close the day they open, hardware failures nobody notices.

That is the difference between a break-fix vendor and a partner. One shows up when things break. The other makes sure you stop noticing.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/fifteen-plus-years-as-the-full-stack-engineering-partner-behind-a-national-medical-coding-platform/)

---

# From Zero Backups to a Safety Net Under a Live EMR

> They were right. We assessed the colocation estate and found one host running five PostgreSQL clusters across three different major versions, each with a different backup configuration, and not one of them working. The most recent local copies were stale by months. On the warehouse cluster there was a large WAL archive with no base backup behind it, which is a pile of receipts for a purchase that was never made. On the core EMR server, every backup was failing, and a cleanup script was deleting WAL files after 14 days whether they had been archived or not.

# From Zero Backups

To a Safety Net Under a Live EMR

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Healthcare technology (hospice and palliative-care EMR)
  *  **Organization:** The hospice and palliative-care division of a leading U.S. post-acute-care technology company
  *  **Environment:** Self-managed PostgreSQL in a colocation datacenter, migrating to Google Cloud (Cloud SQL, GKE, PgBouncer)
  *  **Engagement:** Proactive DBA managed services,
  *  **Services:** Backup and recovery · Health assessment · Migration support · Disaster recovery planning



Outcome   
---  
Five production clusters across three PostgreSQL versions, none with a working backup, all moved to pgBackRest with backups stored in Google Cloud Storage   
135 GiB of unarchived WAL on one compliance-critical database found and drained roughly 48 days before the volume would have filled   
Zero-downtime EMR migration to GCP completed in November 2023 with our team reviewing the plan and standing by through the cutover   
Post-cutover connection pooling and long-running transaction reviews on the production EMR database   
Disaster recovery runbooks written and restore procedures tested against a dedicated DR project   
Results at a glance

## Get in touch

This is your chance to connect with a company that values you as a partner!

[Learn More](</contact-us/>)

## The Client

The client runs the electronic medical record for hospice and palliative care providers across the United States. Nurses chart against this database at the bedside. Medication records, care plans, and compliance audit trails all live in PostgreSQL, and all of it is PHI under HIPAA. When they engaged us, the production estate still ran in a colocation datacenter, months away from a planned migration to Google Cloud.

## The Challenge

The client told us something most companies never say out loud: assume we have no backups. They asked us to prove them wrong.

We couldn't. We assessed the colocation estate and found one host running five PostgreSQL clusters across three different major versions, each with a different backup configuration, and not one of them working. The most recent local copies were stale by months. On the warehouse cluster there was a large WAL archive with no base backup behind it, which is a pile of receipts for a purchase that was never made. On the core EMR server, every backup was failing, and a cleanup script was deleting WAL files after 14 days whether they had been archived or not.

The worst of it sat on one compliance-critical database. WAL archiving was broken both locally and to its remote target. 135 GiB of unarchived WAL had piled up, the archive volume could not hold it, and no base backup existed anywhere we could find. At the observed WAL rate, the data volume was about 48 days from full. Not a hypothetical. A date on a calendar.

## The Solution

We built the safety net first and argued about architecture later.

  * We inventoried every cluster's backup and archiving state and documented it, so the gap was visible instead of assumed.
  * We implemented pgBackRest across the estate, archiving WAL and shipping compressed backups to Google Cloud Storage buckets, out of the colocation facility entirely. We sequenced the rollout by risk: the compliance-critical database first, the core EMR last only because it needed access and disk planning, not because it could wait.
  * We drained the unarchived WAL backlog once real backups existed to replace it, and wired backup status into the client's monitoring so a silent failure could never accumulate for months again.
  * The migration itself was led by the client's cloud partner. Our job was the net under it. We reviewed their zero-downtime migration documentation with multiple engineers, consulted on memory and parallelism settings in the final hours before cutover, and kept an engineer on call through the November migration weekend. The cutover completed without needing us. That is the goal.
  * After cutover we stayed on: we reviewed the PgBouncer deployment fronting the production EMR on Cloud SQL, backed the change from one pod to three, monitored the deploy, and ran proactive reviews of long-running and heavyweight transactions.
  * We moved from safety net to fire drill: disaster recovery runbooks for backup identification and restoration, tested against a dedicated DR project.



## The Results

Every production cluster went from zero restorable backups to pgBackRest backups in cloud storage, verified and monitored. The disk that had 48 days left never filled. The EMR moved to GCP without downtime, and the client kept us on afterward for pooling, transaction hygiene, and disaster recovery planning.

## Why it Matters

Nobody plans to have no backups. It happens one broken cron job at a time, while the green dashboards stay green. The only way to know is to go look, cluster by cluster, before the disk does the audit for you. Find the hole before it finds you.

A WAL archive with no base backup is a hope, not a plan.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/from-zero-backups-to-a-safety-net-under-a-live-emr/)

---

# From Unrecoverable to Under Control: Taming Multi-Tenant PostgreSQL at 17,000 Schemas

> A national employee-benefits administration provider runs its entire business on a single PostgreSQL cluster. Its benefits-administration platform gives every client company a schema of its own: roughly 17,000 to 19,000 identically structured schemas in one database, a schema-per-tenant architecture at a scale most teams never encounter. The data is HIPAA-regulated, the platform is the system of record for benefits processing, and the cluster is self-managed PostgreSQL 11 on Azure virtual machines, with no managed-cloud safety net underneath it.

# From Unrecoverable to Under Control

Taming Multi-Tenant Postgres with 17,000 Schemas

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Employee benefits administration (HIPAA-regulated)
  *  **Organization:** A national employee-benefits administration provider (HIPAA-regulated)
  *  **Environment:** Self-managed PostgreSQL 11 on Azure VMs (primary + streaming replica), pgBackRest to Azure storage, Zabbix + pgBadger monitoring
  *  **Engagement:** Proactive DBA managed services, client since 2024, an engagement that began as an inbound emergency
  *  **Services:** Backup & disaster recovery · Autovacuum and catalog-scale tuning · Monitoring build-out · Cost optimization



Outcome   
---  
Unrecoverable primary database fully recovered; disaster recovery now validated end-to-end, with a full restore completing in roughly 90 minutes (parallel restore plus WAL catch-up)   
~$3,600/month of orphaned backup storage identified for elimination, and a retention policy designed for a backup set that had grown past 12 TB   
19 of 19 high-priority issues resolved (100%), with zero emergency-priority incidents since onboarding   
Application-down autovacuum blocking incident resolved with no recurrence, and vacuum capacity re-tuned for a catalog spanning ~17,000 tenant schemas   
Results at a glance

## Get in touch

We would love to hear from you! Let us become your new partner in Postgres and Open Source.

[Learn More](</contact-us/>)

## The Client

A national employee-benefits administration provider runs its entire business on a single PostgreSQL cluster. Its benefits-administration platform gives every client company a schema of its own: roughly 17,000 to 19,000 identically structured schemas in one database, a schema-per-tenant architecture at a scale most teams never encounter. The data is HIPAA-regulated, the platform is the system of record for benefits processing, and the cluster is self-managed PostgreSQL 11 on Azure virtual machines, with no managed-cloud safety net underneath it.

## The Challenge

The client first reached us as a non-customer, mid-emergency. A backup had failed, and repeated restore attempts were stalling during WAL replay with corrupt-record errors. The primary database, and the benefits data of 17,000+ tenants with it, was effectively unrecoverable. The root cause was a fragile, hand-rolled rsync-based restore process layered on an Azure storage account whose hierarchical-namespace setting was silently incompatible with pgBackRest.

The emergency exposed the deeper problem: almost nothing about standard PostgreSQL operations survives contact with 17,000 schemas unmodified. The system catalog is enormous, so maintenance jobs that iterate every tenant object can balloon lock-manager memory. Autovacuum, tuned for a normal schema count, falls structurally behind. At one point workers ran so long they blocked transactional queries and brought applications down, and transaction-ID age later drifted to roughly 292 million before monitoring flagged it for a managed freeze plan. Backups had swollen past 12 TB with no retention policy. An orphaned legacy storage account was burning about $3,600 per month for nothing. The application connected as superuser with no pooler, periodically exhausting reserved connection slots. All of it on an end-of-life PostgreSQL 11.

## The Solution

We followed our standard arc: diagnose, stabilize, fix root causes, then automate so problems never recur.

  *  **Rescue and rebuild the backup pipeline.** We rebuilt the restore on a properly configured pgBackRest stanza and a new, compatible storage account, recovering the original cluster. We then combined the disaster-recovery test with building a streaming replica, validating restorability and adding high availability in one motion. The full restore completed in about an hour of parallel restore plus half an hour of WAL catch-up.
  *  **Stand up real observability.** We built Zabbix monitoring and nightly pgBadger analysis from scratch, including backup-job monitoring that later caught and resolved its first genuine backup failure before the client ever noticed.
  *  **Re-tune vacuum for extreme schema scale.** We right-sized the servers, increased autovacuum worker capacity, resolved the application-down blocking incident without recurrence, and put transaction-ID-age tracking and freeze planning in place as a standing practice rather than an ad-hoc scramble.
  *  **Coach the application at catalog scale.** We diagnosed a cross-schema batch extract whose anonymous DO block was iterating thousands of schemas in a single transaction and exploding lock-manager entries, and we showed the team how to convert it to a procedure that releases locks per object. We delivered the idle-in-transaction monitoring query the client now relies on, and we traced connection exhaustion to superuser application logins.
  *  **Cut waste and plan the future.** We flagged the orphaned ~$3,600/month storage account for deletion, designed retention for the 12 TB backup set, kept security patching current on primary and replica, and delivered an architecture-lifespan review with a schema-consolidation and partitioning design: the modernization path off PostgreSQL 11 and out of the schema sprawl.



## The Results

A database that could not be restored is now protected by a validated, monitored pgBackRest pipeline with a proven ~90-minute recovery path and a warm replica. Every one of the 19 high-priority issues raised across the engagement has been resolved, a 100% record, with zero emergency-priority incidents and no data loss since onboarding. Even an accidental DELETE without a WHERE clause was reversed from backup the same day. Identified savings of roughly $3,600 per month offset a substantial share of the engagement's cost. And the relationship itself is the clearest result: an emergency call from a stranger converted within days into an ongoing proactive managed-services engagement.

## Why it Matters

Schema-per-tenant multi-tenancy is easy to start and brutal to operate at scale. At 17,000 schemas, autovacuum, backups, catalog locks, and upgrades all stop behaving the way the documentation assumes. This engagement shows the pattern that works: stabilize recoverability first, instrument everything, re-tune maintenance for the real catalog size, and fix application behavior at the root. An architecture most teams would call unmanageable becomes a system that simply runs.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/from-unrecoverable-to-under-control-taming-multi-tenant-postgresql-at-17000-schemas/)

---

# Two Hours, Zero Surprises: Retiring End-of-Life Postgres Inside a Bank's Change Window

> The bank was running PostgreSQL 9.3, a release that had been end-of-life for years. No more security patches. No more bug fixes. For a regulated financial institution, that is not a technical debt line item, it is an audit finding waiting to happen.

# Two Hours, Zero Surprises

Retiring End-of-Life Postgres Inside a Bank's Change Window

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Trust banking and financial services
  *  **Organization:** The trust-bank subsidiary of a Fortune 500 financial-services company
  *  **Environment:** Self-managed PostgreSQL on Linux, on-premises, two datacenters
  *  **Engagement:** Project-based PostgreSQL consulting
  *  **Services:** Major-version upgrades · Disaster recovery · Streaming replication



Outcome   
---  
End-of-life PostgreSQL 9.3 upgraded, executed inside a hard two-hour change window, completed exactly per the approved plan   
Every command rehearsed on a production clone before the change-approval board ever saw the runbook   
WAL archiving implemented, closing a disaster-recovery gap we identified proactively   
Cross-datacenter streaming replication with a cascading standby, which carried the bank through its datacenter move and the retirement of the old primary   
Three and a half years of work delivered entirely inside the bank's security perimeter   
Results at a glance

## Get in touch

Find out why after almost 3 decades we are still taking the Postgres and Open Source world by storm.

[Learn More](</contact-us/>)

## The Client

A federally chartered trust bank, the subsidiary of a Fortune 500 title-insurance and financial-services company. Its PostgreSQL databases sit behind the daily movement of client funds, which means every change to them answers to bank-grade change control: a change-approval board, scheduled maintenance windows, and an audit trail for everything.

## The Challenge

The bank was running PostgreSQL 9.3, a release that had been end-of-life for years. No more security patches. No more bug fixes. For a regulated financial institution, that is not a technical debt line item, it is an audit finding waiting to happen.

The obvious fix was not obvious to execute. The change-approval board would grant a hard two-hour window, on a Saturday morning, with a one-hour buffer before the production team needed the system back. There would be no second attempt that day. And all of it had to happen inside the bank's security perimeter: VPN, jump servers, and dedicated laptops the bank shipped to our engineers, locked down with no administrative rights, before we could touch a single server.

Two hours is not much time to jump a database several major versions. Unless nothing about those two hours is a surprise.

## The Solution

The bank stood up a copy of the production server, and we refreshed it from production itself so the rehearsal environment matched the real thing. Then we rehearsed. We installed the new PostgreSQL version, ported the configuration, and turned the entire upgrade into scripts: one to initialize the new cluster, one to run pg_upgrade, with a dry-run check mode that validates compatibility without changing anything. We ran the procedure on the clone, found the surprises there, and fixed the scripts until there were none left.

Only then did we write the production runbook: a numbered plan where every step named its owner. The bank's team would stop the applications and snapshot the VM. Our engineer would receive temporary root access for the window, run the dry-run check, run the upgrade, and hand the system back for the bank's own testing. The bank took that plan through its change-approval board and got the window approved.

On the scheduled Saturday morning, our engineer executed the plan. The upgrade completed inside the window, according to plan, and the ticket closed two days later with nothing left to say.

The relationship did not stop there. We identified that the cluster was not archiving WAL, a gap that put disaster recovery at risk, and implemented archiving the same way: tested first, then walked through production step by step with the bank's administrator confirming each one. We built streaming replication from the primary to a second datacenter, with a cascading standby behind it. That replication carried the bank's databases through its datacenter move, and the old primary was retired a month later.

## Why it Matters

Regulated environments do not reward heroics. They reward procedures that survive a change-approval board and finish inside the window, every time. In a shop like that, the deliverable is not the upgrade. It is the certainty. A rehearsed runbook is certainty you can schedule.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/two-hours-zero-surprises-retiring-end-of-life-postgres-inside-a-banks-change-window/)

---

# Thirteen Minutes on a Saturday: Disaster Recovery a Hedge Fund Can Actually Trust

> Most disaster recovery plans are documents. Nobody has restored from the backups. Nobody has promoted the replica. The plan is fiction with a table of contents.
This client did not want fiction. When we started in 2022, they asked us to review the backup and recovery posture of a 10TB PostgreSQL 12 estate and tell them the truth. The truth had rough edges. The pgBackRest topology had configuration drift across hosts. A weekly full backup eventually stretched to 65 hours on a database that had quietly grown past 9TB, eating into Monday-morning performance. And the firm had suffered out-of-memory outages on the primary that nobody had fully explained.

# Thirteen Minutes on a Saturday

Disaster Recovery a Hedge Fund Can Actually Trust

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Financial services (fixed-income relative-value investing)
  *  **Organization:** A multi-billion-dollar fixed-income hedge fund
  *  **Environment:** Self-managed PostgreSQL 12, roughly 10TB estate, streaming replication to a dedicated DR site, pgBackRest
  *  **Engagement:** PostgreSQL support and DR engineering
  *  **Services:** Disaster recovery engineering · Backup architecture · Weekend incident response · Performance forensics



Outcome  |  Verified result   
---|---  
Response to a Saturday DR emergency (first incident)  |  13 minutes   
Response to a Saturday failover-test failure (second incident)  |  7 minutes   
First incident: reported, recovered, and closed  |  Same Saturday   
Second incident: root cause found and documented  |  Same Saturday, replica rebuild underway before noon   
Written incident report with hardening recommendations  |  Delivered for both incidents   
Results at a glance

## Get treated like a professional

Reach out and join us in a partner for your success!

[Learn More](</contact-us/>)

## The Client

A multi-billion-dollar fixed-income hedge fund. Its trading and analytics workloads live on a PostgreSQL estate of roughly 10 terabytes, and the firm treats that estate the way it treats any other risk: measured, tested, and reviewed. Markets open Monday morning whether the database is ready or not. So the firm does something most companies only claim to do. It rehearses its disaster recovery, on real hardware, on weekends.

## The Challenge

Most disaster recovery plans are documents. Nobody has restored from the backups. Nobody has promoted the replica. The plan is fiction with a table of contents.

This client did not want fiction. They asked us to review the backup and recovery posture of a 10TB PostgreSQL 12 estate and tell them the truth. The truth had rough edges. The pgBackRest topology had configuration drift across hosts. A weekly full backup eventually stretched to 65 hours on a database that had quietly grown past 9TB, eating into Monday-morning performance. And the firm had suffered out-of-memory outages on the primary that nobody had fully explained.

Worse, a DR plan that ambitious creates a new problem: what happens when the rehearsal itself breaks, on a Saturday, with nobody watching?

## The Solution

We built the program in layers, then stood behind it.

  * We reviewed the backup and DR architecture end to end, wrote the disaster recovery plan, and proved it with a point-in-time restore test. Then we stood up a dedicated DR test environment so failover procedures could be developed and validated without touching production.
  * We ran forensics on the OOM outages with pgbadger. The picture was slow memory creep, not one bad query: 332 concurrent sessions before the crash, 567 temp files representing roughly 11GB of potential memory exposure that sessions never released. That forensic detail turned a mystery outage into a tunable configuration.
  * When the full backup hit 65 hours, we benchmarked the storage with bonnie++ and isolated the bottleneck to VM and network throttling, not PostgreSQL, so the fix landed in the right team's queue instead of ours guessing.



Then the rehearsals broke. Twice. Both times on a Saturday morning.

The first time, a DR test left pg_rewind unable to run because the WAL it needed had been removed from the primary. The DR replica was stranded. The client reported it at 8:04 AM. We were responding at 8:17. Thirteen minutes, on a weekend. We pulled the missing WAL from the pgBackRest repository, let the DR host recover through it, and had it streaming from the primary again. The ticket opened and closed on the same Saturday.

The second time, four months later, reversing a failover test failed for a subtler reason: after promotion, PostgreSQL recycles WAL almost immediately, and archive_mode was off on the replica, so the files pg_rewind needed were simply gone. Reported at 9:39 AM. Responding at 9:46. Seven minutes. We diagnosed the root cause, started a pg_basebackup rebuild of the replica before noon, and delivered the written root-cause analysis that same day.

## The Results

Every number in the table above traces to the ticket record. But the durable result is what happened after each incident: a written incident report, with specific recommendations, that hardened the next rehearsal. Separate the backup repository from the database hosts. Archive WAL on the replica, not just the primary. Change the test procedure so promotion does not eat the evidence. The second incident was harder to cause than the first because the first one taught us both something.

The relationship outcome says the rest. The client put us through their annual vendor due-diligence review, the same scrutiny they apply to any counterparty. We passed.

## Why it Matters

DR you have not rehearsed is fiction. This client understood that and rehearsed anyway, which took nerve, because rehearsals fail. Rehearsals only count if someone answers when they break. Thirteen minutes, then seven. That is what a tested plan looks like.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/thirteen-minutes-on-a-saturday-disaster-recovery-a-hedge-fund-can-actually-trust/)

---

# One Outage, Zero Recurrences: Retiring PostgreSQL's Hidden Capacity Limits at a Global Financial Services Firm

> First, a production sequence in the EU region reached the maximum value of a 32-bit integer: 2,147,483,647. Every insert that depended on it began failing. A platform that had run flawlessly for years could suddenly accept no new rows. Not from load. Not from storage. Not from a bad deployment. A type chosen at design time had run out of numbers.

# One Outage, Zero Recurrences

Retiring PostgreSQL's Hidden Capacity Limits at a Global Financial Services Firm

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Global financial services (risk & analytics)
  *  **Organization:** Publicly traded, roughly $6B in annual revenue, operations on three continents
  *  **Environment:** AWS RDS PostgreSQL, multi-region (US/EU/APAC), read replicas + logical replication
  *  **Engagement:** Proactive DBA managed services, ongoing since 2022
  *  **Services:** 24×7 incident response · Capacity-limits auditing · Schema migration engineering · Performance tuning



Metric  |  Before  |  After   
---|---|---  
EU-region insert availability  |  Outage: all inserts blocked by a sequence at its INT4 maximum  |  Restored; fleet-wide alerting on any sequence above 80% utilization; no recurrence   
Transaction-ID wraparound exposure  |  Autovacuum silently stalled for a week, XID age climbing toward the wraparound limit  |  Targeted VACUUM FREEZE executed; standing XID-age and autovacuum-health alerts   
INT4→INT8 migration risk  |  Single-statement rewrite of a 1.78-billion-row table ran 6+ hours before being cancelled  |  Batched, reviewed migration program; post-migration plan regressions diagnosed and fixed   
Emergency incident record  |  n/a  |  11 emergencies over the engagement, 100% resolved; mean time-to-resolve 0.9 days, 7 of 11 same-day   
Results at a glance

## Get in touch

Get professional, results proven, full stack support from us!

[Learn More](</contact-us/>)

## The Client

The client is a global financial services firm specializing in risk and analytics. Publicly traded, roughly $6B in annual revenue, running multi-region AWS RDS PostgreSQL across the US, EU, and APAC. Their PostgreSQL estate backs the firm's risk-analytics platforms. The largest tables hold 2.2 billion and 677 million rows, and inserts arrive continuously from screening and matching workloads. When those databases cannot accept writes, risk decisions stop. 

## The Challenge

PostgreSQL has hard numeric ceilings, and they stay invisible until the day you hit them. The firm hit two.

First, a production sequence in the EU region reached the maximum value of a 32-bit integer: 2,147,483,647. Every insert that depended on it began failing. A platform that had run flawlessly for years could suddenly accept no new rows. Not from load. Not from storage. Not from a bad deployment. A type chosen at design time had run out of numbers.

Second, earlier in the engagement, autovacuum on the EU database silently stopped running for a week. With no freezing activity, the age of the oldest unfrozen transaction ID climbed steadily toward PostgreSQL's wraparound threshold, the point at which the database protects itself by refusing new transactions entirely. Nothing was alerting on either failure mode. Sequence exhaustion and XID aging were simply not on anyone's dashboard.

Both are the same class of problem: capacity limits that degrade nothing along the way and then fail absolutely.

## The Solution

We ran our standard arc. Diagnose, stabilize, fix the root cause, then instrument it so it cannot recur silently.

  *  **Emergency diagnosis and stabilization.** For the wraparound near-miss, we found the tables closest to the limit with a reusable XID-age query and ran targeted VACUUM FREEZE on a live call with the client's team, pulling the database back from the threshold. For the sequence outage, we restored EU insert capability the way we have closed every emergency in this engagement: hands-on, until it was done.
  *  **Monitoring the limits themselves.** We added alerting for any sequence above 80% utilization across the estate, plus XID-age tracking and a two-check autovacuum-health alert in the client's existing monitoring platform. That catches both the stall and its consequences.
  *  **An INT4→INT8 migration program.** Our audit identified every near-limit sequence and 32-bit key. We reviewed the client's migration scripts before they ran: a single-statement rewrite of a 1.78-billion-row table was cancelled after six hours and replaced with a batched, resumable approach sized to production reality.
  *  **Taming the plan regressions the fix caused.** Widening key columns changed the planner's math. A join across the firm's two largest tables stopped using its supporting indexes, driving CPU saturation and transaction failures. We diagnosed the regression and restored correct index usage, because a capacity fix that breaks query plans has only moved the outage.



## The Results

The EU insert outage has not recurred anywhere in the estate. Near-limit sequences are now found by an alert, not by a failed insert. The wraparound near-miss became a standing runbook: the XID-age query and freeze procedure were reused on later autovacuum stalls in other regions without incident. Across the full engagement, all 11 emergency incidents have been resolved, with a mean time-to-resolve of 0.9 days and 7 of 11 closed the same day. The relationship has grown year over year, expanding into archiving, partitioning, and major-version upgrade work on the same platforms.

## Why it Matters

Most database monitoring watches performance: CPU, latency, disk. The failures that take a region down without warning live somewhere else, in INT4 keys, sequence maxima, and transaction-ID age. These limits give no gradual signal, so auditing and alerting on them is the only defense. The outage that did happen took a day to fix. The ones that didn't cost only a dashboard.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/one-outage-zero-recurrences-retiring-postgresqls-hidden-capacity-limits-at-a-global-financial-services-firm/)

---

# Audit Data Grows Forever. The Databases Stopped Growing With It: Partitioning, Archiving, and Upgrading a Core-Banking Fleet

> Keep every API request and response, forever, in the same database that posts transactions. That is what the compliance requirement amounted to in practice. The audit tables grew without bound and were swallowing the OLTP databases. Backups got longer. Storage costs climbed on every bank's instance. The tables the regulator cares about most were becoming the tables the database could least afford to carry.

# Audit Data Grows Forever.

The Databases Stopped Growing With It: Partitioning, Archiving, and Upgrading a Core-Banking Fleet

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Financial technology (cloud-native core banking)
  *  **Organization:** A cloud-native core-banking platform serving U.S. financial institutions, one database per bank
  *  **Environment:** AWS RDS PostgreSQL, one database per bank, Multi-AZ, logical replication
  *  **Engagement:** Embedded DBA engineering and migration support, 2019 to 2024
  *  **Services:** Partitioning and archival engineering · Major-version upgrades · Logical replication · 24×7 incident response



Metric  |  Outcome   
---|---  
Stalled migration at the largest bank  |  2TB WAL backlog diagnosed and cleared; replication brought fully in sync   
Fleet major-version upgrade  |  Every per-bank database migrated PG12 to PG14 by scripted logical replication   
Online audit-data retention  |  Bounded at 90 days; older data archived to S3 with restorable manifests   
Full customer outage  |  Reported at 5:25 PM; we were responding by 5:28 PM; resolved by Multi-AZ failover   
Results at a glance

## Get in touch

For 3 decades, we help companies like yours. Partner with us.

[Learn More](</contact-us/>)

## The Client

The client runs a cloud-native core-banking platform for U.S. financial institutions. Every bank on the platform gets its own PostgreSQL database on AWS RDS. That database is the ledger: it posts the transactions, holds the balances, and answers the API calls that banking apps make all day. Regulators require the platform to keep a record of every API request and response it handles.

## The Challenge

Keep every API request and response, forever, in the same database that posts transactions. That is what the compliance requirement amounted to in practice. The audit tables grew without bound and were swallowing the OLTP databases. Backups got longer. Storage costs climbed on every bank's instance. The tables the regulator cares about most were becoming the tables the database could least afford to carry.

And the fleet was aging. Every bank was on soon to be EOL PostgreSQL version, headed toward end of life, and pg_upgrade was not an option on the client's terms. These are banks. Downtime windows are negotiated, short, and per institution. Whatever we built had to work one database at a time, dozens of times, without drama.

## The Solution

We started where the growth was: the audit tables.

  *  **Partitioning on the key the platform already had.** The platform's primary keys were a homegrown GUID that encodes a timestamp. We designed native range partitioning on that key, so every day of audit traffic landed in its own partition, with no schema rewrite of the application's identifiers.
  *  **A day-by-day archive pipeline to S3.** Old partitions are exported as day-sized chunks, each with a manifest carrying the table's schema, so any archived day can be restored programmatically on demand. Scheduling runs through pg_timetable. The working retention agreed with the client's developers: 90 days online, everything older in S3.
  *  **A careful production switch.** Converting live audit tables cannot block live banking. We backfilled the partitioned tables with a throttled, resumable script, tested the pacing against the nightly ETL windows, then met with the client's DBA to perform the final switchover in a scheduled session. It went smoothly, and the bloated originals could finally be dropped.
  *  **A scripted per-bank fleet migration, by logical replication.** With the audit data bounded, the databases were small enough to move. We built and tested the runbook, including a technique that converts an existing binary replica into a logical replica, skipping the expensive initial copy entirely. Each bank cut over in a short scheduled window. For the largest bank we split the rollout into two steps to keep each outage small.
  *  **Rescuing the largest migration.** The largest bank's logical replication stalled with a 2TB backlog of unprocessed WAL. We diagnosed the timeout settings, explained the initial-copy semantics that make logical lag look nothing like binary lag, and identified the real ceiling: RDS write throughput tops out near 250MB per second even with provisioned storage, so two sync workers saturate it and more just burn CPU. Tuned to that reality, the subscriber caught up and the migration completed.



The engagement was not only projects. When a SAN failure at AWS throttled disk IO and took a bank fully offline at 5:25 PM, we were on it by 5:28 PM and restored service by failing over to the Multi-AZ standby.

## The Results

The audit tables stopped being a threat to the OLTP workload. Online retention is bounded at 90 days per bank, the regulatory record lives durably in S3, and any archived day can be brought back with its manifest. The entire per-bank fleet moved from PostgreSQL an about to be EOL to supported version through one scripted, repeatable logical-replication process, including a two-step rollout for the largest institution and a recovery from a 2TB WAL backlog along the way. And when the platform had its worst day, a full customer outage from a storage failure, the gap between their report and our response was three minutes.

## Why it Matters

Regulated data grows forever. Your database should not. The record the regulator requires and the working set the application needs are two different things, and a partition boundary is where you separate them. Bound the online data, archive the rest somewhere cheap and restorable, and every hard thing that follows, upgrades included, gets easier.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/audit-data-grows-forever-the-databases-stopped-growing-with-it-partitioning-archiving-and-upgrading-a-core-banking-fleet/)

---

# From Weeks to 0.8 Seconds: Planner Engineering at Billions of Rows

> The firm had hit a scaling wall on three fronts at once.
First, raw volume. The largest entity-match table had grown to 2.2 billion rows, with a companion table holding another 677 million, and a monitoring-history table had swollen to 1.2 TB: too large to vacuum, index, or alter comfortably, and expensive to keep entirely live.

# From Weeks to 0.8 Seconds

Postgres Planner Engineering at Billions of Rows

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Global financial services (risk & analytics)
  *  **Organization:** Publicly traded, ~$6B annual revenue, operations on three continents
  *  **Environment:** AWS RDS PostgreSQL, multi-region (US/EU/APAC), read replicas + logical replication
  *  **Engagement:** Proactive DBA managed services, ongoing since 2022
  *  **Services:** Performance engineering · Major-version upgrades · Partitioning & data lifecycle · Planner tuning



Metric  |  Before  |  After   
---|---|---  
Monthly finance report runtime  |  Weeks  |  0.8 seconds   
Reports regressed by the Postgres upgrade (CTE inlining)  |  Up to 4× slower  |  Pre-upgrade plans restored   
Monitoring-history table  |  1.2 TB live, unmanageable  |  Archived on a repeatable, online process   
Entity-match tables  |  2.2 billion and 677 million rows, monolithic  |  Date-partitioned with a low-downtime path   
Results at a Glance

## Reach out!

Would love an opportunity to help you with Postgres and Open Source

[Learn More](</contact-us/>)

## The Client

The client is a global financial services firm specializing in risk and analytics. Publicly traded, roughly $6B in annual revenue, running multi-region AWS RDS PostgreSQL across the US, EU, and APAC. Their PostgreSQL estate backs the entity-screening and risk-analytics platforms their customers query around the clock: every match decision, inquiry, and monthly financial roll-up flows through these databases. At this scale, with individual tables past two billion rows, query plans are not an implementation detail. They are the product's response time.

## The Challenge

The firm had hit a scaling wall on three fronts at once.

First, raw volume. The largest entity-match table had grown to 2.2 billion rows, with a companion table holding another 677 million, and a monitoring-history table had swollen to 1.2 TB: too large to vacuum, index, or alter comfortably, and expensive to keep entirely live.

Second, a marquee report in the firm's risk-analytics reporting platform, the monthly finance-cost roll-up, had degraded until it literally took weeks to execute. Month-end reporting was effectively unusable.

## The Solution

We attacked the wall in the order the plans demanded.

  *  **Rewrote the pathological report.** Working from EXPLAIN output on production-scale data, we restructured the monthly finance-cost query so the planner could drive it through indexes instead of repeated scans of billion-row tables. The original test query fell from 8 minutes 50 seconds to **0.8 seconds**. A full production month completed in under five minutes, nearly all of it cold-cache I/O. Down from weeks.
  *  **Executed the major-version migration** as phased cutovers across the EU and US regions, on schedule.
  *  **Diagnosed and fixed the CTE-inlining regressions** the upgrade surfaced. Reports ran up to 4× slower post-upgrade, and a monthly data feed and a heavily-joined match query stopped using their indexes. We traced each one to CTE inlining and plan changes, restored the intended plans with targeted AS MATERIALIZED clauses, and separated true regressions from data-distribution false alarms so application teams weren't chasing ghosts.
  *  **Applied surgical planner tuning:** partial indexes matched to the queries' actual predicates, random_page_cost = 1 to reflect SSD-backed RDS storage and favor index scans, and column-type alignment across environments that took one drifted query from 30 seconds back to interactive speed.
  *  **Built the data-lifecycle machinery:** an online table-trim script and a repeatable archiving process for the 1.2 TB monitoring-history table, plus a date-based partitioning strategy, proven first in a proof of concept, for the 2.2 billion-row and 677 million-row match tables. Future maintenance, archiving, and index builds now get partition-sized units of work.



## The Results

The headline number speaks for itself. A business-critical monthly report went from weeks of runtime to 0.8 seconds, an improvement of roughly six orders of magnitude, and we did it with planner expertise, not hardware. The migration landed across regions with every surfaced plan regression diagnosed and fixed, not worked around blindly. Terabyte-scale tables now have an archiving and partitioning path instead of an unbounded growth curve. The tuning work also left durable assets behind: reusable scripts, partial-index patterns, and planner-configuration standards now applied across the estate. The engagement, continues to grow year over year, and we are now the firm's standing PostgreSQL engineering partner across all three regions.

## Why it Matters

Past a billion rows, throwing hardware at a bad plan stops working. The difference between a seq scan and the right partial index is the difference between weeks and sub-second. And major-version upgrades change planner behavior in documented but easily-missed ways: the teams that cross them safely are the ones who can read a plan, name the regression, and fix it at the source. Deep planner expertise is what turns a scaling wall back into a database.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/from-weeks-to-08-seconds-planner-engineering-at-billions-of-rows/)

---

# Restored to the Millisecond: An 18 TB Point-in-Time Recovery, Straight Through an Unreleased PostgreSQL Bug

> Two complications were waiting. First, the retention window: the one full backup old enough to reach the requested day was a single scheduled prune away from deletion. Second, invisible until mid-restore: the freshly installed PostgreSQL minor release on the restore host carried a regression, at that point unfixed in any released version, that silently deadlocks WAL replay.

# Restored to the Millisecond

An 18 TB Point-in-Time Recovery, Straight Through an Unreleased Postgres bugfix

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** K-12 education technology (analytics & family engagement)
  *  **Organization:** A K-12 education analytics and family-engagement platform serving school districts across the U.S.
  *  **Environment:** AWS EC2: self-managed three-node PostgreSQL 15 cluster, ~20 TB ZFS volumes, pgBackRest full backups + continuous WAL archiving to S3
  *  **Engagement:** Proactive DBA managed services with 24/7 monitoring
  *  **Services:** Backup & disaster recovery · Point-in-time recovery · PostgreSQL internals & root-cause diagnosis · Incident response



Metric  |  Outcome   
---|---  
Recovery precision  |  Replay paused 1.378 milliseconds after the requested target timestamp   
Data restored  |  17.9 TB database, rebuilt from a ~3.3 TB compressed pgBackRest repository in S3   
Restore throughput  |  64 parallel pgBackRest workers, sustained ~120 MB/s to disk   
Turnaround  |  Request to delivered, queryable copy in 8 days, including root-causing an unfixed PostgreSQL bug   
Production impact  |  Zero: the live cluster served schools untouched throughout   
Results at a glance

## Get in touch

We are looking forward to working with you!

[Learn More](</contact-us/>)

## The Client

The client is a K-12 education analytics and family-engagement platform serving school districts across the U.S. Its production PostgreSQL, a self-managed three-node cluster on EC2 with roughly 20 TB of compressed ZFS storage, holds every teacher message, attendance record, and district dashboard the platform serves. We have provided proactive DBA managed services since 2022, including designing and restore-testing the platform's disaster-recovery runbook.

## The Challenge

The client's VP of Engineering opened a ticket with a deceptively simple question: what would it take to restore the database as it stood on a specific day two weeks earlier. At 18 TB, nothing about that is simple. A full copy needs its own 20 TB of provisioned disk, terabytes pulled from S3 and decompressed, and days of wall-clock time, all without touching the production cluster still serving schools.

Two complications were waiting. First, the retention window: the one full backup old enough to reach the requested day was a single scheduled prune away from deletion. Second, invisible until mid-restore: the freshly installed PostgreSQL minor release on the restore host carried a regression, at that point unfixed in any released version, that silently deadlocks WAL replay.

## The Solution

**A same-day answer, from a tested playbook.** Within 72 minutes of the request, we returned the written disaster-recovery plan (built and fully restore-tested in 2024, so transfer-and-recovery timing was already known rather than guessed), the complete pgBackRest backup inventory bracketing the target date, and the exact infrastructure needed: one EC2 host with production-sized disk and enough CPU for decompression and WAL replay.

 **We caught the retention cliff.** The required full backup would have been pruned by the weekend. We extended pgBackRest retention immediately, keeping it in S3 until the work was done, then reverted the change once the client finished.

 **We ran the restore at full pipe.** With the target set to midnight UTC on the requested recovery point, pgBackRest pulled the 17.9 TB database from its ~3.3 TB compressed S3 repository using 64 parallel workers, holding a steady ~120 MB/s of disk write and saturating the S3 transfer. The data directory landed in about two days, on schedule.

 **We diagnosed what the logs could not say.** Then WAL replay simply stopped. No error. Nothing in the logs even at maximum verbosity. No I/O, no CPU, the startup process frozen mid-recovery. Reading kernel process state (/proc/<pid>/wchan) showed it parked on a futex: PostgreSQL had deadlocked against itself replaying its own WAL. We traced it to MultiXact handling, a regression introduced in the then-current minor releases of PostgreSQL by a fix for a different race condition, triggered when replaying WAL generated by an older minor version. The upstream community had a fix committed but not yet shipped in any point release. Notably, pgBackRest and the backups themselves were flawless; the fault was in the server's recovery path.

 **We built the fix before it was released.** We compiled PostgreSQL from source with the upstream patch applied and brought the database back into recovery. Replay marched through the remaining WAL and paused exactly where asked, 1.378 milliseconds past the target timestamp, delivered read-only with connection settings mirroring production, retaining the option to advance further in time or promote for writes.

## The Results

Eight days after the initial question, the client's team was querying a byte-faithful copy of their 18 TB database as of the precise moment they had named, straight through an unreleased PostgreSQL bug standing in the road. Production was never touched. The client's team completed their data work against the restored copy. We then reverted the temporary retention changes and returned the backup pipeline to normal, leaving the disaster-recovery runbook re-proven against real fire rather than a drill.

 _"Everything is good to go and the team is wrapping up their work. Thanks for making this happen." (VP of Engineering, the client)_

## Why it Matters

A backup you have never restored is a hope, not a plan. And even a tested plan can meet a failure mode no runbook anticipates. When recovery stalled with empty logs, the difference between a delivered restore and a dead end was engineers who could read kernel process state, correlate it against the PostgreSQL source and upstream commit history, and build a patched server before the fix shipped. At terabyte scale, point-in-time recovery is not a feature you configure. It is an expertise you retain.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/restored-to-the-millisecond-an-18-tb-point-in-time-recovery-straight-through-an-unreleased-postgresql-bugfix/)

---

# Breaking the 20 TB Ceiling: A Zero-Data-Loss Exit from AWS RDS to Self-Managed PostgreSQL

> By mid-2023 the platform had outgrown Amazon RDS on three fronts at once. Scale: the database stood at 18.15 TB, closing in on its 20 TB RDS storage ceiling, and RDS autoscaling had already bitten once, when a cooling-off window froze volume growth during a runaway materialized-view refresh and took a replica down. Cost: the reserved instance backing an r6g.16xlarge was up for renewal, and leadership was scrutinizing a cloud bill the managed service kept inflating. Control: performance was being left on the table. Filesystem compression, kernel and memory tuning, direct log access: RDS exposes none of it, and the client's DBA partner could see only what the managed service allowed.

# Breaking the 20 TB Ceiling

A Zero-Data-Loss Exit from AWS RDS to Self-Managed PostgreSQL

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** K-12 education technology (analytics & family engagement)
  *  **Organization:** A K-12 education analytics and family-engagement platform serving school districts across the U.S.
  *  **Environment:** AWS: formerly RDS PostgreSQL; now a self-managed three-node PostgreSQL cluster on EC2, ~20 TB ZFS volumes, PgBouncer, pgBackRest to S3
  *  **Engagement:** Proactive DBA managed services with 24/7 monitoring
  *  **Services:** Cloud replatforming (RDS exit) · Logical-replication migration · Performance & capacity engineering · 24/7 monitoring & incident response



Metric  |  Before  |  After   
---|---|---  
Storage headroom  |  18.15 TB used, nearing the 20 TB RDS ceiling  |  ~20 TB compressed ZFS volumes, grown on the client's own terms   
Data migrated  |  Single managed RDS instance (r6g.16xlarge) + read replica  |  ~18 TB replicated logically, row-count-verified, zero data loss, including one 17 TB (uncompressed) table   
Cutover impact  |  Risk of an extended outage for a full-database move  |  One planned overnight window during the winter school break   
Rollback safety  |  None  |  Reverse replication back to RDS as a live escape hatch; RDS decommissioned five days after go-live   
Results at a glance

## Get in touch

We would love to partner with you on your organizations success!

[Learn More](</contact-us/>)

## The Client

The client is a K-12 education analytics and family-engagement platform serving school districts across the U.S. Its Ruby on Rails application, covering attendance, communications, and student analytics, runs on a PostgreSQL database grown into the tens of terabytes. Every teacher message and district dashboard depends on it. For a platform whose customers are schools, an outage during the school day is not an option.

## The Challenge

The platform had outgrown Amazon RDS on three fronts at once. **Scale:** the database stood at 18.15 TB, closing in on its 20 TB RDS storage ceiling, and RDS autoscaling had already bitten once, when a cooling-off window froze volume growth during a runaway materialized-view refresh and took a replica down. **Cost:** the reserved instance backing an r6g.16xlarge was up for renewal, and leadership was scrutinizing a cloud bill the managed service kept inflating. **Control:** performance was being left on the table. Filesystem compression, kernel and memory tuning, direct log access: RDS exposes none of it, and the client's DBA partner could see only what the managed service allowed.

The client's framing was direct: out of RDS, into something they could scale horizontally and tune at every layer. The catch was the physics. Nearly 18 TB of live production data, including one 17 TB (uncompressed) append-heavy logging table, had to move without losing a row and without taking schools offline.

## The Solution

We executed the exit as a logical-replication migration: old and new platforms live in parallel until the moment of cutover.

  *  **Build the destination first.** A three-node cluster on EC2, a primary plus two streaming replicas, on Ubuntu with ZFS volumes for transparent compression, provisioned via the client's Terraform and configured with Ansible. We configured and restore-tested pgBackRest backups to S3 _before_ production data arrived, and a dedicated pgBadger log host gave us the query-analysis visibility RDS had withheld.
  *  **Replicate ~18 TB out of RDS logically.** The initial sync surfaced everything a heavily written, long-lived database can hide: index rows exceeding the B-tree size limit, incompletely dropped columns, duplicate-key and tuple-header corruption, long-running transactions blocking snapshot acquisition. We engineered around each one. Publications split by write rate. The 17 TB table synced independently. A 5 TB insert-only archive table moved by a custom parallel, day-at-a-time copy that committed incrementally to avoid lock buildup.
  *  **Cut over on the client's calendar.** Go-live ran in a single planned overnight weekend window during the winter school break, the platform's natural low tide, with row counts verified before traffic moved.
  *  **Keep the exit reversible.** Reverse logical replication flowed changes from the new cluster back to RDS through the first production week, a live rollback path until the client called it. We decommissioned RDS five days after go-live.



## The Results

The platform crossed from managed to self-managed with zero data loss, confirmed by the client with exact row-count matches, in one planned window instead of a forced extended outage. The 20 TB ceiling is gone. Storage is now compressed ZFS, grown through deliberate capacity planning rather than at the mercy of autoscaling cooldowns. The double spend of running RDS alongside its replacement ended the week of cutover, along with the r6g.16xlarge reserved-instance renewal.

The control dividend kept paying. We have since deployed HugePages, tuned work_mem live in production, fixed replica query cancellations with hot_standby_feedback, and replaced a runaway materialized view with a trigger-maintained aggregate table that freed ~110 GB. When an accidental mass UPDATE later overwrote production data, we recovered it in place by reading prior row versions from the heap with pageinspect, responding in 13 minutes, no restore required. The architecture also absorbed the client's next move: a second application's database migrated off Heroku into the same cluster, roughly doubling the workload on infrastructure the client now fully owns.

 _"Week one on the new cluster is looking great: thank you for the wild hackery on a Sunday." (Director of Engineering, the client)_

## Why it Matters

Managed database services trade control for convenience, and at tens of terabytes the trade inverts: storage ceilings, opaque internals, and premium pricing become the risk rather than the remedy. This engagement proves the exit can be engineered safely. Logical replication keeps both platforms live, reverse replication keeps the decision reversible, and cutover happens on the business's calendar, not the vendor's.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/breaking-the-20-tb-ceiling-a-zero-data-loss-exit-from-aws-rds-to-self-managed-postgresql/)

---

# Ahead of the 2.1 Billion Wall: bigint Migrations Delivered as Pull Requests

> Our system health check found integer primary keys on the platform's busiest tables. An integer column tops out at 2.1 billion, and these counters only move in one direction. Hit the wall and inserts fail. Not degrade. Fail, in the middle of a business day, on the tables the whole product depends on.

# Ahead of the 2.1 Billion Wall

Postgres bigint Migrations Delivered as Pull Requests

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Automotive services software (multi-tenant SaaS)
  *  **Organization:** A venture-backed SaaS platform for auto repair shops
  *  **Environment:** Heroku Postgres, 687 GB production database, 112 tables, multi-tenant Ruby on Rails
  *  **Engagement:** PostgreSQL health check plus hands-on remediation
  *  **Services:** Schema migration engineering · Full-text search tuning · Platform evaluation · Emergency standby



Metric  |  Before  |  After   
---|---|---  
Primary key headroom on core tables  |  Integer, a hard 2.1 billion ceiling  |  Bigint, ceiling removed   
Migration runtime  |  Unknown  |  Timed on a 687 GB fork of production: 16m50s, 1h24m, 2h32m for the three largest   
Largest migration vs. maintenance window  |  Would not fit  |  Split in two; first production window executed cleanly   
Delivery format  |  Recommendations memo  |  Rails migrations written by us, submitted as pull requests to the client's repository   
Results at a glance

## Get in touch

We would love to chat about how we can be your Postgres or Open Source partner

[Learn More](</contact-us/>)

## The Client

The client runs a multi-tenant SaaS platform that auto repair shops use to write estimates, order parts, and get cars back to their owners. Every repair order, every vehicle, every customer profile lives in one Postgres database on Heroku. When that database slows down, a service writer is standing at a counter with a customer waiting. When it stops, hundreds of shops stop with it.

## The Challenge

Our system health check found integer primary keys on the platform's busiest tables. An integer column tops out at 2.1 billion, and these counters only move in one direction. Hit the wall and inserts fail. Not degrade. Fail, in the middle of a business day, on the tables the whole product depends on.

Fixing it means rewriting some of the largest tables in a 687 GB database, and the platform made that harder, not easier. Heroku Postgres allows no access to the configuration knobs that speed up bulk rewrites. Logical replication, our preferred near-zero-downtime path, was blocked: publications could be created, subscriptions could not. One concurrent index build on this database had already run past 24 hours and finished INVALID. Everything had to happen inside maintenance windows the client could actually afford.

The client's engineering team had one more constraint. They manage every schema change through version-controlled Rails migrations, and they did not have spare capacity to write these.

## The Solution

So we wrote them.

Our engineer checked out the client's codebase, got the application running locally, and wrote the ActiveRecord migrations to move the primary and foreign keys to bigint, in the client's own conventions, submitted as pull requests through their normal review process. Not a script attached to a ticket. A commit with our name on it, passing their checks.

Then we rehearsed. The client forked the production database, all 687 GB of it, and we ran every migration against the fork with a stopwatch: 16 minutes 50 seconds for the vehicle references, 1 hour 24 minutes for inventory, 2 hours 32 minutes for profiles. The rehearsal caught what a dev database never could. One migration failed against a trigger that existed only in production. We fixed it before it ever mattered.

The timings showed the largest migration would not fit the maintenance window, so we split it into two parts and sequenced them across separate windows. The first production window ran in late July and executed cleanly. The client ran the remaining windows themselves, following our runbook, with our 24x7 emergency line standing by. They never needed it for a failure, but it was there.

Along the way we handled what the engagement surfaced: we diagnosed a deadlock during CREATE FUNCTION down to catalog tuple locks and function body checking, redesigned their multi-tenant full-text search around tenant-scoped partial GIN indexes so big tenants stopped wrecking the planner for everyone, and evaluated a move off Heroku entirely, recommending EC2 where the knobs we kept reaching for would finally exist.

## The Results

The 2.1 billion ceiling is gone from the tables that were counting toward it. The client got version-controlled migrations that fit their process, timed runbooks proven against a full-size copy of production, and a team that had watched every step before doing it alone. The engagement kept going: search tuning, platform planning, and standby coverage.

## Why it Matters

Every consultancy will tell you your integer keys are going to overflow. A memo does not move a 687 GB database. The measure of a database partner is whether they will open the pull request, run the rehearsal, and put their name in your commit history next to yours.

Advice is cheap. Commits are accountability.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/ahead-of-the-21-billion-wall-bigint-migrations-delivered-as-pull-requests/)

---

# Every Emergency Resolved, None Caused by PostgreSQL: Fifteen Years Running the Full Stack for a Vacation-Rental Marketplace

> Self-hosting means every failure mode belongs to you. Over the engagement the platform absorbed the full catalog: a failed RAID-controller battery that took a database server down, direct-attached storage throwing hardware errors for a week, a Ceph RBD volume stuck mid-delete, swap exhaustion on a storage node, and a runaway application process that inflated PostgreSQL logging from roughly 1.4 GB a day to 240 GB in under twelve hours, filling the root filesystem the same day. All of it against a seasonal travel business whose January and holiday-quarter traffic spikes forgive nothing.

# Every Emergency Resolved, None Caused by PostgreSQL

Fifteen Years Running the Full Stack for a Vacation-Rental Marketplace

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Online travel: consumer vacation-rental marketplace
  *  **Organization:** A leading online vacation-rental marketplace connecting owners and travelers, with pronounced seasonal booking peaks in January and Q4
  *  **Environment:** Fully self-hosted: a four-node LXD container cluster on Ceph storage, PostgreSQL, pglogical/Bucardo replication, pgBackRest backups to S3, dedicated 10 Gbps replication network
  *  **Engagement:** Proactive managed PostgreSQL services
  *  **Services:** Full-stack platform operations · Backup & recovery engineering · Major-version upgrades · 24×7 incident response



Metric  |  Before  |  After   
---|---|---  
Database platform  |  Bare metal + DRBD/NFS  |  LXD containers on a four-node Ceph cluster   
PostgreSQL major version  |  EOL  |  On a continuing minor-release cadence   
Backup transfer overages  |  Recurring monthly bandwidth charges  |  Eliminated (incremental, throttled pgBackRest)   
Stale backup storage in S3  |  8.7 TB of legacy backups  |  Reclaimed   
Emergency incidents  |  n/a  |  4/4 resolved; 3 of 4 same-day; none caused by PostgreSQL   
Results at a glance

## Get in touch

Get the consulting and support your deserve for Postgres and Open Source

[Learn More](</contact-us/>)

## The Client

A leading online vacation-rental marketplace has run its business on PostgreSQL since 2011. Unusually for a consumer web property of its traffic, it runs the entire stack itself: its own hardware in a colocation datacenter, its own load balancers, storage, and database cluster. Every listing, booking, and account lives in that database. There is no cloud provider to absorb a failure. When something breaks anywhere between the disk and the connection slot, someone has to own it end to end.

For fifteen years, that someone has been us.

## The Challenge

Self-hosting means every failure mode belongs to you. Over the engagement the platform absorbed the full catalog: a failed RAID-controller battery that took a database server down, direct-attached storage throwing hardware errors for a week, a Ceph RBD volume stuck mid-delete, swap exhaustion on a storage node, and a runaway application process that inflated PostgreSQL logging from roughly 1.4 GB a day to 240 GB in under twelve hours, filling the root filesystem the same day. All of it against a seasonal travel business whose January and holiday-quarter traffic spikes forgive nothing.

Meanwhile the platform was aging out from under the workload. PostgreSQL running past end-of-life on bare metal with DRBD and NFS. Backups on legacy WAL-E tooling. Datacenter bandwidth overages recurring every month.

## The Solution

Our approach has been the same for fifteen years: own the whole stack, and treat recovery as the product.

  *  **Zero-downtime replatforming.** We executed a full datacenter migration with cascading replication and a switchover, no outage window. The client's engineering team's verdict on the cutover: it went perfectly.
  *  **Container-and-Ceph modernization.** We rebuilt the bare-metal DRBD/NFS platform as LXD containers on a four-node Ceph cluster, with a dedicated 10 Gbps replication network and a golden container image that registers its own DNS and monitoring. As the storage layer's failure modes surfaced (stuck RBD volumes, undersized container profiles, swap pressure), we engineered them out. We completed this with a CephFS cutover that retired the legacy NFS service entirely, replicated four ways like the rest of the cluster: 3.4 times the write throughput and 36 times the read throughput of the NFS service it replaced, executed in a single planned 30-minute window.
  *  **Major-version escape from EOL.** Postgres de-risked by a benchmarked side-by-side test environment before cutover, with security minor releases applied on cadence since.
  *  **Recovery engineering, continuously exercised.** We rebuilt backups from WAL-E to incremental, bandwidth-throttled pgBackRest with continuous WAL archiving to S3. That ended the monthly overages outright and reclaimed 8.7 TB of stale legacy backups. Restore procedures are tested and documented, not assumed. When the client needed to investigate historical table data, we caught the required full backup one scheduled prune away from deletion and extended retention on the spot, preserving the recovery point until diagnosis was complete.
  *  **Root-cause discipline.** We traced the 240 GB log explosion same-day to an application UPDATE writing oversized binary data. We traced a query stall to stale planner statistics: five seconds to milliseconds after ANALYZE. We traced a backup failure all the way down to IPv6 DNS resolution-order behavior in glibc.



## The Results

Across 306 tickets and fifteen years, every emergency-priority incident was resolved, three of four the same day, and not one was caused by PostgreSQL itself. Each traced to the application, network, or load-balancer tier while the database kept serving. The critical tier overall (emergency plus high priority) stands at 98% resolved.

The durable outcomes compound: a modern container-and-Ceph platform where end-of-life bare metal once stood, a supported PostgreSQL major version, backups that are cheaper, faster, and provably restorable, and monitoring and automation that retire toil rather than defer it. Fifteen years in, the relationship keeps expanding on the same trajectory. Disaster-recovery and cloud-failover engineering are now in flight.

 _"It went perfectly." The client's engineering team, after the zero-downtime datacenter migration._

## Why it Matters

Managed cloud databases outsource recovery to someone else's runbook. When you self-host, recovery expertise is the product, and it cannot be bolted on during an incident. Fifteen years of that discipline buys platform migrations without downtime, backups that are exercised rather than hoped about, and a database tier that is never the reason the site is down.

A backup you have never restored is a hope. This client has never had to hope.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/case_study_emergency_resolved_none_by_postgres/)

---

# Fifteen Years, Seven Emergencies, Zero Data Loss: Managed PostgreSQL Behind a Major Public Library Catalog

> Running a mission-critical open-source stack on premises demands deep PostgreSQL expertise the library could not justify as a full-time internal team. When the engagement began in, the estate ran on bare-metal CentOS hosts fronted by pgpool, and over fifteen years every generation of that stack aged into a risk. The operating systems reached end of life. The pgpool connection pooler proved fragile, at one point taking the whole system down over a stale socket file. Long-running report queries sat idle in transaction for days, stalling replication and blocking cleanup. Disk and WAL-archive exhaustion recurred through the bare-metal era. And through it all, the database had to climb five major PostgreSQL versions without interrupting daily circulation for the public.

# Fifteen Years, Seven Emergencies, Zero Data Loss

Managed PostgreSQL Behind a Major Public Library Catalog

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

* **Industry:** Public sector: public libraries
  *  **Organization:** One of the busiest public library systems in the United States, serving well over a million residents
  *  **Environment:** Self-managed PostgreSQL on on-premises VMware, PgBouncer connection pooling, pgBackRest backups, behind the Evergreen open-source integrated library system (ILS)
  *  **Engagement:** Proactive managed DBA services
  *  **Services:** Major-version upgrades · 24×7 monitoring & incident response · Infrastructure migration · Performance engineering



Outcome   
---  
100% resolution of all 88 Emergency and High-priority issues raised in 15+ years   
Only 7 emergencies in 15 years: 7/7 resolved, mean time-to-resolve 2.4 days; the most recent resolved same day   
PostgreSQL across five major-version upgrades with zero data-loss incidents   
981 support tickets, 99% closed, including a proactive review that identified 461 unused indexes for safe removal   
Results at a glance

## Get in touch

Would love to speak about opportunities to be your partner in Postgres and Open Source

[Learn More](</contact-us/>)

## The Client

The client is one of the busiest public library systems in the United States, serving well over a million residents across dozens of branches. Its catalog, circulation, holds, and patron accounts all run on Evergreen, the open-source ILS, and PostgreSQL is Evergreen's system of record. Every catalog search, checkout, and due date touches the database. Any database problem is immediately visible to the public at every branch. As a taxpayer-funded institution, the library chose an open-source stack over proprietary library platforms, provided it could be run with enterprise-grade reliability.

## The Challenge

Running a mission-critical open-source stack on premises demands deep PostgreSQL expertise the library could not justify as a full-time internal team. When the engagement began in 2010, the estate ran PostgreSQL 9.0 on bare-metal CentOS hosts fronted by pgpool, and over fifteen years every generation of that stack aged into a risk. The operating systems reached end of life. The pgpool connection pooler proved fragile, at one point taking the whole system down over a stale socket file. Long-running report queries sat idle in transaction for days, stalling replication and blocking cleanup. Disk and WAL-archive exhaustion recurred through the bare-metal era. And through it all, the database had to climb five major PostgreSQL versions without interrupting daily circulation for the public.

## The Solution

We have run the library's PostgreSQL estate continuously since 2010 under a flat-rate proactive support agreement, a rate held unchanged for a full decade, combining 24×7 monitoring with planned modernization:

  *  **A repeatable, low-risk upgrade playbook.** Each major-version upgrade pulls a replica out of the load-balancing pool as a standing rollback point before the primary is touched. That playbook carried the database from PostgreSQL through modern versions and runs the client's annual Evergreen application upgrades on the same cadence.
  *  **Fleet modernization.** We migrated the entire database fleet off end-of-life bare-metal CentOS onto Ubuntu VMs on VMware with monitoring intact, eliminating a large EOL risk surface.
  *  **Connection and backup stack overhaul.** We replaced the fragile pgpool tier with PgBouncer and standardized backups on pgBackRest, then validated restores when it mattered: an apparent "missing days" restore scare resolved as a procedure correction, with production backups confirmed healthy.
  *  **Monitoring we operate ourselves.** A fully managed Zabbix stack watches the estate. When the monitoring platform itself aged, we rebuilt it end to end, repairing broken history-table partitioning in the process, and added long-running-query and replication-delay alerting.
  *  **Proactive performance engineering.** After transaction-ID wraparound pressure surfaced , we built an automated weekly VACUUM FREEZE job that has headed off the problem ever since, and a proactive index review identified 461 unused indexes for safe removal.
  *  **Incident response that closes cleanly.** When a data-center power loss with generator failure took down the VMware cluster in 2025, we verified every host on recovery, caught the one real defect, an unmounted backup volume silently blocking WAL archiving, and fixed it the same day.



## The Results

Across 981 tickets and fifteen years, the engagement has produced a 99% closure rate and 100% resolution of every one of the 88 Emergency and High-priority issues ever raised. There have been just seven emergencies in fifteen years, most of them routine, resolved in 2.4 days on average, with the most recent closed same-day. The database advanced five major PostgreSQL versions with no data-loss incident. The fleet moved off end-of-life hardware. The wraparound, pooling, and archiving failure modes of the early years were engineered out rather than repeatedly firefought.

The relationship keeps expanding. The client stood up a new Kubernetes-fronted production cluster with us providing backups and monitoring from day one, and the next major-version upgrade is already planned.

## Why it Matters

Public institutions do not need proprietary platforms to get proprietary-grade reliability. They need disciplined operations on the open-source stack they already chose. A rehearsed upgrade playbook, proactive monitoring, and root-cause fixes turn PostgreSQL into infrastructure the public never has to think about, at a fraction of proprietary licensing cost.

Fifteen years of boring, predictable uptime. For a public catalog, boring is the win.

---
[View this page online](https://www.commandprompt.com/about/success-stories-case-studies/fifteen-years-seven-emergencies-zero-data-loss-managed-postgresql-behind-a-major-public-library-catalog/)

---

# Careers

> Command Prompt Inc. careers

## Open Positions

![Fort](/media/images/guard.height-500.format-webp.webp) ![Fort](/media/images/guard.height-500.format-webp.webp)

## No openings at this time.

---
[View this page online](https://www.commandprompt.com/about/careers/)

---

# Database and Systems Administrator

![Zebra_GrandCanyon.jpg](/media/images/Zebra_GrandCanyon.height-500.format-webp.webp) ![Zebra_GrandCanyon.jpg](/media/images/Zebra_GrandCanyon.height-500.format-webp.webp)

**(U.S. Only)**

Are you tired of 60 hour weeks, being under appreciated and having no meaningful relationship with your team? Command Prompt has: No Venture Capital, No Debt, and No B.S. We are honest, transparent, professional services and support for the Postgres centered stack. We are human and community leadership focused technology company with decades of leadership experience.

 **  
Command Prompt offers:**

  * 100% work from home: Digital nomads welcome!
  * 401k with full match
  * Profit sharing
  * Flex time
  * Health Insurance
  * Health Reimbursement Arrangement (HRA)
  * Book Stipend
  * Professional Development subsidy
  * A positive work environment built around productive team dynamics



 **  
About Command Prompt:**

Command Prompt is an original Postgres company and has been operating since 1997. We specialize in white glove, platinum level service with a focus on positivity, professionalism, and team growth. We have an extremely low turnover rate for team members as well as clients, with active clients since 2004. We are profitable and wish to add an amazing team member.

 **  
About you:**

You do not seek a gig, you seek a home. You are a legal U.S. resident or citizen (if applying for U.S. based position). You want to be part of a team of professionals vested in the success of themselves, their team, and their clients. You have a positive attitude, excellent written and verbal communication. You prefer a dynamic work environment and you encourage constructive criticism. You love to solve problems and find creative solutions.  
  
Your skill set is that of a generalist with a competent practical knowledge of Linux, PostgreSQL, and related technologies. There may be a passion within you for automation with Salt or Ansible and you love well written documentation. You understand that practical security is for the benefit of yourself, your team, and the client. Your ego allows you to ask for help and welcomes the opportunity to learn. You may grumble about the cloud but you understand its place and value. You have the ability to imagine, propose, test, and deliver integrated and maintained solutions for clients. You work well in a team.  
  
You will be interfacing with clients and a positive attitude for service and professionalism is not optional.

 **  
What would be nice:**

  * Knowledge in Oracle, ideally with experience in Oracle to PostgreSQL migrations.
  * Experience supporting PostgreSQL in cloud environments including (but not limited to) AWS, Microsoft Azure, Google Cloud, Softlayer, etc.
  * Detailed understanding of the PostgreSQL Architecture and internals.
  * Understanding and working knowledge of various extensions in PostgreSQL.
  * Effective technical writing for documentation and playbooks.
  * Kubernetes experience.



 **Compensation:**

Compensation is competitive, based on experience and location.

 **Apply:**

  * Email your resume as a PDF attachment to: jd<at>commandprompt.com
  * The subject of the email will be the reason we should consider your resume.
  * Please specify which region you are applying for (U.S., Asia, Europe) in the body of the message.
  * Do not send a cover letter.
  * Before you apply, please familiarize yourself with our company and our culture. Here is a [good start.](<https://www.commandprompt.com/about/intrepidusvita/>)



Applicants that can not follow the above instructions will not be considered.

---
[View this page online](https://www.commandprompt.com/about/careers/database-and-systems-administrator/)

---

# Database and Systems Administrator (No-US)

## Database and Systems Administrator (Non-US)

![Lighthouse](/media/images/lite.height-500.format-webp.webp) ![Lighthouse](/media/images/lite.height-500.format-webp.webp)

Are you tired of 60 hour weeks, being under appreciated and having no meaningful relationship with your team? Command Prompt has: No Venture Capital, No Debt, and No B.S. We are honest, transparent, professional services and support for the Postgres centered stack. We are human and community leadership focused technology company with decades of leadership experience.

 **  
Command Prompt offers:**

  * 100% work from home: Digital nomads welcome!
  * 401k with full match (US Only)
  * Profit sharing
  * Flex time
  * Health Insurance (US Only)
  * Health Reimbursement Arrangement (HRA) (US Only)
  * Book Stipend
  * Professional Development subsidy
  * A positive work environment built around productive team dynamics



 **  
About Command Prompt:**

Command Prompt is an original Postgres company and has been operating since 1997. We specialize in white glove, platinum level service with a focus on positivity, professionalism, and team growth. We have an extremely low turnover rate for team members as well as clients, with active clients since 2004. We are profitable and wish to add an amazing team member.

 **  
About you:**

You do not seek a gig, you seek a home. You want to be part of a team of professionals vested in the success of themselves, their team, and their clients. You have a positive attitude, excellent written and verbal communication. You prefer a dynamic work environment and you encourage constructive criticism. You love to solve problems and find creative solutions.  
  
Your skill set is that of a generalist with a competent practical knowledge of Linux, PostgreSQL, and related technologies. There may be a passion within you for automation with Salt or Ansible and you love well written documentation. You understand that practical security is for the benefit of yourself, your team, and the client. Your ego allows you to ask for help and welcomes the opportunity to learn. You may grumble about the cloud but you understand its place and value. You have the ability to imagine, propose, test, and deliver integrated and maintained solutions for clients. You work well in a team.  
  
You will be interfacing with clients and a positive attitude for service and professionalism is not optional.

 **  
What would be nice:**

  * Knowledge in Oracle, ideally with experience in Oracle to PostgreSQL migrations.
  * Experience supporting PostgreSQL in cloud environments including (but not limited to) AWS, Microsoft Azure, Google Cloud, Softlayer, etc.
  * Detailed understanding of the PostgreSQL Architecture and internals.
  * Understanding and working knowledge of various extensions in PostgreSQL.
  * Effective technical writing for documentation and playbooks.
  * Kubernetes experience.



 **Compensation:**

Compensation is competitive, based on experience and location.

 **Apply:**

  * Email your resume as a PDF attachment to: amanda<at>commandprompt.com
  * The subject of the email will be the reason we should consider your resume.
  * Please specify which region you are applying for (U.S., Asia, Europe) in the body of the message.
  * Do not send a cover letter.
  * Before you apply, please familiarize yourself with our company and our culture. Here is a [good start.](<https://www.commandprompt.com/about/intrepidusvita/>)



Applicants that can not follow the above instructions will not be considered.

---
[View this page online](https://www.commandprompt.com/about/careers/database-and-systems-administrator-no-us/)

---

# Project Management Assistant

## Project Management Assistant

![Bring it on](/media/images/taco.height-500.format-webp.webp) ![Bring it on](/media/images/taco.height-500.format-webp.webp)

Are you tired of 60 hour weeks, being under appreciated and having no meaningful relationship with your team? Command Prompt has: No Venture Capital, No Debt, and No B.S. We are honest, transparent, professional services and support for the Postgres centered stack. We are human and community leadership focused technology company with decades of leadership experience.  


 **Command Prompt offers:**

  * 100% work from home: Digital nomads welcome!
  * 401k with full match
  * Profit sharing
  * Flex time
  * Health Insurance
  * Health Reimbursement Arrangement (HRA)
  * Book Stipend
  * Professional Development subsidy
  * A positive work environment built around productive team dynamics  




 **About Command Prompt:**

Command Prompt is an original Postgres company and has been operating since 1997. We specialize in white glove, platinum level service with a focus on positivity, professionalism, and team growth. We have an extremely low turnover rate for team members as well as clients, with active clients since 2004. We are profitable and wish to add an amazing team member.

 **  
About you:**

You do not seek a gig, you seek a home. You want to be part of a team of professionals vested in the success of themselves, their team, and their clients. You have a positive attitude, excellent written and verbal communication. You prefer a dynamic work environment and you encourage constructive criticism. You love to solve problems and find creative solutions.

 **List of Initial Tasks and Responsibilities:**

* Responding to tickets as they come in (first human responder)

* Checking in with the team throughout the week on task status

* Creating project plans with technical team member input

* Ensuring milestones are met by Command Prompt team

* Ensuring team members get progress updates to clients when the task is active

* Ensuring tasks/projects are kept up to date with due dates, status, and next steps at all times

* Reminding team of submitting billables

* Check ins/setting up meetings with quiet clients that have active projects

* Setting up calls with clients per client request based on the direction of the Project Manager

* Taking extensive, detailed notes during calls (especially action items)

* Ensuring team remembers all policies, for Command Prompt and for specific clients

* Helping to put together Statements of Work for current clients for review by the Project Manager

* Ensuring on call team member fulfills weekly duties

* Keeping client information (address, contacts, requirements) up to date

 **Skills Needed:**

* Ability to provide excellent client service

* Professional quality writing and grammar

* Attention to detail

* General comfort with phone calls and video conferencing

* Time management

* Efficiency

* Prioritization

* Proactive response

 **How Training Would Work:**

The Command Prompt Project Management Assistant would work directly with the current Project Manager to get to know the expectations with regards to requirements, timelines, professional response, and management. All training/work is done from a remote location via chat and phone call.

Week one: An onboarding task list will be created and populated with initial learning tasks to be completed by the Assistant. Once complete and the general onboarding process has ended, Assistant will learn to work with the Command Prompt engineering team and clients.

 **Expectations:**

* Daily summary report/meeting with Project Manager to download the bullet points and any urgent details that must be addressed

* Full time employment with a set schedule

* Management of tickets for tracking daily/weekly tasks through Redmine

 **Compensation:**

Compensation is competitive, based on experience and location.

 **How to apply:**

  * Email your resume as a PDF attachment to: amanda<at>commandprompt.com
  * The subject of the email will be the reason we should consider your resume.
  * Please specify which region you are applying for (U.S., Asia, Europe) in the body of the message.
  * Do not send a cover letter.
  * Before you apply, please familiarize yourself with our company and our culture. Here is a [good start.](<https://www.commandprompt.com/about/intrepidusvita/>)



Applicants that can not follow the above instructions will not be considered.

---
[View this page online](https://www.commandprompt.com/about/careers/project-management-assistant/)

---

# Sr. Inside Sales Representative

## Sr. Inside Sales Representative (U.S)

Command Prompt has: No Venture Capital, No Debt, and No B.S. We are honest, transparent, professional services and support for the Postgres centered stack. We are a human and community leadership focused Open Source technology company with decades of leadership experience.

 **  
Command Prompt offers:**

  * 100% work from home: Digital nomads welcome!
  * 401k with full match
  * Profit sharing
  * Flex time with PTO
  * Employer sponsored Self-Care time
  * Employer sponsored community volunteer time
  * Health Insurance
  * Health Reimbursement Arrangement (HRA)
  * Book Stipend
  * Professional Development subsidy
  * A positive work environment built around productive team dynamics



 **  
About Command Prompt:**

Command Prompt is an original Postgres and Open Source company. We have been operating since 1997. We specialize in white glove, platinum level service with a focus on positivity, professionalism, and team growth. We have a low turnover rate for team members as well as clients, with active clients since 2004. We are profitable and wish to add an amazing team member.

 **  
About you:**

You are a legal U.S. resident or citizen (if applying for a U.S. based position). You want to be part of a team of professionals vested in the success of themselves, their team, and their clients. You have a positive attitude with excellent written and verbal communication. You prefer a dynamic work environment and you encourage constructive criticism. You love to solve problems, find creative solutions and build relationships based on honesty and integrity.

Your skill set is that of a problem solver. You are willing to sell a solution that solves a problem and refuse to sell one that doesn’t. You have the ability to imagine, propose, and deliver on strategic solutions for clients. You work well in a team. Your belief is that a client is a partner in our mutual success. You have a deep understanding and belief in the [farming method](<https://www.tsia.com/blog/why-farming-for-is-more-efficient-than-hunting-for-technology-revenue-growth>), hunting and know when which is appropriate.

 **  
Your bench:**

  * Knowledge of PostgreSQL, Oracle, or other modern Database Systems.
  * Experience in cloud environments including (but not limited to) AWS, Microsoft Azure, Google Cloud, Softlayer, etc.
  * Effective proposal writing skills.
  * Knowledge of general Open Source solutions such as Linux, the Stack and Kubernetes.



 **  
Compensation:**

Compensation is competitive, based on experience and location.

 **  
Apply:**

  * Email your resume as a PDF attachment to: jd<at>commandprompt.com
  * The subject of the email will be the reason we should consider your resume.
  * Please specify which region you are applying for (U.S., Asia, Europe) in the body of the message.
  * Do not send a cover letter.
  * Before you apply, please familiarize yourself with our company and our culture. Here is a [good start.](<https://www.commandprompt.com/about/intrepidusvita/>)



Applicants that can not follow the above instructions will not be considered.

---
[View this page online](https://www.commandprompt.com/about/careers/sr-inside-sales-representative/)

---

# Intrepidus Vita

## Life and Leadership

![20221019_180202](/media/images/20221019_180202.height-500.format-webp.webp) ![20221019_180202](/media/images/20221019_180202.height-500.format-webp.webp)

The Intrepidus Vita (Fearless Life) project is our life and leadership initiative. We provide content, podcasts, videos, and general inspiration and motivation for people around the globe through service, success and a pay it forward attitude. This project is largely centered around how professionals can lead a full life and help people understand that there is no work life balance. There is only life balance and work is one part of it.

##   
Articles

  * [Professionalism Matters even when working remote](<https://www.commandprompt.com/blog/professionalism-matters-even-when-working-remote/>)
  * [Pay it Forward](<https://www.commandprompt.com/blog/Pay_It-Forward/>)
  * [The COVID-19 Pivot](<https://www.commandprompt.com/blog/the_covid_pivot/>)
  * [How to achieve success when working from home](<https://www.commandprompt.com/blog/how_to_achieve_success_when_working_from_home/>)
  * [Recognizing and developing Emotional Intelligence](<https://www.commandprompt.com/blog/Recognizing-and-Developing-Emotional-Intelligence/>)
  * [We're all in this together](<https://www.commandprompt.com/blog/were-all-in-this-together/>)
  * [The issue of convenience](</blog/the-issue-of-convenience/>)  
  




### Keys to moving forward in your life and career

  * [Get out of your own way](<https://www.commandprompt.com/blog/keys_to_moving_forward_get_out_of_your_own_way/>)
  * [Making the leap to the uncomfortable](<https://www.commandprompt.com/blog/making-the-leap-to-uncomfortable/>)
  * [Your Work-Life balance is killing you](<https://commandprompt.com/blog/your-work-life-balance-is-killing-you/>)



## A school bus?

![Intrepidus Vita](/media/images/bus_missoula.height-500.format-webp.webp) ![Intrepidus Vita](/media/images/bus_missoula.height-500.format-webp.webp)

This picture was taken in September 2021 in Missoula, Montana. It is the inspiration of the Intrepidus Vita movement. We (Amanda Nystrom and JD) travel the United States for many months at a time working, paying it forward and experiencing life. It is true that to do so in a School Bus is not the norm but it is a 100k+ person community throughout the United States and Europe that enjoys or desires a free and nomadic lifestyle. There are many who are seeking freedom from the rigors of debt, corporate abuse and being paid too little to enjoy too much of what our great country (and others) have to offer. Others, like ourselves do it for inspiration of our leadership content, adventure and to continue the mission of [People, Postgres, Data](<https://postgresconf.org/>).

---
[View this page online](https://www.commandprompt.com/about/intrepidusvita/)

---

# Policies

## Our Command Prompt Policies

Command Prompt is committed to taking our clients and partners privacy and security concerns seriously. Information security is a top priority for our team. We strive daily to implement and maintain security policies, procedures, processes, and standards for due diligence in preventing unauthorized access to our client data. We apply appropriate administrative, operational, and technical security controls to help ensure that our client data is handled and processed in a responsible and secure manner.  


Our information security and access control strategies cover all aspects of our company, including:  
  


  * Data protection
  * Organizational security
  * Operational security processes and procedures
  * Incident management and response
  * Business continuity and disaster recovery
  * [Privacy policy](</privacy-policy/>)
  * [Terms of Use](</terms-of-use/>)



  
Additional company policies:

  * [Command Prompt Code of Conduct](</about/code-of-conduct/>).

---
[View this page online](https://www.commandprompt.com/about/policies/)

---

# Code of Conduct

> code of conduct

## Code of Conduct

This Code of Conduct (‘Code’) describes what Command Prompt Inc. (“Command Prompt”) stands for and believes in. The Code guides us in making sound and ethical decisions that are in the best interest of all Command Prompt stakeholders including our staff, clients, and community.  
  


This Code and the Business Principles apply to all Command Prompt employees worldwide and align with the Code of Conduct of the Responsible Business Alliance (formerly the Electronic Industry Citizenship Coalition). We actively pursue adherence to the EICC Code of Conduct on behalf of our stakeholders.  
  


The Code describes five core values and corresponding Business Principles in support of standards for Labor, Health and Safety, the Environment, Business Ethics, and acceptable Management Systems.  
  


 **We respect people and planet  
**

  * We define and execute our business strategy with a responsibility for the economic, social and environmental impact of our activities, products, and services.
  * We respect our employees, value their different cultural identities and fully acknowledge their individual contribution.
  * We are committed to a safe and healthy working environment where mutual respect prevails.
  * We provide working conditions based on objective and non-discriminatory criteria, which include a commitment to diversity and equal opportunities for all employees.
  * We show zero tolerance to any form of discrimination or harassment.
  * We do not use forced, bonded or indentured labor, involuntary prison labor, slavery, child labor or trafficking of persons.
  * We care for and contribute to the communities in which we operate.
  * We continuously improve our own environmental performance by reducing harmful emissions to air, soil and water.
  * We aim to improve the resource efficiency of our products and services,and to enable significant improvements in energy efficiency of computing systems.



 **We operate with integrity  
**

  * We adhere to applicable laws, regulations and corporate governance standards.
  * We operate our business on the basis of integrity, excellence, commitment and fair play.
  * We expect the same from those parties with whom we do business.
  * We avoid possible conflicts of interests between personal and professional relationships. This also means that we do not use company opportunities for personal gain.
  * We do not tolerate any form of bribery and/or corruption.
  * We continuously promote honest and accountable behavior.



 **We preserve our assets**

  * We carefully preserve and protect our intellectual property and deal with information to secure the required level of confidentiality, integrity and availability of that information.
  * We use and protect company assets responsibly and professionally for Command Prompt’s legitimate business purposes.
  * We respect and safeguard third party assets and Information.
  * We respect each individual’s right to privacy and therefore protect and deal respectfully with any personal data we process.



 **We manage professionally  
**

  * We manage exposure by following processes and policies.
  * We apply high quality in accounting, reviewing, reporting, auditing and disclosing.



 **We encourage to Speak Up  
**

  * We value and encourage individuals to speak up and raise concerns about actual or suspected misconduct.
  * We deal with concerns in a professional, confidential and respectful manner. Individuals speaking up in good faith are protected from any form of retaliation.

---
[View this page online](https://www.commandprompt.com/about/code-of-conduct/)

---

# PgConf

## PgConf: The Original U.S. Postgres Conference

![DSC_0776](/media/images/DSC_0776.height-500.format-webp.webp) ![DSC_0776](/media/images/DSC_0776.height-500.format-webp.webp)

PgConf in the United States was conceived by Command Prompt's founder, Joshua (JD) Drake.

  
The first PgConf was held at Portland State University in 2007.

  
PgConf continues to be volunteer organized and is known in the United States as PgConf / Postgres Conference / PostgresConf. In April 2024, PgConf.US ran again in San Jose and then again in Seattle.  
  
You can visit the [website here](<https://pgconf.org>).

## PgConf 2024: San Jose

![7Y8A2553](/media/images/7Y8A2553.height-500.format-webp.webp) ![7Y8A2553](/media/images/7Y8A2553.height-500.format-webp.webp)

The keynote at PgConf 2024: San Jose

---
[View this page online](https://www.commandprompt.com/about/pgconf/)

---

# Our Team

> Meet the team behind Command Prompt: the Postgres engineers who answer when you call. Real people, no call centers, supporting open source since 1997.

## Our Team

![Amanda Nystrom](/media/images/amandafrenchie.height-300.format-webp.webp)

## Amanda Nystrom

### CEO

Amanda has been in the open source world for over a decade, with four degrees in communication, psychology, and science. Her role as the Chief Executive Officer has reinforced her passion for serving people and ensuring the best quality service for clients and her team. She is a Duke Certified Health & Wellbeing Coach and an annoyingly positive person. In her life outside of work, she often finds herself traveling in a short bus named Intrepidus, hiking, and photographing nature.

![Ildefonso Camargo](/media/images/Ildefonso.height-300.format-webp.webp)

## Ildefonso Camargo

### CIO

Ildefonso has been in IT-related jobs for over 20 years. He is an Electronics Engineer, having spent all of his university years working in research labs related to computing (from IT to AI). He is originally from Venezuela and now lives in the Sunshine State. He is married, has two children, and a dog named Julieta. Ildefonso’s secret to his success is listening to classical music while he works. He is a musician, with experience in classical and folkloric music, knows how to play the Oboe, the Mandolin, and the Venezuelan "Cuatro." No matter the task thrown at him, he accepts the challenge and finds enjoyment in solving the problem.

![Joshua Drake](/media/images/jd.height-300.format-webp.webp)

## Joshua Drake

### President & CTO

Joshua D. Drake (JD) is a long standing member of the PostgreSQL Community. He co-authored the original Oreilly book, "Practical PostgreSQL", is a Founder/Director and former President of United States PostgreSQL (http://www.postgresql.us/). Further he was a Director for Software in the Public Interest for 9 years (http://www.spi-inc.org). He is Co-Chair of Postgres Conference and helps organize many of the Postgres meetups in North America. An Infrastructure and Full Stack expert, you will benefit from well over 20 years of successful experience in Open Source implementation when working with him.

![Eugene Dubinin](/media/images/euegene3.height-300.format-webp.webp)

## Eugene Dubinin

### Senior Developer & Project Lead

Eugene has been in the IT industry for 18 years. He began his career as a Linux system administrator at one of the top ISPs in his area. After five years working as a system administrator he decided to switch to software developing, still keeping his preference for open source software solutions and the UNIX operating systems. Eugene spends his spare time mountain biking, rock climbing, and being adventurous. He is interested in photography and ARM-based single-board computers. A fun fact about Eugene is that he got into programming just because he wanted to write mods to Quake2.

![Debra Cerda](/media/images/debbie_grxGANS.height-300.format-webp.webp)

## Debra Cerda

### Director of Compliance & Client Success

Debra Cerda has spent nearly fifteen years as a business development and sales professional within the water industry and technology sectors. She has been an open data, open source, and Postgres advocate for over a decade. Debra is an organizer of the Austin Postgres and other major cities Meetup groups, as well as a co-organizer of the PostgresConf series. She also served as a Director for the US PostgreSQL Association. Her additional volunteer work includes launching a nonprofit community radio station. Debra is passionate about film, water, and her Chihuahua mix dogs.

![James Campbell](/media/images/james2.height-300.format-webp.webp)

## James Campbell

### System Administrator / DBA

James has over eight years of experience working in higher education as a SysAdmin (and unofficial Postgres DBA), and holds a BS in mathematics and computer science from Clarkson University. He started programming when he was 12, on an Apple IIe. James has used Linux since the early 2000’s, and is a Gentoo enthusiast (yep, one of those). A couple of his interests are cryptography and automation. James lives in Maine with his spouse, five kids, and some number of cats. His hobbies include grumbling about the weather, baking, fixing things, losing to his kids in video games, and playing several musical instruments (poorly).

![Greg Dostatni](/media/images/greg.height-300.format-webp.webp)

## Greg Dostatni

### DBA

Greg is an experienced IT professional with over 20 years of experience in higher education. Starting as a developer, he worked on software to manage Search and Rescue incidents, urban crowd movement simulations and identifying and cataloging trees from aerial photography. He has a background as a DBA / System Administrator working with Oracle and Postgres in Solaris and Linux. Greg has later transitioned into building and managing applications and services for a large university in Canada. Greg is committed to using technology to solve problems both at home and in professional setting.

![Valerii Herman](/media/images/Screenshot_2023-12-12_141554.height-300.format-webp.webp)

## Valerii Herman

### Python Developer

Valerii is a skilled software developer with over 4 years of experience in the field.Throughout his career, he has had the opportunity to work on diverse projects, ranging from e-commerce platforms to data analysis tools.Having a deep understanding of web development technologies, he is also known for his strong analytical competencies. Valerii is a responsible individual always willing to research things as thoroughly as possible to come up with original ideas. He is a communicative and self-motivated team player ready to take on new challenges and provide top-notch expertise. Outside of work, he enjoys playing chess, reading books, and staying active in the gym.

![Dayana Porcari](/media/images/dayana.height-300.format-webp.webp)

## Dayana Porcari

### Executive Assistant

Dayana holds a Bachelor's degree in Business Communication from Universidad Peruana de Ciencias Aplicadas. She has seven years of experience in project and communication direction, team oversight, event planning and digital management. Over the past five years, she has also traveled and worked as an English and Spanish interpreter and translator to different parts of Latin America.

Dayana is a highly organized, self-motivated creative. She seeks to learn about new tendencies, tools and apps as well as creating content. She enjoys challenges, seeking references and inspiration and constantly trying new ideas.

Dayana’s hobbies are sports and physical activities including Muay Thai. She is very passionate about volleyball which she currently practices and competes in. But, since balance is important, she also loves to bake and look for new food places in the city.

![Brian Fehrle](/media/images/Brian2.height-300.format-webp.webp)

## Brian Fehrle

### DBA

Brian has worked in the open source world since 2008. Starting as an apprentice, he quickly dedicated his efforts to becoming a seasoned professional, promoting PostgreSQL as the forefront of his career. He works to understand not just database systems but the applications powered by them as well.

As a serial hobbyist, he is a “jack of random trades” and is always wanting to learn something new. From Raspberry Pi projects to making soap, homebrewing, to cheese making. He is working toward a future in organic regenerative agriculture in a decentralized ecosystem.

![Maggie Samons](/media/images/maggie.height-300.format-webp.webp)

## Maggie Samons

### Project Manager

Maggie is a dynamic leader with more than nine years of professional experience. Her leadership style employs differentiated approaches to move groups toward a specific goal or achievement standard while keeping a people-first mindset.

Outside of work, Maggie enjoys hiking and anything water related when she isn’t reading.

![Hunter O'Brien](/media/images/CMD_Profile_Picture.height-300.format-webp.webp)

## Hunter O'Brien

### Jr Sysadmin/Jr DBA  


Hunter is a newly joined Jr. DBA at Command Prompt, bringing his fresh perspective and enthusiasm to the team. He holds a degree in Computer Science and is excited to develop his skills alongside some of the best professionals in the industry. Hunter is also a Marine Corps Veteran, which has instilled in him a strong work ethic and a commitment to excellence. He lives in California, where he enjoys an active lifestyle, engaging in skateboarding, surfing, and snowboarding. He shares his home with his Belgian Malinois, Nikki. Hunter is eager to contribute to Command Prompt's success and to grow both personally and professionally.

## Ready for PostgreSQL success?

Let's get on the phone and have a human-to-human conversation.

[Request a Call](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/about/our-team/)

---

# Success Stories: Case Studies

> Discover how enterprise leaders solve complex PostgreSQL bottlenecks, cut cloud costs, and prevent critical outages. Explore our case studies.

# PostgreSQL Enterprise Case Studies

Every database tells a story of growth, complexity, and resilience. Discover how engineering leaders partner with Command Prompt to protect their infrastructure, prevent critical database outages, and scale PostgreSQL with minimal business disruption.

[ Request a Strategic Discovery Call ](</contact-us/>) [ Get Support ](</support/>)

## Healthtech / Health Care

  * [The 5 TB Data Diet: Shrinking a Database Until It Fit Its New Cloud](</about/success-stories-case-studies/the-5-tb-data-diet-shrinking-a-database-until-it-fit-its-new-cloud/>)
  * [Eighteen Years on Call: From PostgreSQL 8.1 to 17, and a Nine-Minute Report Cut to 30 Seconds](</about/success-stories-case-studies/eighteen-years-on-call-from-postgresql-81-to-17-and-a-nine-minute-report-cut-to-30-seconds/>)
  * [The Migration the Monitoring Could Not See: PostgreSQL 11 to AlloyDB, Live](</about/success-stories-case-studies/the-migration-the-monitoring-could-not-see/>)
  * [Won on Features, Kept on Plumbing: Fifteen Years of Enterprise Identity Federation Behind a National Medical-Coding Platform](</about/success-stories-case-studies/fifteen-plus-years-as-the-full-stack-engineering-partner-behind-a-national-medical-coding-platform/>)
  * [From Zero Backups to a Safety Net Under a Live EMR](</about/success-stories-case-studies/from-zero-backups-to-a-safety-net-under-a-live-emr/>)
  * [From Unrecoverable to Under Control: Taming Multi-Tenant PostgreSQL at 17,000 Schemas](</about/success-stories-case-studies/from-unrecoverable-to-under-control-taming-multi-tenant-postgresql-at-17000-schemas/>)



## Fintech and Financial

  * [Two Hours, Zero Surprises: Retiring End-of-Life PostgreSQL Inside a Bank's Change Window](</about/success-stories-case-studies/two-hours-zero-surprises-retiring-end-of-life-postgres-inside-a-banks-change-window/>)
  * [Thirteen Minutes on a Saturday: Disaster Recovery a Hedge Fund Can Actually Trust](</about/success-stories-case-studies/thirteen-minutes-on-a-saturday-disaster-recovery-a-hedge-fund-can-actually-trust/>)
  * [One Outage, Zero Recurrences: Retiring PostgreSQL's Hidden Capacity Limits at a Global Financial Services Firm](</about/success-stories-case-studies/one-outage-zero-recurrences-retiring-postgresqls-hidden-capacity-limits-at-a-global-financial-services-firm/>)
  * [Audit Data Grows Forever. The Databases Stopped Growing With It: Partitioning, Archiving, and Upgrading a Core-Banking Fleet](</about/success-stories-case-studies/audit-data-grows-forever-the-databases-stopped-growing-with-it-partitioning-archiving-and-upgrading-a-core-banking-fleet/>)
  * [From Weeks to 0.8 Seconds: Planner Engineering at Billions of Rows](</about/success-stories-case-studies/from-weeks-to-08-seconds-planner-engineering-at-billions-of-rows/>)



## Connect with a PostgreSQL Advisor

**Ready to scale your platform, optimize performance, and prevent critical database outages? Connect with our team to explore strategic solutions designed to protect your data with minimal business disruption.**

[Request a Strategic Discovery Call](</contact-us/>)

## General Industries

  * [Restored to the Millisecond: An 18 TB Point-in-Time Recovery, Straight Through an Unreleased PostgreSQL Bugfix](</about/success-stories-case-studies/restored-to-the-millisecond-an-18-tb-point-in-time-recovery-straight-through-an-unreleased-postgresql-bugfix/>)
  * [Breaking the 20 TB Ceiling: A Zero-Data-Loss Exit from AWS RDS to Self-Managed PostgreSQL](</about/success-stories-case-studies/breaking-the-20-tb-ceiling-a-zero-data-loss-exit-from-aws-rds-to-self-managed-postgresql/>)
  * [240 IDs From the Wall: A Zero-Downtime bigint Rescue for a Two-Billion-Row Table](</about/success-stories-case-studies/ahead-of-the-21-billion-wall-bigint-migrations-delivered-as-pull-requests/>)
  * [Every Emergency Resolved, None Caused by PostgreSQL: Fifteen Years Running the Full Stack for a Vacation-Rental Marketplace](</about/success-stories-case-studies/case_study_emergency_resolved_none_by_postgres/>)
  * [Fifteen Years, Seven Emergencies, Zero Data Loss: Managed PostgreSQL Behind a Major Public Library Catalog](</about/success-stories-case-studies/fifteen-years-seven-emergencies-zero-data-loss-managed-postgresql-behind-a-major-public-library-catalog/>)

---
[View this page online](https://www.commandprompt.com/about/case-studies/)

---

# 9 Minutes to 30 Seconds: Modernizing Clinical Trial Analytics Across Two Decades of PostgreSQL Upgrades

> How a global clinical trials platform achieved an 18x analytics speedup and navigated two decades of PostgreSQL upgrades with zero downtime.

# From 9 Minutes to 30 Seconds

How a global clinical trials platform achieved an 18x analytics speedup and navigated two decades of PostgreSQL upgrades with zero downtime.

[ Talk to a PostgreSQL Advisor ](</contact-us/>) [ Explore Support Plans ](</support/>)

## Strategic Partnership Blueprint & System Profile

  * **Industry:** Clinical-trial medical imaging (life sciences technology)
  *  **Platform Scale:** High-throughput clinical imaging pipeline moving regulated, audit-locked patient data between global research hospitals and trial sponsors
  *  **System Architecture:** High-availability self-managed instances and Amazon RDS fleets; actively running PostgreSQL 17 in production
  *  **Partnership Longevity:** Proactive PostgreSQL engineering and advisory, ongoing since April 2008 **(18 years, 134 tickets resolved)**
  *  **Core Competencies Delivered:** Zero-Downtime Major Version Upgrades • Advanced Query Optimization • Failover Clustering & PITR • Row-Level Security (RLS) Policy Design



Metric  |  Before February 2026  |  After February 2026   
---|---|---  
PostgreSQL major version  |  13  |  17   
Slowest client-facing QC report  |  9+ minutes on PostgreSQL 13  |  ~30 seconds on PostgreSQL 17 after our rewrite (18x)   
Payment report  |  ~4 minutes on PostgreSQL 13  |  ~1.5 minutes on PostgreSQL 17   
Results at a Glance

## The Client

**In clinical research, database latency is a direct bottleneck to human health.  
  
** The client operates a global, highly regulated medical imaging network that serves as the absolute pipeline for clinical-trial data. When a hospital scans a trial patient, their platform is legally and operationally responsible for carrying that medical image securely to sponsors with the immutable chain of custody that federal regulators demand.  
  
PostgreSQL is the bedrock of this entire ecosystem, powering every patient submission, every security audit trail, and every high-level analytics report sponsors read.  
  
Because **a slow database means a slow clinical trial,** maintaining absolute database performance is not a luxury; it is a compliance prerequisite.

## The Challenge

Our partnership has spanned nearly two decades because database challenges do not stand still, they evolve with your business.  
  
Over **18 years** , the client scaled through five distinct operational eras, relying on Command Prompt to navigate each inflection point:

  *  **The Bare-Metal Era (2008):** Taming aggressive write amplification and disk I/O bottlenecks when legacy autovacuum parameters fell behind on PostgreSQL 8.1.
  *  **The High-Availability Transition (Early 2010s):** Re-architecting a single-point-of-failure database server into a robust, geographically redundant failover cluster with Point-in-Time Recovery (PITR).
  *  **The 2.1 Billion Wall (2013):** **Busting** a critical, production-stopping emergency when image submissions suddenly crashed under a mysterious **32-bit integer overflow**.
  *  **The Cloud Hijack (2021):** Bailing out a high-risk cloud migration after an out-of-band jump from PostgreSQL 9.6 to 13 on AWS RDS that was executed (without our advisory) left production highly unstable.
  *  **The Sub-Minute Mandate (2026):** Optimizing reporting infrastructure during a **PostgreSQL 17 major version upgrade** to meet a strict SLA requiring every custom analytics query to return in under 60 seconds.



## The Solution

As their long-term **trusted expert advisors** , we met each challenge with hands-on systems engineering, not static reports:

  *  **Forensics & Vacuum Engineering:** Instead of blindly running VACUUM, we performed deep free-space map accounting to resolve chronic bloat on high-turnover tables.
  *  **Fail-Safe Clustering:** We engineered and deployed their original DRBD and Corosync/Pacemaker high-availability stack, scaling it seamlessly to multi-instance PostgreSQL clusters as their trial volume doubled.
  *  **Bypassing the Signed 32-Bit Overflow:** When image submissions halted with numeric value out of range, our engineers traced the failure within hours. The database was healthy, but a signed 32-bit integer cast in the application stack was converting Large Object IDs past 2.1 billion into corrupted negative strings. We patched the logic, restoring system integrity.
  *  **High-Performance Row-Level Security (RLS):** To guarantee complete data isolation between competing trial sponsors, we spent years designing, testing, and optimizing **HIPAA-compliant row-level-security (RLS) policies**. By restructuring complex-join filters, we ensured absolute tenant isolation without sacrificing query latency.



## The Results

In February 2026, the platform successfully cut over from PostgreSQL 13 (End-of-Life since November 2025) to **PostgreSQL 17**.

Our proactive performance tuning and index optimization delivered immediate, transformative business outcomes:

  *  **QC Report Optimization:** Slashed the platform’s slowest client-facing QC report from **over 9 minutes to just 30 seconds, resulting in** an **18x (1,700%) performance increase** that completely eliminated trial sponsor delay.
  *  **Operational Speedup:** Cut payment processing reports from **4 minutes to 1.5 minutes**.
  *  **Flawless Outage Record:** Resolved **11 of 11 critical production-level emergencies** with zero data loss over an 18-year lifecycle.
  *  **Continuous Modernization:** Guided an active database from **PostgreSQL 8.1 to 17** without a single hour of unplanned downtime or platform regressions.



## The Strategic Takeaway

When a database scales across nearly two decades and nine major version upgrades, the greatest risk is the loss of institutional memory.

  
Every time a database is handed off to a new faceless utility support desk, critical architectural context is lost.  
  
Because we have engineered this platform's database lifecycle alongside their team since PostgreSQL 8.1, our engineers didn't need to waste days studying schemas, investigating the performance tax of sponsor-isolation RLS, or guessing how the medical imaging pipeline behaves under load. We carried that architectural memory forward.  
  
This level of continuous, proactive partnership transforms a database from a fragile, reactive bottleneck into a quiet, high-performing asset and allowing their engineering team to focus entirely on life-saving clinical trial software.

## Facing Complex PostgreSQL Performance or Scale Challenges?

Whether you're planning a major version upgrade, resolving query latency, or escaping cloud vendor lock-in, let's look at your architecture together. Speak with us today to evaluate your best options.

[Speak with a PostgreSQL Advisor](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/about/case-studies/clinical-trials-portal-postgresql-upgrades-performance-tuning/)

---

# Support

> Enterprise PostgreSQL, Linux and Open Source support since 1997. 24x7x365 coverage, no per-instance pricing, under-1-hour response for SLA clients. Multiple options to fit your situation.

# Support for Postgres and Open Source

24x7x365 Enterprise support for Postgres centered Open Source stack

[ Contact us ](</contact-us/>) [ Emergency Support ](</support/emergency-support/>)

## Your Postgres and Open Source problems are our specialty.

Command Prompt works with your team directly — no call centers, no escalation queues, no per-instance pricing. When you call, you're talking to a Command Prompt engineer who already knows your system. It is our comprehensive experience since 1997 that allows us to help your organization succeed with Postgres and Open Source.

  * [Success Stores and Case Studies](</about/success-stories-case-studies/>)
  * [Alternatives:](</alternatives/>) Honest comparisons to the competition



## What brings most clients to us

![Postgres Support](/media/images/postgres-support-icon-600.height-300.format-webp.webp)

## Postgres Support

Any platform, any version, 24x7x365 — [Audax Postgres](</products/audax-postgres/>), community PostgreSQL, RDS, Aurora, Azure, Google Cloud, and more, supported by engineers who know your system.

[ Learn More ](</support/postgres-support/>)

![Emergency Support](/media/images/recovery.height-300.format-webp.webp)

## Emergency Support

Something is broken in production right now and you need help. If you are in an outage / emergency situation please call +1.503.667.4564. If you are not a support contract client, emergency rates will apply.

[ Learn More ](</support/emergency-support/>)

![Postgres End of Life \(EOL\) support](/media/images/eol-support-icon-600.height-300.format-webp.webp)

## Postgres End of Life (EOL) support

Running a version past community EOL? We bring stability to your enterprise by supporting every release up to 8 years from release — 3 beyond EOL.

[ Learn More ](</support/support-for-eol-versions-of-postgres/>)

## Support Plans

Multiple engagement options, select the best fit for how your organization operates or your highest priority at the moment.

Feature  |  Adhoc Consulting  |  Standard SLA  |  Proactive SLA (PSLA)   
---|---|---|---  
Postgres and full-stack Professional services  |  Yes  |  Yes  |  Yes   
Service Level Agreement  |  No  |  Yes  |  Yes   
24x7x365 coverage  |  Yes*  |  Yes  |  Yes   
Under-1-hour emergency response*  |  No  |  Yes  |  Yes   
Fixed hourly rate (no surge pricing)  |  No  |  Yes  |  Yes   
Immunity from after-hours & emergency rates  |  No  |  Yes  |  Yes   
Priority response queue  |  |  Yes  |  Yes   
Billing cycle  |  Retainer + monthly  |  Monthly/Annual  |  Monthly/Annual   
Best for  |  Flexible/project work  |  Ongoing production coverage  |  Fully supported operational health   
* subject to afterhours, emergency and holiday rates

## Contact us

Reach out! We would love to be part of your success story with Postgres and Open Source.

[Learn More](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/support/)

---

# Support for EOL versions of Postgres

> Get 8 years of PostgreSQL support, FedRAMP compliant patching and first class support and consulting from the only Postgres company operating since 1997.

# Enterprise class Postgres support

With FedRAMP compliant patching and 3 extra years of support

[ Contact us ](</contact-us/>) [ Get Support ](</support/>)

## Audax Postgres Extended (EOL) Support: PgLTS

### **Versioning Policy**

The PostgreSQL Global Development Group releases a new major version containing new features every year in late September to early October. The standard lifespan of a community supported release of PostgreSQL is 5 years.

Command Prompt with an appropriate [support contract](</support/>) will provide 24x7x365 support for EOL versions of PostgreSQL up to 8 years from the initial release date. This extends the support lifecycle of a PostgreSQL release by 3 years. The support timelines are listed in the below grid. [Contact us today](</contact-us/>).

### You may also want to read about:

  * [Audax Postgres product page](</products/audax-postgres/>)
  * [Postgres and Open Source Support](</support/postgres-support/>)



Version  |  Released  |  End of Life  |  Extended Support Until  |  Security (CVE) backpatch support   
---|---|---|---|---  
10  |  Oct 5, 2017  |  Nov 10, 2022  |  N/A  |  N   
11  |  Oct 18, 2018  |  Nov 9, 2023  |  Nov 30, 2026  |  N   
12  |  Oct 3, 2019  |  Nov 14, 2024  |  Nov 30, 2027  |  Y   
13  |  Sept 24, 2020  |  Nov 13, 2025  |  Nov 30, 2028  |  Y   
14  |  Sept 30, 2021  |  Nov 12, 2026  |  Nov 30, 2029  |  Y   
15  |  Oct 13, 2022  |  Nov 11, 2027  |  Nov 30, 2030  |  Y   
16  |  Sept 14, 2023  |  Nov 9, 2028  |  Nov 30, 2031  |  Y   
17  |  Sept 26, 2024  |  Nov 8, 2029  |  Nov 30, 2032  |  Y   
18  |  Sept 25, 2025  |  Nov 14, 2030  |  Nov 30, 2033  |  Y   
Supported Releases Timeline

---
[View this page online](https://www.commandprompt.com/support/support-for-eol-versions-of-postgres/)

---

# Postgres Support

> Postgres and Open Source Support from North America's oldest Postgres Company

# Postgres success since 1997

Only Command Prompt has been helping companies with PostgreSQL and Open Source since 1997.

[ Contact us ](</contact-us/>) [ Learn More ](</about/success-stories-case-studies/>)

## Why Command Prompt for Postgres Support

Since 1997, Command Prompt has been providing best in class Postgres and Open Source Support. Our Professional services are Full Stack and cover a wide range of technologies beyond Postgres. There is no other company that provides the breadth and depth of expertise for PostgreSQL. Our team of experts is specifically versed in multiple technologies to enable your enterprise to be successful with Postgres. Read more at [Success stories and Case studies.](</about/success-stories-case-studies/>)

## What about End of Life or Extended support?

Command Prompt provides End of Life or Extended support for any version of PostgreSQL. We provide support for up to 8 years from original release date and 3 years after EOL.

  * [More on EOL/Extended Support](</support/support-for-eol-versions-of-postgres/>)



## What Postgres versions does Command Prompt Support?

We provide Postgres Support for any platform including (but not limited to):

  * [Audax Postgres](</products/audax-postgres/>)
  * Open Source PostgreSQL
  * EnterpriseDB Postgres Advanced Server
  * AWS RDS PostgreSQL
  * AWS Aurora for PostgreSQL
  * Azure for PostgreSQL
  * Google Cloud Postgres
  * Google AlloyDB
  * PgEdge Distributed Postgres

---
[View this page online](https://www.commandprompt.com/support/postgres-support/)

---

# PostgreSQL Feature Matrix

|  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
64-bit large objects  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Advisory locks  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Custom background workers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Disk based FSM  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Dynamic Background Workers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
EXPLAIN (BUFFERS) support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
EXPLAIN (WAL) support  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
"jsonlog" logging format  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Loadable plugin infrastructure for monitoring the planner  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Payload support for LISTEN/NOTIFY  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_stat_io - I/O metrics view  |  Yes  |  No  |  No  |  No  |  No  |  No   
Server statistics in shared memory  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
SQL-standard information schema  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Support for anonymous shared memory  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
XML, JSON and YAML output for EXPLAIN  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
|  |  |  |  |  |   
The Postgres Backend (Server) |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Arrays of compound types  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Array support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ENUM data type  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
GUID/UUID data type  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
macaddr8 data type  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Multiranges  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
NULLs in Array  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Phrase search  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Range types  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
smallserial type  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Type modifier support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
XML data type  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Data Types, Functions, & Operator capability |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Block-range (BRIN) indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
B-tree bottom-up index deletion  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
B-tree deduplication  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Concurrent GiST indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Covering Indexes for B-trees (INCLUDE)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Covering indexes for GiST (INCLUDE)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Deferrable unique constraints  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Exclusion constraints  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
GIN (Generalized Inverted Index) Indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
GIN indexes partial match  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
GIN Index performance and size improvements  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
GiST (Generalized Search Tree) Indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Indexes on expressions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Index-only scans  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Index-only scans on GiST  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Index support for IS NULL  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
In-memory Bitmap Indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
K-nearest neighbor GiST support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
K-nearest neighbor SP-GiST Support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Non-blocking CREATE INDEX  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel B-tree index scans  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallelized CREATE INDEX for B-tree indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Space-Partitioned GiST (SP-GiST) Indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SP-GiST indexes for range types  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
UNIQUE NULLS NOT DISTINCT  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
WAL support for hash indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Indexing and Constraint features |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
ANY_VALUE aggregate  |  Yes  |  No  |  No  |  No  |  No  |  No   
FETCH FIRST .. WITH TIES  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
GROUPING SETS, CUBE and ROLLUP support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
INSERT/UPDATE/DELETE RETURNING  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
LATERAL clause  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
MERGE  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Multirow VALUES  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Non-decimal integer literals  |  Yes  |  No  |  No  |  No  |  No  |  No   
ORDER BY NULLS FIRST/LAST  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
range_agg range type aggregation function  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Recursive Queries  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
regexp_count, regexp_instr, regexp_like  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Row-wise comparison  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SELECT FOR NO KEY UPDATE/SELECT FOR KEY SHARE lock modes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SQL standard interval handling  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SYSTEM_USER  |  Yes  |  No  |  No  |  No  |  No  |  No   
TABLE statement  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Underscores (_) for thousands separators  |  Yes  |  No  |  No  |  No  |  No  |  No   
unnest/array_agg  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Upsert (INSERT ... ON CONFLICT DO ...)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Window functions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
WITHIN GROUP clause  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
WITH ORDINALITY clause  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
WITH Queries (Common Table Expressions)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Writable WITH Queries (Common Table Expressions)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Structured Query Language (SQL) features |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
ALTER object IF EXISTS  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ALTER TABLE ... ADD UNIQUE/PRIMARY KEY USING INDEX  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ALTER TABLE ... SET ACCESS METHOD  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
ALTER TABLE ... SET LOGGED / UNLOGGED  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Changing column types (ALTER TABLE .. ALTER COLUMN TYPE)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
CREATE ACCESS METHOD  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
CREATE TABLE ... (LIKE) with foreign tables, views and composite types  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
DROP object IF EXISTS  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ON COMMIT clause for CREATE TEMPORARY TABLE  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
REINDEX CONCURRENTLY  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Stored Generated Columns  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Typed tables  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Data Definition Language (DDL) |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Abbreviated Keys  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Asynchronous Commit  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Automatic plan invalidation  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Background Checkpointer  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Background Writer  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Base backup throttling  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
CREATE STATISTICS - most-common values (MCV) statistics  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
CREATE STATISTICS - multicolumn  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
CREATE STATISTICS - "OR" and "IN/ANY" statistics  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Cross datatype hashing support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Distributed checkpointing  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Foreign keys marked as NOT VALID  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Frozen page map  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Full Text Search  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Hash aggregation can use disk  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Hashing support for DISTINCT/UNION/INTERSECT/EXCEPT  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Hashing support for FULL OUTER JOIN, LEFT OUTER JOIN and RIGHT OUTER JOIN  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Heap Only Tuples (HOT)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Improved performance for sorts exceeding working memory  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Improved window function performance  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Incremental sort  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Incremental sort for SELECT DISTINCT  |  Yes  |  No  |  No  |  No  |  No  |  No   
Incremental sort for window functions  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Inlined WITH Queries (Common Table Expressions)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Inlining of SQL-functions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Just-in-Time (JIT) compilation for expression evaluation and tuple deforming  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Load balancing for libpq / psql  |  Yes  |  No  |  No  |  No  |  No  |  No   
LZ4 compression for TOAST tables  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Multi-core scalability for read-only workloads  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Multiple temporary tablespaces  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Outer Join reordering  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel bitmap heap scans  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel FULL and RIGHT joins  |  Yes  |  No  |  No  |  No  |  No  |  No   
Parallel full table scans (sequential scans)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel hash joins  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel JOIN, aggregate  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel merge joins  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel query  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel "SELECT DISTINCT" |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Partial sort capability (top-n sorting)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Query pipelining  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Reduced lock levels for ALTER TABLE commands  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SELECT ... FOR UPDATE/SHARE NOWAIT  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Set costs specific to TABLESPACEs  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Shared row level locking  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SIMD support for ARM  |  Yes  |  No  |  No  |  No  |  No  |  No   
SIMD support for x86  |  Yes  |  No  |  No  |  No  |  No  |  No   
SKIP LOCKED clause  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Synchronized sequential scanning  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
TABLESAMPLE clause  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Tablespaces  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Unlogged tables  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
WAL Buffer auto-tuning  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Performance  |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Improved set of JSON functions and operators  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
JSONB data type  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
JSONB-modifying operators and functions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
JSONB Subscripting  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
JSON data type  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SQL/JSON constructors  |  Yes  |  No  |  No  |  No  |  No  |  No   
SQL/JSON: datetime()  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
SQL/JSON IS JSON  |  Yes  |  No  |  No  |  No  |  No  |  No   
SQL/JSON path expressions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
NoSQL/JSON |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Accelerated partition pruning  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Declarative table partitioning  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Default Partition  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Foreign Key references for partitioned tables  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Foreign table inheritance  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Partitioning by a hash key  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Partition pruning during query execution  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Support for PRIMARY KEY, FOREIGN KEY, indexes, and triggers on partitioned tables  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Table Partitioning  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
UPDATE on a partition key  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Partitioning and Inheritance |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Materialized Views  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Materialized views with concurrent refresh  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SECURITY INVOKER views  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Temporary VIEWs  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Updatable views  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
WITH CHECK clause  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Views  |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
ALTER SUBSCRIPTION ... SKIP  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Cascading streaming replication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Configure max WAL retention for replication slots  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Logical replication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Logical replication avoids replication loops  |  Yes  |  No  |  No  |  No  |  No  |  No   
Logical replication column lists  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Logical replication for partitioned tables  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Logical replication from standbys  |  Yes  |  No  |  No  |  No  |  No  |  No   
Logical replication initial sync using binary protocol  |  Yes  |  No  |  No  |  No  |  No  |  No   
Logical replication lookups with additional indexes  |  Yes  |  No  |  No  |  No  |  No  |  No   
Logical replication parallel apply of transactions  |  Yes  |  No  |  No  |  No  |  No  |  No   
Logical replication publish all tables in schema  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Logical replication row filtering  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Logical replication stream in-progress transactions  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Logical replication subscriber can disable on error  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Quorum commit for synchronous replication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Replication Slots  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Streaming-only cascading replication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Streaming Replication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Synchronous replication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Replication capabilities including High Availability Core |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Archive modules  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Checksum on data pages  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Enable/Disable page checksums in an offline cluster  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Generic WAL facility  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Hot Standby  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
lz4 and Zstandard (zstd) compression for WAL full page writes  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
min_wal_size / max_wal_size  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Multiple synchronous standbys  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Named restore points  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel pg_dump  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Parallel restore  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_basebackup client decompression  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
pg_basebackup server-side compression  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
pg_basebackup tool  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_receivewal (formerly pg_receivexlog)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Point-in-Time Recovery  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Pre-fetch WAL during recovery  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
remote_apply mode  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Time-delayed Standbys  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Verify backup integrity (pg_verifybackup)  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Warm Standby  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Backup, Restore and Data Integrity |  |  |  |  |  |   
---|---|---|---|---|---|---  
COPY from/to STDIN/STDOUT  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
COPY FROM ... WHERE  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
COPY with arbitrary SELECT  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
CSV support for COPY  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Data Import and Export (Core features only, does not include extensions) |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
ALTER SYSTEM  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Fractional input for "integer" values  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Include directives for pg_hba.conf and pg_ident.conf  |  Yes  |  No  |  No  |  No  |  No  |  No   
Per user/database server configuration settings  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_config system view  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Regular expression matching in pg_hba.conf and pg_ident.conf  |  Yes  |  No  |  No  |  No  |  No  |  No   
Configuration Management |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Channel binding for SCRAM authentication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Client can require SCRAM channel binding  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Client-specified requirements for authentication  |  Yes  |  No  |  No  |  No  |  No  |  No   
Column level permissions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Default permissions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
GRANT/REVOKE ON ALL TABLES/SEQUENCES/FUNCTIONS  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
GSSAPI client and server-side encryption  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
GSSAPI support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Kerberos credential delegation  |  Yes  |  No  |  No  |  No  |  No  |  No   
Large object access controls  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
LDAP server discovery  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Multifactor authentication via valid client SSL/TLS certificate  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Native LDAP authentication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Native RADIUS authentication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Per user/database connection limits  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Predefined roles  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Privileges for setting configuration parameters  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
ROLES  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Row-Level Security  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SCRAM-SHA-256 Authentication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Search+bind mode operation for LDAP authentication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
security_barrier option on views  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Security Service Provider Interface (SSPI)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SSL certificate validation in libpq  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SSL client certificate authentication  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SSPI authentication via GSSAPI  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Support using the client's OS trusted CA.  |  Yes  |  No  |  No  |  No  |  No  |  No   
Security and Compliance |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Cursors  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Savepoints  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Serializable Snapshot Isolation  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Two Phase commit  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Updatable cursors  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Transactions and Visibility |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Inserted data can trigger autovacuum  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Integrated autovacuum daemon  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Page freezing optimizations  |  Yes  |  No  |  No  |  No  |  No  |  No   
Parallelized VACUUM for Indexes  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Parallel vacuumdb jobs  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Vacuum "emergency mode" |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Visibility Map for Vacuuming  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Vacuum and Maintenance |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Certificate authentication with postgres_fdw  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Foreign data wrapper query parallelism  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Foreign data wrappers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Foreign Tables  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
IMPORT FOREIGN SCHEMA  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Import foreign table partitions  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
Parallel query execution on remote databases  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
postgres_fdw parallel commit  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
postgres_fdw pushdown  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
PostgreSQL Foreign Data Wrapper  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Writable Foreign Data Wrappers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Foreign Data Wrappers (SQL/MED) |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
ALTER TABLE ENABLE/DISABLE TRIGGER  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ALTER TABLE / ENABLE REPLICA TRIGGER/RULE  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
BEGIN ATOMIC function bodies  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
CALL syntax for executing procedures  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Column level triggers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
CREATE PROCEDURE syntax for SQL stored procedures  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Event triggers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
FILTER clause for aggregate functions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ORDER BY support within aggregates  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Per function GUC settings  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Per function statistics  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
RETURN QUERY EXECUTE  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
RETURNS TABLE  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Statement level triggers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Statement level TRUNCATE triggers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Triggers on views  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Variadic functions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
WHEN clause for CREATE TRIGGER  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
UDFs, Stored Procedures and Triggers |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
CASE in pl/pgsql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
CONTINUE statement for PL/pgSQL  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
CREATE TRANSFORM  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
DO statement for pl/perl  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
DO statement for pl/pgsql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
EXCEPTION support in PL/pgSQL  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
EXECUTE USING in PL/pgSQL  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
FOREACH IN ARRAY in pl/pgsql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
IN/OUT/INOUT parameters for pl/pgsql and PL/SQL  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Named parameters  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Non-superuser language creation  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pl/pgsql installed by default  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Polymorphic functions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Python 3 support for pl/python  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Qualified function parameters  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Query parallelism for RETURN QUERY  |  Yes  |  Yes  |  Yes  |  No  |  No  |  No   
RETURN QUERY in pl/pgsql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ROWS and COST specification for functions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Scrollable and updatable cursor support for pl/pgsql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
SQLERRM/SQLSTATE for pl/pgsql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Unicode object support in PL/python  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
User defined exceptions  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Validator function for pl/perl  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Procedural Languages (Core features only, does not include Extensions or External capabilities) |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
CREATE EXTENSION .. CASCADE  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Extension Installation  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Trusted Extensions  |  Yes  |  Yes  |  Yes  |  Yes  |  No  |  No   
Extensions |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Column-level collation support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Database level Collation  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Default ICU collations for clusters/databases  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
EUC_JIS_2004/ SHIFT_JIS_2004 support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ICU collations  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Multibyte encoding support, incl. UTF8  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Multiple language support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Nondeterministic collations  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  No   
Unicode string literals and identifiers  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
UTF8 support on Windows  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Internationalization |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
pgbench  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_prewarm  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_rewind  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_standby  |  Obsolete  |  Obsolete  |  Obsolete  |  Yes  |  Yes  |  Yes   
pg_upgrade  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_waldump  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
psql \bind  |  Yes  |  No  |  No  |  No  |  No  |  No   
psql \dconfig  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
Version aware psql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Client Applications (Core only, does not include 3rd party options) |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
adminpack  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
auth_delay  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
auto_explain  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
btree_gin  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
btree_gist  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
citext  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
dblink  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
dblink asyncronous notification support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
file_fdw  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
fuzzystrmatch  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
hstore  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
intarray  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
isn (ISBN)  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
KNN support for CUBE  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
ltree  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pageinspect  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
passwordcheck  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_buffercache  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_freespacemap  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_stat_statements  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_stat_statements improvements  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pgstattuple  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_trgm  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_trgm regular expressions indexing  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
pg_walinspect  |  Yes  |  Yes  |  No  |  No  |  No  |  No   
seg  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
sepgsql  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
sslinfo  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
tablefunc  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
tcn  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
unaccent  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
uuid-ossp  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Additional Modules |  16  |  15  |  41  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Full SSL support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
IPv6 Support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
V3 client protocol  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Network and Protocol |  16  |  15  |  14  |  13  |  12  |  11   
---|---|---|---|---|---|---  
Microsoft Visual C++ Support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Native Windows Port  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Spinlock support for the SuperH hardware platform  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Sun Studio compiler on Linux  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Windows x64 support  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes  |  Yes   
Platforms

---
[View this page online](https://www.commandprompt.com/support/postgresql-feature-matrix/)

---

# Emergency Support

> Emergency Support for your Postgres and Open Source stack

# Emergency Support for your Full Stack

Postgres, Linux and other Open Source software, we are your one stop solution for emergency support

[ Existing SLA Client ](<https://redmine.commandprompt.com/>) [ New Client ](</contact-us/>)

### Existing SLA Clients

  1. If you are an existing client, email your client environment with the word EMERGENCY in the subject line with the issue you are experiencing.
  2. [Login into your client environment](<https://redmine.commandprompt.com/>) and create a new Issue with Emergency status.



### New Clients (non-existing)

  1. If you are a new client looking to establish emergency services please call +1.503.667.4564. Note that a credit card will be required and emergency rates will apply.
  2. As emergency service without an SLA is expensive, if this is not an emergency we strongly suggest you contact us via the [contact form](<https://www.commandprompt.com/contact-us/>) or [email us](<mailto:sales@commandprompt.com?subject=New%20Client%20Inquiry>) to establish service.

---
[View this page online](https://www.commandprompt.com/support/emergency-support/)

---

# Terms of Use

> terms of use

## Legal

## AGREEMENT TO TERMS OF USE

These Terms and Conditions of Use (the "Terms of Use") apply to the Command Prompt Website located at www.commandprompt.com (the "Website"), which is the property of Command Prompt Inc. ("Command Prompt") and its licensors. By using or visiting the Website, you agree to comply with, and be bound by, these Terms of Use and all applicable laws and regulations. Please review the following Terms of Use carefully. If you do not agree to these Terms of Use, you may not access or use the Website and you should immediately exit the Website. The terms "we" "our" refer to Command Prompt. The terms "you" and "your" refer to the user or viewer of the Website

Command Prompt reserves the right, at its sole discretion, to change, modify, add or remove portions of these Terms of Use at any time without notice. It is your responsibility to check these Terms of Use periodically for changes. Your continued use of the Website following the posting of changes will mean that you accept and agree to the changes. As long as you comply with these Terms of Use, Command Prompt grants you a personal, non-exclusive, non-transferable, limited privilege to enter and use the Website which shall be defined by these Terms of Use as follows:  
  


## CONTENT

All content available on the Website including, without limitation, text, graphics, user interfaces, visual interfaces, photographs, logos, sounds, music, artwork and computer code (collectively, "Content"), including but not limited to the design, structure, selection, coordination, expression, "look and feel" and arrangement of such Content, contained on the Website is owned, controlled or licensed by or to Command Prompt, and is protected by laws relating to trade dress, copyright, patent, unfair competition, trademark, and/or other forms of intellectual property rights and by other applicable law and Command Prompt reserves and retains all rights in and to such Content.

The name and mark "Command Prompt" and any other names, marks, logos, graphics, designs, webpage designs, and icons of Command Prompt used in connection with the Website are registered or unregistered trademarks, service marks, or trade dress of Command Prompt (the "Marks"). You may not use the Marks other than in connection with any incidental use as necessary to view and access the Website. Without limiting the foregoing, you shall not be permitted to use any of the Marks or any other names or marks that are similar to, or likely to cause confusion with, any of the Marks.

Except as expressly provided in these Terms of Use, no part of the Website and no Content or Marks may be copied, reproduced, republished, uploaded, posted, publicly displayed, encoded, translated, transmitted or distributed in any way (including "mirroring") to any other computer, server, website or other medium for publication or distribution or for any commercial enterprise, without Command Prompt's express prior written consent.

You may use information on Command Prompt products and services (such as data sheets, knowledge base articles, and similar materials) purposely and explicitly made available, with written permission, by Command Prompt for downloading from the Website, provided that you (1) do not remove any proprietary notice language in all copies of such documents, (2) use such information only for your personal, non-commercial informational purpose and do not copy or post such information on any networked computer or broadcast it in any media, (3) make no modifications to any such information, and (4) do not make any additional representations or warranties relating to such documents.

Command Prompt is not responsible for the conduct, whether online or offline, of any user of the Website.  
  


## YOUR USE OF THE WEBSITE

Except solely as necessary for you to access the Website for its intended purpose, you may not copy, modify, translate, distribute, transmit, publish, republish, perform, display, post, download, upload, frame, sublicense or sell the Content or any portion thereof. Except as expressly set forth in these Terms of Use, these Terms of Use do not, and shall not be interpreted or construed to, grant to you any license to any intellectual property rights or other proprietary rights, including any implied licenses or licenses granted by estoppels or otherwise.

You may not use any "deep-link", "page-scrape", "robot", "spider" or other automated device, program, algorithm or methodology, or any similar or equivalent manual process, to access, acquire, copy or monitor any portion of the Website or any Content, or in any way reproduce or circumvent the navigational structure or presentation of the Website or any Content, to obtain or attempt to obtain any materials, documents or information through any means not purposely and explicitly made available, with written permission, through the Website.

You may not attempt to gain unauthorized access to any portion or feature of the Website, or any other systems or networks connected to the Website or to any Command Prompt server, or to any of the services offered on or through the Website, by hacking, password "mining" or any other illegitimate means.

You may not probe, scan or test the vulnerability of the Website or any network connected to the Website, nor breach the security or authentication measures on the Website or any network connected to the Website.

You agree that you will not take any action that imposes an unreasonable or disproportionately large load on the infrastructure of the Website or Command Prompt's systems or networks, or any systems or networks connected to the Website or to Command Prompt.

You agree not to use any device, software or routine to interfere or attempt to interfere with the proper working of the Website or any transaction being conducted on the Website, or with any other person's use of the Website.

You may not forge headers or otherwise manipulate identifiers in order to disguise the origin of any message or transmittal you send to Command Prompt on or through the Website or any service offered on or through the Website. You may not pretend that you are, or that you represent, someone else, or impersonate any other individual or entity.

You may not use the Website or any Content, or post any messages or content, for any purpose that is unlawful or prohibited by these Terms of Use, or to solicit the performance of any illegal activity or other activity which infringes the rights of Command Prompt or others.  
  


## CHANGES TO SERVICE AND SUSPENSION OF SERVICE

Command Prompt reserves the right, in its sole discretion, to change, suspend, discontinue, or terminate the Website or any and all content, applications, materials, and other items used or contained in the Website at any time and from time to time and without notice or explanation, for any or no reason, and without any liability to you. Command Prompt reserves the right in its sole discretion, to deny, restrict, suspend, discontinue, or terminate your access to the Website or any portion thereof at any time, with or without prior notice or explanation, for any or no reason, and without any liability to you.  
  


## COMMERCIAL TRANSACTIONS

Additional terms and conditions may apply to purchases of goods or services and to specific portions or features of the Website, including contests, promotions or other similar features, all of which terms are made a part of these Terms of Use by this reference. You agree to abide by such other terms and conditions, including where applicable representing that you are of sufficient legal age to use or participate in such service or feature. If there is a conflict between these Terms of Use and the terms posted for or applicable to a specific portion of the Website or for any service offered on or through the Website, the latter terms shall control with respect to your use of that portion of the Website or the specific service.

Command Prompt's obligations, if any, with regard to its products and services are governed solely by the agreements pursuant to which they are provided, and nothing on this Website should be construed to alter such agreements

Command Prompt may make changes to any products or services offered on the Website, or to the applicable prices for any such products or services, at any time, without notice. The materials on the Website with respect to products and services may be out of date, and Command Prompt makes no commitment to update the materials on the Website with respect to such products and services.  
  


## ACCOUNTS, PASSWORDS AND SECURITY

Certain features or services offered on or through the Website may require you to open an account. You are entirely responsible for maintaining the confidentiality of your account information, including your password, and for any and all activity that occurs under your account. You agree to notify Command Prompt immediately of any unauthorized use of your account or password, or any other breach of security. However, you may be held liable for losses incurred by Command Prompt or any other user of or visitor to the Website due to someone else using your ID, password or account.

You may not use anyone else's ID, password or account at any time without the express permission and consent of the holder of that ID, password or account. Command Prompt cannot and will not be liable for any loss or damage arising from your failure to comply with these obligations.

Registration for an account is void where the user lacks the eligibility for registration or such registration is otherwise prohibited. Registration for an account, any part of the Website or any service provided by Command Prompt is limited to users thirteen (13) years of age or older. Any registration by any user under thirteen (13) years of age is expressly prohibited. By submitting registration information, you represent and warrant that you are thirteen (13) years of age or older, that all registration information you submit is truthful and accurate, that you will maintain the accuracy of such information, that you agree to abide by the terms and conditions of these Terms of Use, and that your registration does not and will not violate any applicable law or regulation. A person who is eligible and desires to create an account may, upon consenting to these Terms of Use, submit an application to register in accordance with the procedures set forth by Command Prompt. Command Prompt reserves the right, in its sole discretion, to deny, restrict, suspend, discontinue, or terminate your account, with or without prior notice or explanation, for any or no reason, without any liability to you.  
  


## PRIVACY

Command Prompt's Privacy Policy applies to use of this Website. The Privacy Policy is incorporated into these Terms of Use by this reference. Additionally, by using the Website, you acknowledge and agree that Internet transmissions are never completely private or secure. You understand that any message or information you send to the Website may be read or intercepted by others, even if there is a special notice that a particular transmission (for example, credit card information) is encrypted. By using the Website, you consent to have your personal data transferred to, and processed in, the United States.  
  


## THIRD PARTY WEBSITES

This Website may contain links to other independent third-party websites ("Linked Sites") and content (including, without limitation, text, photographs, images, graphics, designs, audio, video, games, applications, software, and files) owned by, or originating from, third parties ("Third Party Content"). Such Linked Sites and Third Party Content are not under Command Prompt's control, and Command Prompt is not responsible for and does not endorse the content of such Linked Sites, including any information or materials contained on such Linked Sites. Command Prompt’s inclusion of any linked website or third party content on the Website does not imply approval, partnership, or endorsement of such website or content by Command Prompt. If you follow a link to a Linked Site or otherwise access a third party website, you do so solely at your own risk, and Command Prompt's Privacy Policy and other policies and practices, including these Terms of Use, do not apply to your use or access of such Linked Sites. Command Prompt takes no responsibility for third party advertisements or third party applications that are posted on or through the Website, nor does it take any responsibility for the goods or services provided by its advertisers. Reference to any products, services, content, or other information, whether by trade name, trademark, service mark, manufacturer, supplier, or otherwise, does not constitute or imply sponsorship, endorsement, or recommendation by, or any affiliation with, Command Prompt. You will need to make your own independent judgment regarding your interaction with these Linked Sites.  
  


## DISCLAIMERS

YOU EXPRESSLY AGREE THAT YOUR USE OF THE WEBSITE IS AT YOUR SOLE RISK. THE WEBSITE, INCLUDING ANY CONTENT, APPLICATIONS OR MATERIALS PROVIDED BY OR ON THE WEBSITE, ARE PROVIDED ON AN .AS IS. BASIS AND COMMAND PROMPT HEREBY EXPRESSLY DISCLAIMS ALL REPRESENTATIONS AND WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.

COMMAND PROMPT CANNOT AND DOES NOT GUARANTEE ANY SPECIFIC RESULTS FROM THE USE OF THE WEBSITE. COMMAND PROMPT SPECIFICALLY DOES NOT MAKE ANY CLAIM OR WARRANTY THAT THE SERVICES OR ACCESS TO THE WEBSITE WILL BE UNINTERRUPTED OR ERROR-FREE AND ASSUMES NO RESPONSIBILITY FOR ANY ERROR, OMISSION, INTERRUPTION, DELETION, DEFECT, DELAY IN OPERATION OR TRANSMISSION, COMMUNICATIONS LINE FAILURE, THEFT OR DESTRUCTION, OR UNAUTHORIZED ACCESS TO, OR ALTERATION OF, ANY CONTENT OR ANY USER COMMUNICATION OR MESSAGE. COMMAND PROMPT DOES NOT REPRESENT OR WARRANT THAT APPLICATIONS, CONTENT, DATA, OR MATERIALS ON THE WEBSITE OR DOWNLOADED THROUGH THE WEBSITE ARE ACCURATE, COMPLETE, RELIABLE, CURRENT, OR ERROR-FREE OR THAT THE WEBSITE OR ANY APPLICATIONS OR CONTENT PROVIDED BY COMMAND PROMPT ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS. ACCORDINGLY, YOU SHOULD ALWAYS EXERCISE CAUTION IN THE USE AND/OR DOWNLOADING OF ANY SUCH APPLICATIONS, CONTENT, DATA, OR MATERIALS AND USE INDUSTRY-RECOGNIZED SOFTWARE TO DETECT AND DISABLE OR BLOCK VIRUSES, MALWARE, AND OTHER MALICIOUS CODE. YOU ARE SOLELY RESPONSIBLE FOR YOUR USE OF ANY OF THE FOREGOING AND ANY DAMAGES TO YOUR MOBILE DEVICE, COMPUTER, DATABASE, OR COMPUTER SYSTEM, ANY LOSS OF DATA, AND ANY OTHER DAMAGE OR HARM OF ANY KIND THAT MAY RESULT FROM ANY OF THE FOREGOING. COMMAND PROMPT CANNOT AND DOES NOT GUARANTEE THAT ANY DEFECTS, ERRORS OR OMISSIONS WILL BE CORRECTED, REGARDLESS OF WHETHER COMMAND PROMPT IS AWARE OF THESE DEFECTS, ERRORS OR OMISSIONS.

YOU ASSUME TOTAL RESPONSIBILITY FOR YOUR USE OF THE WEBSITE AND ANY LINKED SITES. YOUR SOLE REMEDY AGAINST COMMAND PROMPT FOR DISSATISFACTION WITH THE WEBSITE OR ANY CONTENT IS TO STOP USING THE WEBSITE OR ANY SUCH CONTENT. THIS LIMITATION OF RELIEF IS A PART OF THE BARGAIN BETWEEN THE PARTIES. TO THE EXTENT APPLICABLE STATE LAW DOES NOT ALLOW THE EXCLUSIONS AND DISCLAIMERS OF WARRANTIES AS SET FORTH IN THIS SECTION, SOME OR ALL OF THE ABOVE EXCLUSIONS AND DISCLAIMERS MAY NOT APPLY TO YOU, IN WHICH CASE ALL WARRANTIES WILL BE LIMITED TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW. YOU ACKNOWLEDGE THAT THE DISCLAIMERS, LIMITATIONS, AND WAIVERS OF LIABILITY SET FORTH IN THIS SECTION SHALL SURVIVE ANY TERMINATION OR EXPIRATION OF THESE TERMS OF USE OR YOUR USE OF THE WEBSITE.  
  


## LIMITATION OF LIABILITY

IN NO EVENT SHALL COMMAND PROMPT, ITS AFFILIATES, OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AGENTS, SUCCESSORS AND/OR ASSIGNS BE LIABLE FOR ANY INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL, OR PUNITIVE DAMAGES, INCLUDING DAMAGES FOR LOST PROFITS OR LOSS OF DATA, ARISING OUT OF, OR RESULTING FROM, YOUR USE OF THE WEBSITE, EVEN IF COMMAND PROMPT IS AWARE OF OR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

IF, NOTWITHSTANDING THE OTHER PROVISIONS OF THESE TERMS OF USE, COMMAND PROMPT IS FOUND TO BE LIABLE TO YOU FOR ANY DAMAGE OR LOSS WHICH ARISES OUT OF OR IS IN ANY WAY CONNECTED WITH YOUR USE OF THE WEBSITE OR ANY CONTENT, COMMAND PROMPT'S AGGREGATE LIABILITY, REGARDLESS OF THE FORM OF ACTION, WILL AT ALL TIMES BE LIMITED TO THE GREATER OF (1) THE TOTAL OF ANY SUBSCRIPTION OR SIMILAR FEES WITH RESPECT TO ANY SERVICE OR FEATURE OF OR ON THE WEBSITE PAID IN THE TWELVE MONTHS PRIOR TO THE DATE OF THE INITIAL CLAIM MADE AGAINST COMMAND PROMPT (BUT NOT INCLUDING THE PURCHASE PRICE FOR ANY COMMAND PROMPT SOFTWARE PRODUCTS OR SERVICES), OR (2) US$100.00. NOTWITHSTANDING ANYTHING TO THE CONTRARY SET FORTH HEREIN, TO THE EXTENT APPLICABLE STATE LAW DOES NOT ALLOW THE EXCLUSIONS AND LIMITATIONS OF DAMAGES AS SET FORTH THROUGHOUT THIS SECTION AND THESE TERMS OF USE, SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY NOT APPLY TO YOU, IN WHICH CASE COMMAND PROMPT’S LIABILITY TO YOU WILL BE LIMITED TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW.  
  


## INDEMNITY

You agree to indemnify and hold Command Prompt, its officers, directors, shareholders, predecessors, successors in interest, employees, agents, subsidiaries and affiliates, harmless from any and all demands, losses, damages, costs liability, claims or expenses (including reasonable attorneys' fees and costs of investigation), made against Command Prompt by any third party due to or arising out of or in connection with, (a) your use of the Website, (b) your breach of these Terms of Use, including your breach of any covenant, representation, warranty, term, or condition set forth herein, including, without limitation, the obligations set out in the section .Your Use of the Website,. or (c) your violation of any law or regulation or of any third party rights, including infringement, libel, misappropriation, or other violation of any third party’s intellectual property or other legal rights.  
  


## VIOLATION OF THESE TERMS OF USE

In the event of your violation of these Terms of Use, Command Prompt may take any of the following actions. These potential actions do not limit the rights of Command Prompt to these possible actions in the event of violation of these Terms of Use, nor does this section limit the rights or possible actions of Command Prompt in situations where no breach has occurred.

Command Prompt may disclose any information we have about you (including your identity) if we determine that such disclosure is necessary in connection with any investigation or complaint regarding your use of the Website, or to identify, contact or bring legal action against someone who may be causing injury to or interference with (either intentionally or unintentionally) Command Prompt's rights or property, or the rights or property of visitors to or users of the Website, including Command Prompt's customers. Command Prompt reserves the right at all times to disclose any information that Command Prompt deems necessary to comply with any applicable law, regulation, legal process or governmental request. Command Prompt also may disclose your information when Command Prompt determines that applicable law requires or permits such disclosure, including exchanging information with other companies and organizations for fraud protection purposes.

You acknowledge and agree that Command Prompt may preserve any transmittal or communication by you with Command Prompt through the Website or any service offered on or through the Website, and may also disclose such data if required to do so by law or Command Prompt determines that such preservation or disclosure is reasonably necessary to (1) comply with legal process, (2) enforce these Terms of Use, (3) respond to claims that any such data violates the rights of others, or (4) protect the rights, property or personal safety of Command Prompt, its employees, users of or visitors to the Website, and the public.

You agree that Command Prompt may, in its sole discretion and without prior notice, terminate your access to the Website and/or block your future access to the Website if we determine that you have violated these Terms of Use or other agreements or guidelines which may be associated with your use of the Website. You also agree that any violation by you of these Terms of Use will constitute an unlawful and unfair business practice, and will cause irreparable harm to Command Prompt, for which monetary damages would be inadequate, and you consent to Command Prompt obtaining any injunctive or equitable relief that Command Prompt deems necessary or appropriate in such circumstances. These remedies are in addition to any other remedies Command Prompt may have at law or in equity.

You agree that Command Prompt may, in its sole discretion and without prior notice, terminate your access to the Website, for cause, which includes (but is not limited to) (1) requests by law enforcement or other government agencies, (2) a request by you (self-initiated account deletions), (3) discontinuance or material modification of the Website or any service offered on or through the Website, or (4) unexpected technical issues or problems.

If Command Prompt does take any legal action against you as a result of your violation of these Terms of Use, Command Prompt will be entitled to recover from you, and you agree to pay, all reasonable attorneys' fees and costs of such action, in addition to any other relief granted to Command Prompt. You agree that Command Prompt will not be liable to you or to any third party for termination of your access to the Website as a result of any violation of these Terms of Use.  
  


## DMCA NOTICE OF INFRINGEMENT

If you believe that the use or display of any content on the Website infringes any copyright that you own or control, please contact Command Prompt’s designated agent for copyright claims at:

Legal Department  
Phone: [1 503 667 4564](<tel:1 503 667 4564>)  
Email: [legal@commandprompt.com](<mailto:legal@commandprompt.com>)

When providing notification of alleged infringement of a copyright that you own or control, please provide Command Prompt.s designated agent the following information: (a) identification of the copyrighted work claimed to have been infringed, or, if multiple copyrighted works on the Website are covered by a single notification, a representative list of such works on the Website; (b) identification of the material that is claimed to be infringing or the subject of infringing activity and that is to be removed or access to which is to be disabled, including information reasonably sufficient to permit Command Prompt to locate the material; (c) information reasonably sufficient to permit Command Prompt to contact you, including an address, telephone number, and, if available, an electronic mail address at which you may be contacted; (d) a statement that you have a good faith belief that use of the material in the manner complained of is not authorized by the copyright owner, its agent, or the law; (e) a statement by you that the information in the notification is accurate, and under penalty of perjury, that you have the authority to enforce the copyrights that are claimed to be infringed; and (f) your physical or electronic signature.  
  


## GOVERNING LAW; DISPUTES

The internal laws of the State of Washington, excluding its conflict of laws principles, shall govern these Terms of Use and any dispute between you and Command Prompt or any of its officers, directors, affiliates, or employees. You and Command Prompt hereby consent to and agree to submit to the exclusive jurisdiction of, and venue in, the state and federal courts located within WHATCOM COUNTY, WASHINGTON with respect to any dispute arising from your use of the Website or these Terms of Use or any other dispute between you and Command Prompt. Each party irrevocably waives, to the fullest extent permitted by law, any right to trial by jury in the resolution of any dispute arising out of, or relating to, use of the Website and these Terms of Use. You hereby waive all defenses of lack of personal jurisdiction and forum non conveniens with respect to the jurisdiction of, and venue in, the state and federal courts of Washington. You agree that any cause of action you may have arising out of or related to these Terms of Use or the Website must commence within one (1) year after the cause of action accrues; otherwise, such cause of action shall be permanently barred.  
  


## MISCELLANEOUS

These Terms of Use operate to the fullest extent permissible by applicable law. If any provision of these Terms of Use are deemed to be invalid, void or unenforceable, such provision shall be deemed severed or limited to the minimum extent necessary and the remaining provisions of these Terms of Use shall not be affected and shall remain in full force and effect. These Terms of Use, along with the Privacy Policy referenced herein, constitute the entire agreement between you and Command Prompt with regard to your use of the Website, and any and all other written or oral agreements, proposals or understandings previously existing between you and Command Prompt with respect to your use of the Website are hereby superseded and cancelled. Command Prompt will not accept any counter-offers to these Terms of Use, and all such offers are hereby categorically rejected.

The headings used for the sections in these Terms of Use are for convenience and reference purposes only and shall in no way affect the meaning or interpretation of these Terms of Use. Command Prompt's failure to insist on or enforce strict performance of these Terms of Use shall not be construed as a waiver by Command Prompt of any provision or any right it has to enforce these Terms of Use, nor shall any course of conduct between Command Prompt and you or any other party be deemed to modify any provision of these Terms of Use. These Terms of Use shall not be interpreted or construed to confer any rights or remedies on any third parties.

These Terms of Use and any rights granted hereunder may not be transferred or assigned by you, and any such transfer or assignment shall be void and ineffective. Command Prompt may freely assign these Terms of Use and its rights and obligations hereunder without restriction. The rights and obligations of these Terms of Use shall survive the termination of your use of THIS Website and any use of Command Prompt services and products. Nothing in these Terms of Use or any action by either party should be interpreted as creating an agency or partnership relationship.

---
[View this page online](https://www.commandprompt.com/terms-of-use/)

---

# Privacy Policy

## Privacy Policy

( _Last updated: January 20, 2023)_

 _  
_

Command Prompt Inc. has created this privacy policy ( "Privacy Policy") to demonstrate our commitment to protecting an individual's right to protect his/her personal data.  
  


‘Personal data’ refers to any information relating to a person that can be used to identify such person, directly or indirectly. For instance, using an identifier such as a name, an identification number, location data, an online identifier or to one or more factors specific to the physical, physiological, genetic, mental, economic, cultural or social identity of that natural person.  
  


This Privacy Policy is effective as to all users of www.commandprompt.com (the "Website"), and incorporates by reference our Terms of Use. Terms with initial capital letters used in this Privacy Policy shall have the respective meanings assigned to them in the Terms of Use, unless specifically defined in this document. The terms "Command Prompt," "we," and "our" refer to Command Prompt Inc. The terms "you" and "your" refer to the user or viewer of the Website.  
  


By using this Website, you freely and knowingly consent to the collection and use of information as described herein. Command Prompt reserves the right to make changes periodically to this Privacy Policy by our sole discretion. Changes to the Privacy Policy will be posted on this page. Your continued use of this Website after any such changes constitutes your acceptance of the changes and of the revised Privacy Policy.

 _  
_

## Scope of this Privacy Policy

This Privacy Policy applies only to Personal Data collected by Command Prompt Inc. through software interactions with the Command Prompt Inc. website ("Site") and does not apply to any other information collected by Command Prompt Inc. through other means unless otherwise specified. If you have other agreements with Command Prompt Inc. governing Command Prompt Inc. products and services, then those agreements control with regard to the subject matter of those agreements. Further, our Privacy Policy does not cover the activities of any third parties.

  


This Privacy Policy covers:  


  * The information we collect
  * The basis for processing your information
  * How we use your personal information
  * How we may share or disclose your personal information
  * What cookies and web beacons are and how we and others use them
  * How we secure and store your information
  * Your rights if you are a California resident
  * Our policy towards children
  * What choices do we give you, and how can you correct or review your personal information
  * How to contact us
  * How we may update our privacy policy



## The Information We Collect

In interacting or registering with Command Prompt Inc. or requesting information, you may provide us with a password, your real name, industry, organization name, job role, and contact information, such as e-mail address, phone number, and shipping address. We may also collect your product registration information, product interest information, transaction information, or demographic information. In addition, for certain licensees, Command Prompt Inc. may require additional information, such as student verification information. We may collect payment information such as your credit card number and billing address if you purchase or license products and services from us.  
  


If you connect with Command Prompt Inc. accounts on third party social networking sites, we may also collect information about your social networking accounts, for example, your name, user name or handle, public profile, and email address. We may also combine information you provide with data we collect automatically (as further described below) and with data we receive from third parties.  
  


Whenever you visit the Command Prompt Inc. website, Command Prompt Inc. also receives and records information on our server logs from your browser, including your computer's or mobile device's operating system type and version, browser type and language, your Internet Protocol (IP) address, and geographic areas derived from your IP address, Command Prompt Inc. cookie information, file information, time stamped logs regarding access times and duration of visits, the websites you visited before coming to Website, and other usage data relating to your activities on our Sites, including the pages you request. We may relate this information to the personal data you provide for purposes described in this Privacy Policy.  
  


Certain third parties, including analytics companies, advertisers and ad networks, may also automatically collect information about you through our Website, using cookies, Web beacons, and device identifiers, including personally identifiable information (PII) about your online activities over time and across different websites, devices, online channels and applications when you use our Website.  
  


## The Basis for Processing Your Information

Command Prompt Inc. processes your personal data based on the following lawful grounds:  
  


  * Legitimate Interests: As necessary for our legitimate interests in carrying out our business, such as sharing information related to your demonstrated interest in database and enterprise information technology, trial software downloads, or other products and services, provided those interests are not outweighed by your rights and interests;
  * Contract: As necessary to enter and perform a contract with you, such as when you ask us to provide services to you;
  * Legal Obligation: When we have a legal obligation to carry out the processing, such as complying with an applicable law; or
  * Consent: Where processing is based on your consent, such as when you have opted in to receive marketing communications from us, we will identify the processing purposes and provide you with relevant information to make the processing fair and transparent. Please email marketing@commandprompt.com to let us know if you no longer wish to receive further marketing emails.  
  




## How We Use Your Personal Data

Command Prompt Inc. may use your personal data to:  
  


  * Provide and deliver products or services you’ve requested, including software updates;
  * Operate and improve our internal operations, systems, products, and services;
  * Understand you and your preferences to enhance your experience;
  * Carry out the sales, sales solicitation, shipment of products, complete orders, and provide other services performed by us or third parties;
  * Communicate with you about promotions, upcoming events, and news about products and services offered by Command Prompt Inc. and our selected partners;
  * Provide system maintenance or handle system malfunctions;
  * Respond to your comments and questions and provide customer service;
  * Send you service-related information, including confirmations, invoices, technical notices, updates, security alerts, and support and administrative messages;
  * Link or combine information about you with other personal data we get from third parties, to help understand your needs and provide you with better and more personalized service;
  * Enforce our terms and conditions or protect our business, partners, or users;
  * Protect against, investigate, and deter fraudulent, unauthorized, or illegal activity;
  * Carry out identity verification and authentication services; and/or
  * Other separately and explicitly prescribed purposes.



  


## How We May Share or Disclose Your Personal Information

Command Prompt Inc. does not rent, sell, or share personal data about you with other people or unaffiliated companies, except under the following circumstances:  
  


  * We may provide your personal data to third parties who help facilitate the Website (for example, by providing website development, statistical analyses, data processing, or sending communications to users), but for use solely in connection with facilitating the Website;
  * We may provide your personal data to financial institutions, credit card companies, collection enterprises, and other enterprises that process payments or represent the buyer or seller to facilitate payment owed to us or to a seller when you submit such personal data for the purposes of effecting a purchase or other financial transaction;
  * We may provide your personal data to persons who owe us a duty of confidentiality in connection with a legitimate business purpose of Command Prompt Inc.;
  * We may provide your personal data to third parties, including, but not limited to, law enforcement agencies, state, local or federal governments, private litigants, and other companies, as may be required to (1) comply with lawful requests such as subpoenas or court orders, (2) comply with applicable state, federal, or local law, (3) prevent fraud or other illegal activities from being perpetrated through the Website, or (4) protect the property, safety, or legal rights of Command Prompt Inc. and its users;
  * We may provide your personal data to any third party whom you have consented to receive your personal information;
  * We may provide your personal data to affiliated companies or business successors of Command Prompt Inc.;
  * We may provide your personal data to third parties as otherwise separately and explicitly prescribed; and/or
  * We may provide your personal data as a result of mergers and acquisitions related to Command Prompt Inc..



We will not provide your personal data to third party advertisers, except as provided in this Privacy Policy, without your permission; however, we may provide non-personal data, such as your age, interests, or the way you use the Website, to any third party for any purpose including customizing and targeting advertising messages.

  


## What Cookies and Web Beacons Are and How We and Others Use Them

Our Site may use various software technologies including "cookies", "web beacons" and "pixel tags." "Cookies" are small text files that we and others may place in visitors' computer browsers to store their preferences. Cookies themselves do not contain any personal data. "Web beacons" or "Pixel tags" are small pieces of code placed on a web page or within the body of an email to monitor the behavior and collect data about the visitors viewing a web page or viewing or opening an email. For example, web beacons can be used to count the users who visit a web page or to deliver a cookie to the browser of a visitor viewing that page. We may use web beacons on our Website from time to time for this and advertising purposes.

  
We use cookies to deliver personalized content, to save you having to re-enter your password repeatedly, and to tailor our information offerings relating to how you and others use the Website. From time to time, we partner with third parties who may place cookies on your browser when you visit our Websites, may send their own cookies to your cookie file, and may use those cookies to track and collect information about you and your online activities over time and across different websites, devices, and applications and to provide targeted advertising based on your interests and previous browsing history. Some cookies remain on your mobile phone, computer or mobile device until they are deleted.

  
Certain third party ad networks may automatically collect information about your visits to our Sites and other websites, such as your IP address, your Internet service provider, and the browser you use to visit our Sites. They do this using cookies, web beacons or other technologies. You can learn more about practices of many of these third parties by visiting the Digital Advertising Alliance (http://www.aboutads.info/choices/) in the USA, Digital Advertising Alliance of Canada (http://youradchoices.ca/) in Canada or the European Digital Advertising Alliance (http://www.youronlinechoices.eu/) in Europe. This Privacy Policy does not apply to, and we are not responsible for, cookies or web beacons and other technologies in third party advertising. We encourage you to check the privacy policies of third party advertisers and/or ad services to learn about their use of cookies, web beacons and other technology.

  
Some web browsers (including some mobile web browsers) provide settings that allow you to control or reject cookies or to alert you when a cookie is placed on your computer, tablet or mobile device. Although you are not required to accept cookies, if you block or reject them, you may not have access to all features available through our services. For more information, visit the help page for your web browser.  
  


## What Internet Protocol Addresses Are

An Internet protocol (";IP") address is the unique number assigned to your server or Internet Service Provider ("ISP"). Command Prompt Inc. may track such IP addresses for system administration, to report aggregate information, site tracking, to prevent our servers from being abused and for other uses described in this Privacy Policy.

##   
Collection of Information by Third-Party Sites and Sponsors

Third parties that help facilitate the Website may, from time to time, collect information through the Website in the course of providing support;

  * Third parties may collect other information that you voluntarily post or publish through the Website in any way;
  * Web-crawlers such as Google may collect information through the Website; and/or
  * The Website may contain links or references to other websites, including third party advertisers and other unaffiliated websites.



  


## How We Secure and Store Your Personal Data

We have put in place reasonable and appropriate physical, electronic, and managerial procedures in an effort to help safeguard information we collect through our Sites. However, you should know that no company, including Command Prompt Inc., can fully eliminate security risks associated with personal data. To help protect yourself, please use a strong password, do not use the same passwords to access your Command Prompt Inc. accounts that you use with other accounts or services, and protect your user names and passwords to help prevent others from accessing your accounts and services.

  
Command Prompt Inc. is a global company with affiliates, varied business processes, management structures and technical systems that cross borders. Information collected by Command Prompt Inc. or on our behalf may be stored on your computers, on your mobile devices, or on our servers, and may be transferred to, accessed from, or stored and processed in, the United States and other countries including but not limited to the Netherlands, England, France, Australia, Japan, South Korea, Pakistan, India, and any other country where Command Prompt Inc. or its service providers maintain facilities or support centers (a list of Command Prompt Inc. offices can be found here: https://www.commandprompt.com/contact), including jurisdictions that may not have data privacy laws that provide protections equivalent to those provided in your home country. However, we will protect all personal data we obtain in accordance with this Privacy Policy and take reasonable steps to ensure that it is treated lawfully. Personal data we collect may be retained for as long as needed to fulfill legitimate business purposes, including the purposes outlined in this Privacy Policy, or for a period of time specifically required or allowed by applicable regulations or laws.

  
Personal data we collect may be retained for as long as needed to fulfill legitimate business purposes, including the purposes outlined in this Privacy Policy, or for a period of time specifically required or allowed by applicable regulations or laws.

  


## Your Rights Under Certain U.S. State Privacy Laws

The[ U.S. States Privacy Notice](</privacy-policy/us-states-privacy-notice/>) (“Notice”) supplements the information in and is part of this Policy. This Notice discloses information related to our privacy practices required by certain U.S. State privacy laws which include California, Colorado, Connecticut, Nevada, Virginia, Utah and any other future rights granting U.S. state.  
  


California Civil Code Section 1798.83 permits users of our website that are California residents to request certain information regarding our disclosure of personal information to third parties for their direct marketing purposes. To make such a request, please send an e-mail to the Command Prompt Inc. Legal Department at legal@commandprompt.com.

  


## Our Policy Toward Children

Command Prompt Inc. does not knowingly collect or solicit Personally Identifiable Information (PII) from anyone under the age of thirteen (13). If we learn that we have inadvertently obtained Personally Identifiable Information from a child under the age of thirteen (13), we will delete that information as soon as practicable. If you believe that a child under the age of thirteen (13) has submitted Personally Identifiable Information in connection with the Website, please contact us at privacy@commandprompt.com.  


  


## What Choices Do We Give You and How Can You Correct or Review Your Personal Data

  


### ACCOUNT INFORMATION AND RETENTION

Upon request, we will provide an individual with access to personal data that we have collected about them (provided that they have given adequate proof of identity). We also offer individuals the ability to have inaccuracies corrected within their contact information. You may also request deletion of your personal data. We will honor requests as required by law and subject to our business and legal needs to retain your data. These information requests can be made by sending us an e-mail at privacy@commandprompt.com. We will retain your personal data for the period necessary to fulfill the purposes outlined in this Privacy Notice. If you wish to deactivate your account, please email us at privacy@commandprompt.com, but note that we may retain certain information as required by law or for legitimate business purposes. We may also retain cached or archived copies of information for a certain period of time. We will respond to your access request within 30 days.  


We will retain your personal data for as long as your account is active, as needed to provide you services, to comply with our legal obligations, resolve disputes and enforce our agreements.

  


### COOKIES

When you use our Website, you can usually choose to set your browser to remove cookies and to reject cookies from our servers. If you choose to remove cookies or reject cookies, this could affect certain features or services of our Website. You can also choose to opt-out of use of cookies by many of our third party advertising partners for delivery of personalized ads by visiting the Digital Advertising Alliance (http://www.aboutads.info/choices/) in the USA, Digital Advertising Alliance of Canada (http://youradchoices.ca/) in Canada or the European Digital Advertising Alliance (http://www.youronlinechoices.eu/) in Europe. If you delete your cookies, use a different browser, or buy a new computer, you will need to renew your opt-out choices.  


While we and others give you certain choices, as further outlined in this Policy, there are many ways that Web browser signals and similar mechanisms can indicate your choice to disable tracking, and we may not be aware of nor honor every mechanism.

  


### MARKETING EMAILS

Our marketing emails tell you how to "opt-out" of receiving further marketing emails. You may also contact us marketing@commandprompt.com with a subject line "Unsubscribe" at any time to let us know that you no longer wish to receive further marketing emails. If you receive a phone call from one of our sales representatives, you can ask them to put you on our email unsubscribe list, or you can call us directly and ask to be unsubscribed from our mailing list. If you opt out, we may still send you non-marketing emails. Non-marketing emails include emails about your accounts and our business dealings with you, and, as allowed by applicable law, requests for your participation in surveys.

  


## How to Contact Us

Command Prompt Inc. may retain Consumer’s Personal Data for a period of time consistent with the original purpose of collection. To ask questions or comment about this Privacy Policy and our privacy practices or if you need to update, change or remove your information, contact us at: privacy@commandprompt.com or by regular mail addressed to:  
  


Command Prompt Inc.  
Attn: Legal Department  
2950 Newmarket ST STE 101 - 231  
Bellingham, WA 98226

  


## How We May Update Our Privacy Policy

From time to time, we may collect and use personally identifiable information (PII) in ways not previously disclosed in our Privacy Policy. If our information practices change we will post any adjustments to our policy on this website and change the “Last Updated” date above. Unless additional notice or consent is required by applicable laws, this will serve as your notification of these changes. If you are concerned about how your information is used, bookmark this page and check back periodically.

---
[View this page online](https://www.commandprompt.com/privacy-policy/)

---

# U.S. States Privacy Notice

## U.S. States Privacy Notice

_Last Updated: January 20, 2023_

  
This U.S. States Privacy Notice (“Notice”) supplements the information in and is part of the [**COMMAND PROMPT PRIVACY POLICY**](</privacy-policy/>). This Notice discloses information related to our privacy practices required by certain U.S. State privacy laws which include California, Colorado, Connecticut, Nevada, Virginia, Utah and any other future rights granting U.S. state. This Notice is intended to supplement the **COMMAND PROMPT PRIVACY POLICY** in order to meet our disclosure requirements pursuant to relevant state law. To understand our privacy practices, you should refer to the **COMMAND PROMPT PRIVACY POLICY** in addition to this supplement applicable to residents of rights granting states.

  
This Notice applies to Personal Information, as defined below, that is processed by Command Prompt in the course of our business, including via the Command Prompt Site, and through our Apps, forums, social media accounts, blogs, and other online or offline offerings (together with any and all future online and offline offerings operated by or on behalf of Command Prompt, the “Services”).

  
This Notice is not intended to apply to Personal Information we collect about our employees, applicants for employment, or contractors in the employment context.

  
The definition of “Personal Information” may be different under individual state regulations. Generally, the definition used in this Notice differs from the definition used in the **COMMAND PROMPT PRIVACY POLICY**. As used in this Notice only, “Personal Information” refers to “information that identifies, relates to, describes, is capable of being associated with, or could reasonably be linked, directly or indirectly, with a particular consumer or household.”  


  


## WHAT PERSONAL INFORMATION WE COLLECT

The table below identifies the categories of Personal Information we collect and provides examples of Personal Information in such categories, along with information on the third parties with whom such categories of information may be shared. For more information about the Personal Information we collect, please see “The Information We Collect” section of the **COMMAND PROMPT PRIVACY POLICY.**

.

![Personal Information](/media/images/Personal_Information.width-1200.format-webp.webp)

  


* We may also share each of the above listed categories of Personal Information with government entities if we believe doing so is necessary: (i) to comply with law enforcement or national security requests and legal process, such as, a court order or subpoena; (ii) to protect yours, ours or others’ rights, property or safety; or (iii) to enforce Command Prompt policies or contracts. Additionally, if we are involved in a merger, acquisition, financing, reorganization, bankruptcy, receivership, sale of company assets or transition of service to another provider, then each of the above listed categories of Personal Information may be shared with the involved corporate entities and their professional advisors, representatives and agents as part of the transaction as permitted by law and/or contract.*

  
The sources of the Personal Information we collect above include Personal Information that you directly provide to us (for example, on our Site or our Redmine Platform, or by telephone), Personal Information that we gather from the devices you use to access our Services (for example, mobile applications or websites), Personal Information we receive from third party partners (for example, certain marketing, research or survey partners), and Personal Information that we generate internally (for example, we may generate identifiers internally that we associate with you).  


  


## HOW WE USE PERSONAL INFORMATION

The **COMMAND PROMPT PRIVACY POLICY** describes our uses of Personal Information (“How We Use Your Personal Data”).

  


WHAT PERSONAL INFORMATION WE SHARE

In addition to the table above, the **COMMAND PROMPT PRIVACY POLICY** provides information regarding the categories of third parties with whom we share Personal Information (see section “How We May Share or Disclose Your Personal Information”).

  
State laws, such as those in California, require that we also list the categories of Personal Information that we have disclosed to third parties for business purposes in the last 12 months. In the last 12 months, we have disclosed all of the categories of Personal Information we describe in the “What Personal Information We Collect” section for business purposes. For example, we may share your IP address or device ID with service providers that provide crash monitoring and reporting services to us.

  
Some states allow residents to have the right to opt out of disclosures of Personal Information to third parties for valuable consideration (which may be considered “sales” for example under California law even if no money is exchanged). If you would like to minimize “selling” of your information with third parties for marketing purposes, please opt out of sale/share by using the “Do Not Sell/Share My Personal Information” link on the bottom of our website.

  
Please Note: The California Privacy Rights Act (CPRA) defines the term “sale” broadly, and it may include selling/sharing certain information for particular purposes through technology such as cookies or other identifiers. We never sell personal information to third parties for money nor do we “share” it for targeted advertising purposes (as defined by state privacy laws). However, under the CPRA, when you visit this website, we and our partners may collect certain information about you, your devices, and your behavior through cookies, tags or other identifiers that may be considered a “sale/share” even if no money is exchanged.  


  


## YOUR RIGHTS

Your state’s law may allow you have certain rights, such as:

  *  **Right to data portability/access.** You may be entitled to receive the specific pieces of Personal Information we have collected in the 12 months preceding your request, including, where applicable, in an electronic and readily-usable format.
  *  **Right to know.** You may be entitled to receive information regarding the categories of Personal Information we collected, the sources from which we collected Personal Information, the purposes for which we collected and shared Personal Information, the categories of Personal Information that we sold and the categories of third parties to whom the Personal Information was sold, and the categories of Personal Information that we disclosed for a business purpose in the 12 months preceding your request.
  *  **Right to deletion.** You may be entitled to request that we delete the Personal Information that we have collected from you. We will use commercially reasonable efforts to honor your request, in compliance with applicable laws. Please note, however, that we may need to keep such information, such as for our legitimate business purposes or as required to comply with applicable law.
  *  **Opt out/Limiting Use.** You may be able to opt out of some collection or uses of your Personal Information.
  *  **Rectification.** You have the right to correct inaccurate information.



  
You may freely exercise these rights without fear of being denied goods or services. We may, however, provide a different level of service or charge a different rate reasonably relating to the value of your Personal Information. If you would like to exercise one of your rights, please email **PRIVACY@COMMANDPROMPT.COM** or contact us at (503) 667-4564.

  
You may opt out and we honor certain technologies broadcasting an Opt-Out Preference Signal, such as the Global Privacy Control (GPC) if you are a resident of certain states. This occurs on the browsers and/or browser extensions that support such a signal. This request will be linked to your browser identifier only.

  
We are required to verify the requests we receive from you when you exercise certain rights listed above. We (or third parties we engage to assist us) may ask you to provide certain information to us in order for us to verify your request, including your name, email address, Command Prompt username, billing address, and phone number (the “Verification Information”). This information will be used to generate a brief quiz with personalized questions to verify your identity. If you fail the identity verification quiz twice, our third-party verification partner will ask you to verify your identity by submitting a copy of state-issued ID and a photograph of yourself.

  
You may also designate an authorized agent to exercise your rights on your behalf. If you have provided an authorized agent with a power of attorney pursuant to your state’s Probate Code, we will work directly with your authorized agent to complete your request. Where you have not provided an authorized agent with a power of attorney pursuant to your state’s Probate Code, we will reach out to you directly to confirm the authorized agent’s authority and collect the Verification Information.

  
In addition to these rights, pursuant to California’s “Shine the Light” law, California residents who share personal information with us have the right to request and obtain from us once per year, free of charge, a list of the third parties to whom we have disclosed their Personal Information (if any) for direct marketing purposes in the prior calendar year, as well as the type of Personal Information disclosed to those parties. If you would like to exercise this right, please use the contact information listed below to contact us.  


  


## HOW TO CONTACT US

If you have any questions about our privacy practices, this Notice or would like to contact us you can do so by email at **PRIVACY@COMMANDPROMPT.COM** or at the address below.

  
Command Prompt Inc.  
Attn: Legal Department  
2950 Newmarket ST STE 101 - 231  
Bellingham, WA 98226

  
  


## UPDATES TO OUR PRIVACY NOTICE

We may update our Privacy Notice from time to time. When we do, we will take appropriate measures to inform you, consistent with the significance of the changes we make. We will obtain your consent to any material Privacy Notice changes if and where this is required by applicable data protection laws. You can see when this Privacy Notice was last updated by checking the "last updated" date displayed at the top of this Notice.

---
[View this page online](https://www.commandprompt.com/privacy-policy/us-states-privacy-notice/)

---

# Products

> PostgreSQL products & open source tools: PgManage GUI admin, PgLTS extended support, pgBackRest backup, pglogical replication. Enterprise-ready solutions.


---
[View this page online](https://www.commandprompt.com/products/)

---

# Audax Postgres

> PostgreSQL Long Term Support

# The Postgres for the Enterprise

Audax Postgres extends PostgreSQL with FedRAMP-compliant patching for 8 years per release. That is 3 years beyond community end of life.

[ Learn More ](</contact-us/>) [ Postgres Support ](</support/postgres-support/>)

Your browser does not support the video tag. 

## Audax Postgres

Audax Postgres is a FedRAMP patch compliant PostgreSQL distribution for the mature enterprise. Supporting PostgreSQL version 12 and up, Command Prompt insures that your data stack stays reliable and secure. You can find more information on the patch and [support schedule here.](</support/support-for-eol-versions-of-postgres/>)

## It isn't broke, why be forced to fix it?

Depending on the size of your organization, the number of applications and the quantity of databases upgrading Postgresql may be a multi-million dollar investment. PgLTS allows your organization to amortize that effort for an additional 3 years allowing for a proper plan and increased opportunity for success.

## Pricing

PgLTS has a straight forward pricing model. It is supported for 3 years in addition to the community initial 5 years providing 8 total years of support. The [exact support schedule](</support/support-for-eol-versions-of-postgres/>) can be found here.

Version  |  Cost with Annual PSLA [1]  |  2024-2025  |  2025-2026  |  2026-2027  |  2027-2028  |  2028-2029   
---|---|---|---|---|---|---  
12  |  0  |  5k/yr  |  7.5k/yr  |  10k/yr  |  N/A  |  N/A   
13  |  0  |  N/A  |  5k/yr  |  7.5k/yr  |  10k/yr  |  N/A   
14  |  0  |  N/A  |  N/A  |  5k/yr  |  7.5k/yr  |  10k/yr   
PgLTS: Straight forward pricing (per install)

## Enterprise Pricing and 24x7 Support

Command Prompt also offers Enterprise pricing for large quantities of installs as well as 24x7x365 support. For more information please [contact us](</contact-us/>) or [read more here](</support/>).

  1. The Annual PSLA includes up to 5 licenses and a 25% discount on licenses above the quantity of 5.



## LTS for PostgreSQL supported OS versions

Command Prompt supports certain versions of operating systems and PostgreSQL for LTS support by default. That list is below.  
  
Under certain circumstances we may support other Open Source operating systems (FreeBSD). However, we do not support Microsoft or Apple based operating systems for LTS packaging.  


Operating System  |  Base PostgreSQL version*  |  Supported?   
---|---|---  
Ubuntu  |  |   
18.04  |  10  |  N   
20.04  |  12  |  Y   
22.04  |  14  |  Y   
24.04  |  16  |  Y   
26.04  |  18  |  Y   
Almra/Rocky/RHEL  |  |   
8  |  10  |  N   
9  |  13  |  Y   
10  |  16  |  Y   
Debian  |  |   
10  |  11  |  N   
11  |  13  |  Y   
12  |  15  |  Y   
13  |  17  |  Y   
LTS for PostgreSQL supported OS versions

## Explanation on versions

Command Prompt will provide native packages for PostgreSQL and Operating system based on the version of PostgreSQL shipped with the OS.

* * *

Command Prompt will also back port packages where changes to the base operating system do not need to be made. For example, Ubuntu 22.04 ships with PostgreSQL 12. We will also provide PostgreSQL 13 (and on) to Ubuntu 22.04 on the condition that additional not PostgreSQL packages do not need to be upgraded or backpatched to do so (OpenSSL, Zlib etc...).

---
[View this page online](https://www.commandprompt.com/products/audax-postgres/)

---

# Audax Data Manager

> Discover Audax Data Manager (formerly PgManage), a modern open-source SQL editor and GUI database admin tool for Postgres, MySQL, SQLite, MariaDB.

# The database manager that stays out of your way

Audax Data Manager is a modern, convenient and powerful SQL Editor and Database Client for Developers and Administrators

Spin It Up

## What's Inside

## Multi-database

Supports PostgreSQL, MySQL, MariaDB, SQL Server, Oracle and SQLite3

## Modern

Intuitive interface that helps and does not get in your way.

Switchable themes and UI scaling

## Secure

Privacy-first, no data collection, no telemetry.  
Keeps your credentials in encrypted form.

## Powerful

View database performance metrics

Run backups

Manage Roles and Extensions

Tune your PostgreSQL server parameters

Connect to your environment via SSH tunnels

## Convenient

Use multiple database workspaces at once.

Edit data in a familiar spreadsheet-like way.

Easily locate database objects with fuzzy search.

Supports hot-keys and keyboard navigation for core features.

## Smart

Shows schema- and context-aware suggestions for tables, views, columns, aliases, and functions as you type.

Adds query error annotations in the exact place that is causing problems

Copy table data as Markdown, JSON or CSV

## How It Looks

![query-explain](/media/images/query-explain.width-1200.format-png.png)

![query](/media/images/query.width-1200.format-png.png)

![pg-config-management](/media/images/pg-config-management.width-1200.format-png.png)

![pg-backup](/media/images/pg-backup.width-1200.format-png.png)

![home](/media/images/home.width-1200.format-png.png)

![database-erd](/media/images/database-erd.width-1200.format-png.png)

![connections](/media/images/connections.width-1200.format-png.png)

## Spin It Up

![Linux AppImage](/media/images/linux-icon.height-300.format-webp.webp)

## Linux AppImage

[pgmanage-1.5.AppImage](<https://github.com/commandprompt/pgmanage/releases/download/1.5-release/pgmanage-1.5.AppImage>)

![Windows](/media/images/win-icon.height-300.format-webp.webp)

## Windows

[pgmanage-1.5_setup_win64.exe](<https://github.com/commandprompt/pgmanage/releases/download/1.5-release/pgmanage-1.5_setup_win64.exe>)

![macOS](/media/images/osx-icon.height-300.format-webp.webp)

## macOS

[pgmanage-1.5_mac_x64.dmg](<https://github.com/commandprompt/pgmanage/releases/download/1.5-release/pgmanage-1.5_mac_x64.dmg>)

![AWS](/media/images/pgmanage-aws-icon.height-300.format-webp.webp)

## AWS

[AWS Marketplace](<https://aws.amazon.com/marketplace/pp/prodview-rrd472rooejz2>)

![Docker](/media/images/pgmanage-docker-icon.height-300.format-webp.webp)

## Docker

[Audax Data Manager Docker Image](<https://hub.docker.com/r/cmdpromptinc/audax-enterprise>)

## Latest Release

### Audax Data Manager 1.5 Release Highlights:

 **Schema editor:**  
Oracle is now supported by Schema Editor  
Added support for renaming indexes in MySQL, MariaDB, SQLite3 and MS SQL Server  
Added support for updating column comments for Postgres, MySQL and MariaDB  
  
 **Improved Keyboard Navigation:**  
Added support for keyboard navigation in Database Explorer using Page-Up, Page-Down, Home, End and arrow keys.  
Context menus can now be opened using the keyboard "Context Menu" key in Data Editor, Query Tabs, Snippets and Database Explorer.  
Implemented hotkey support for Copy/Paste and Clear actions in data grids  
  
 **Data Editor:**  
It is now possible to copy and paste cell regions in the same way as it is done in popular spreadsheet editors  
Cells with lengthy or complex content can now be edited in a dedicated modal window in addition to inline editing  
  
 **UX:**  
Full-screen mode support for Data Editor and ERD tabs  
Added quick access to theme and font size settings in the app sidebar  
Query history commands are not deduplicated if the same command is run several times in a row  
Added the "unsaved data" warning when user tries to close a workspace or tab  
  
 **Backups/Restore:**  
Added support for multiple versions of pg_dump/pg_restore binaries. Backup/Restore features will now try to select a version that is matching Postgres server being backed up.  
  
[ **Full Release Notes on Github**](<https://github.com/commandprompt/pgmanage/releases#release-1.5-release>)

## Enterprise Edition

[**Purchase Enterprise License**](<mailto:sales@commandprompt.com?subject=Audax%20Enterprise%20License%20Purchase>)

Features  |  Community  |  Enterprise   
---|---|---  
All Core Features  |  ✔️  |  ✔️   
Works Offline  |  ✔️  |  ✖️   
Remote Access via web browser  |  ✖️  |  ✔️   
Multi User Support  |  ✖️  |  ✔️   
Oauth2 Authentication  |  ✖️  |  ✔️   
AWS Deployment  |  ✖️  |  ✔️   
Docker Deployment  |  ✖️  |  ✔️

---
[View this page online](https://www.commandprompt.com/products/audax-data-manager/)

---

# PgColumnar

> pgColumnar is a column-oriented storage extension for PostgreSQL, implemented as a table access method. A table created USING pgcolumnar stores its data by column, with per-column compression, chunk-group skipping, and a vectorized aggregate path. It targets analytic workloads: large scans, aggregates, and column projections over append-mostly data. It also reads external Parquet and Apache Iceberg tables, from a local path or from object storage.

# pgColumnar

Column storage for PostgreSQL, built for fast analytics at scale.

[ Try it out! ](<https://github.com/commandprompt/pgcolumnar>) [ Contact Us ](</contact-us/>)

Bringing analytics to PostgreSQL

## Features

## Smaller Storage

Automatically compresses your data using the best method for each column  
Cuts storage space by up to 97% compared to normal tables

## Faster Queries

Answers totals, counts, and averages almost instantly, and skips scanning data that can't match — reading only what's needed.

## Safe & Always Up-to-Date

Fully transactional with enforced data rules, plus zero-downtime schema changes and format switching.

## Maintains Itself

Automatic background cleanup and optimization that never slows down active queries, with multi-worker data loading for speed.

## Plays Well With Others

Works with popular formats like Parquet and Arrow, reads files from cloud storage directly, and fits right into your existing PostgreSQL setup.

## Reliable

Full MVCC, transactions, and savepoint rollback semantics  
Unique, primary-key, NOT NULL, and CHECK constraints enforced on insert

## Benchmarks

**97% smaller** on disk than standard row-based tables

 **13,000x faster** on COUNT(*), answered from metadata, no data scanned

 **600x faster** on SUM/AVG over a column

 **116x faster** on indexed lookups using index-only scans

 **7x faster** bulk loads and exports, parallelized across workers

 **3.4x smaller** than row storage at 100M rows — smaller than TimescaleDB and Citus columnar in the same test

* * *

 _Full methodology, hardware specs, and raw numbers:_ [_commandprompt.github.io/pgcolumnar/benchmarks_](<https://commandprompt.github.io/pgcolumnar/benchmarks/>)

## When to use it

\-  |  Use pgColumnar  |  Use regular tables   
---|---|---  
Workload  |  Append-mostly, read-heavy  |  Frequent updates and deletes   
Access pattern  |  Wide scans, aggregates, reporting  |  Point lookups, single-row fetches   
Table shape  |  Wide tables, queries touch a few columns  |  Queries need most or all columns per row   
Data type  |  Compresses well, read more than written  |  Changes constantly, low compression benefit   
Example workloads  |  Fact tables, event logs, analytics  |  OLTP, transactional systems   
  
## Get It

![pgcolumnar-logo](/media/images/pgcolumnar-logo.width-1200.format-webp.webp)
    
    
    git clone <https://github.com/commandprompt/pgcolumnar> 
    
    
    cd pgcolumnar make && make install

 **Full build instructions** : [Installation guide](<https://commandprompt.github.io/pgcolumnar/installation/>)

## Frequently Asked Questions

###  Will my existing queries still work? 

* * *

Yes. A columnar table is an ordinary PostgreSQL relation. It works with your existing indexes, COPY, pg_dump, replication, and transactions without changes to your queries.

###  Does pgColumnar replace my existing tables? 

* * *

No. It's a table access method you opt into per table (CREATE TABLE ... USING pgcolumnar). Existing heap tables are unaffected, and you can convert a table to or from columnar storage without rewriting it manually.

###  What happens to performance once I delete rows? 

* * *

Aggregates fall back from metadata-only answers to a full scan of the affected row groups until you run pgcolumnar.vacuum. Only the touched groups are affected, not the whole table.

###  Can I still use indexes on a columnar table? 

* * *

Yes. CREATE INDEX builds standard btree and hash indexes, and index-only scans are supported through a columnar visibility map.

###  Is pgColumnar production-ready? 

* * *

It's currently 1.0alpha2. It's functional and benchmarked, but treat it as pre-production software until a stable release.

###  Does it support updates and deletes? 

* * *

Yes, along with unique, primary key, NOT NULL, and CHECK constraints. The storage layout is optimized for append-mostly data, so update-heavy and delete-heavy workloads see less benefit than analytics workloads.

###  How is data compressed? 

* * *

Each column chunk is encoded with the best fit from several type-aware methods (RLE, delta, dictionary, and others), then optionally compressed further with pglz, lz4, or zstd.

## More Information

**Status:** PgColumnar is currently 1.0alpha2 and ready to be tested by the wider world.

 **Compatibility:** PostgreSQL versions 15, 16, 17, 18 (19beta2 validated)  
 **License:** MIT to encourage contribution (AI welcome)

 **Docs:** <https://commandprompt.github.io/pgcolumnar/>

**Code:** <https://github.com/commandprompt/pgcolumnar>

* * *

  


## Try pgColumnar on your own workload

Talk to the team behind it about your use case, deployment, or support options.

[Talk to the Team](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/products/pgcolumnar/)

---

# plX: The excellent transpiler for PostgreSQL

> Write PostgreSQL functions in the language you already know. Ruby, PHP, JavaScript, TypeScript, Python, Go, COBOL, Oracle PL/SQL, or Transact-SQL, compiled to plpgsql at CREATE FUNCTION time.

# plX: The excellent transpiler

The safe way to write procedures for PostgreSQL in your favorite language

[ Learn More ](</contact-us/>) [ Get Support ](</support/>)

![plx](/media/images/plx.width-1200.format-webp.webp)

**Write PostgreSQL functions in the language you already know.** Ruby, PHP, JavaScript, TypeScript, Python, Go, COBOL, Oracle PL/SQL, or Transact-SQL, compiled to plpgsql at CREATE FUNCTION time.

plx is a PostgreSQL extension. When you run CREATE FUNCTION ... LANGUAGE plx*, plx transpiles the body to plpgsql and stores that plpgsql in pg_proc.prosrc. At run time the function is executed by PostgreSQL's own plpgsql interpreter. There is no separate language runtime loaded into the backend, the generated plpgsql is visible in the catalog, and every plpgsql construct is reachable from every dialect.

## Contact Us

Reach out! We would love to hear from you

[Learn More](</contact-us/>)

## Dialects

The front end is dialect-pluggable, and the set is open-ended. The dialects available today:

  * [ **plxruby**](<https://commandprompt.github.io/plx/plxruby/>) — a Ruby dialect
  * [ **plxphp**](<https://commandprompt.github.io/plx/plxphp/>) — a PHP dialect
  * [ **plxjs**](<https://commandprompt.github.io/plx/plxjs/>) — a JavaScript dialect
  * [ **plxts**](<https://commandprompt.github.io/plx/plxts/>) — a TypeScript dialect (plxjs plus type annotations)
  * [ **plxpython3**](<https://commandprompt.github.io/plx/plxpython3/>) — a Python dialect
  * [ **plxgo**](<https://commandprompt.github.io/plx/plxgo/>) — a Go dialect
  * [ **plxcobol**](<https://commandprompt.github.io/plx/plxcobol/>) — a COBOL dialect (ISO/IEC 1989:2023)
  * [ **plxplsql**](<https://commandprompt.github.io/plx/plxplsql/>) — an Oracle PL/SQL dialect
  * [ **plxtsql**](<https://commandprompt.github.io/plx/plxtsql/>) — a Transact-SQL (SQL Server) dialect



## More info

  * License: MIT to encourage contribution (AI Welcome)
  * Documentation: <https://commandprompt.github.io/plx/>
  * Code: <https://github.com/commandprompt/plx>

---
[View this page online](https://www.commandprompt.com/products/plx-the-excellent-transpiler-for-postgresql/)

---

# Performance Audit

## Performance problems rarely have one cause. We look at the whole system.

Timeouts, slow queries, and connection exhaustion are usually connected. The Command Prompt Performance Audit examines your PostgreSQL environment across configuration, table and index health, autovacuum behavior, WAL and checkpoint load, and query patterns, and gives you a prioritized list of what to fix and how. [Schedule your audit today](</contact-us/>). 

## Who This Is For

This audit is most valuable when:  


  * Queries that used to run in milliseconds are now timing out
  * Your connection pool is exhausting despite normal traffic
  * Autovacuum seems to be running constantly but dead tuples keep accumulating
  * You've tuned what you can but performance isn't improving
  * You're preparing for a major version upgrade and want a clean bill of health first
  * Your team is newer to PostgreSQL and you want an expert baseline review



## What We Examine

## System and Configuration

  * PostgreSQL configuration review (postgresql.conf, key tuning parameters)
  * System-level indicators: sar, iostat, vmstat
  * WAL and checkpoint behavior
  * Log analysis: errors, warnings, slow query log



## Table and Index Health

  * Table and index bloat
  * Autovacuum settings and dead tuple accumulation
  * Unused and redundant indexes



## Query Performance

  * Identification and analysis of the slowest queries
  * Query plan review
  * Connection pool behavior and long-running query patterns
  * Optimization recommendations for top offenders



## What You Receive

At the end of the engagement you receive a written report covering:

  * Findings across each area examined
  * Root cause analysis for your top performance issues
  * Prioritized recommendations with implementation guidance
  * Estimated effort for each recommended fix



We walk through the report with you and answer questions if needed. The goal is that you leave knowing exactly what to do next, whether you execute internally or engage us to help.

## How It's Scoped

Engagements are scoped based on your environment — number of systems, database size, and the complexity of the issues you're seeing. Most audits can be completed within a short, defined timeframe.

Contact us with a brief description of your environment and the symptoms you're seeing. We'll respond with a scope, what the engagement will cover, and likely a few questions.

[Contact us to scope your audit](</contact-us/>)

## What Comes Next?

The Performance Audit is a great introduction to the depth and breadth of our Postgres expertise, and is often the starting point for a longer engagement. Common next steps:

  * Basic Service SLA (SLA) or Proactive SLA (PSLA) Support — ongoing enterprise-wide, 24x7 coverage once you've stabilized
  * Major Version Upgrade — if you're on an EOL or aging version, the audit surfaces what needs to be addressed and what can be optimized before upgrading
  * [Learn about our support plans](</about/support-options/>)

---
[View this page online](https://www.commandprompt.com/products/performance-audit/)

---

# Audit & Tune

## Audit & Tune

The Audit & Tune is a way for our Command Prompt team of experts to become familiar with a Client's environment. It provides a thorough overview of the environment and documents best practices including optimizations to be made for the PostgreSQL Environment. Pricing includes a single cluster/server.

  
This option provides a documented best practices list of recommendations for your PostgreSQL installation, whether on-prem or in the cloud. One of our technical experts will:

  * Verify application interface
    * Connectivity
    * Network Connections
    * Long Running Queries
    * Idle Transactions
  * Verify best practices network access
  * Verify Instance appropriateness for workload
  * Verify OS (where applicable)
  * Verify Hardware (on-prem only)



  
[Contact us](</contact-us/>) today to schedule an Audit & Tune.

---
[View this page online](https://www.commandprompt.com/products/audit-tune/)

---

# Cloud Migration Assessment

> Moving PostgreSQL to AWS, GCP, or Azure? Command Prompt's cloud migration assessment covers the full stack — database, application, operations, and cost — so your migration plan reflects production reality.

## Cloud migration decisions are easier when you have the full picture.

Command Prompt's Cloud Migration Assessment looks at the full stack, including the database architecture, application dependencies, infrastructure configurations, and operational model. You have a clear, realistic picture of what the migration requires, am estimate of what it will cost, and how your PostgreSQL environment will need to be configured and tuned once you're there.

## Who This Is For

This assessment is most useful when:

  * You're running PostgreSQL on-prem and evaluating a move to AWS RDS, Aurora, GCP Cloud SQL, or Azure
  * You're already on cloud PostgreSQL but costs are higher than expected
  * You're planning a major version upgrade alongside a cloud migration
  * Your operations team hasn't managed cloud-hosted PostgreSQL before and you need a realistic picture of what changes
  * You're an AWS client evaluating RDS vs. Aurora vs. EC2-hosted PostgreSQL



## What the Assessment Covers

## Full Stack Evaluation

  * Database: schema, query patterns, extensions, replication configuration
  * Application: compatibility with target cloud database tier, connection handling
  * Operations: high availability, backup and restore, monitoring, maintenance windows
  * Infrastructure: instance sizing, storage type, read replica topology, multi-AZ requirements



## Cost Analysis

  * Current vs. projected cloud cost by tier (RDS, Aurora, EC2-hosted)
  * Hidden cost factors: data transfer, storage I/O, backup retention, cross-AZ traffic
  * Cost optimization recommendations: right-sizing, reserved instances, storage tiering



## Migration Planning

  * Deployment options: RDS vs. Aurora vs. self-managed on EC2; AlloyDB
  * Data migration approach: logical replication, pg_dump/restore, parallel operation
  * Downtime analysis and cutover options
  * Post-migration operational model: who manages what, monitoring setup, upgrade cadence
  * Skills and training gaps for your team



## What You Receive

A written assessment report covering:

  * Full stack findings and risk areas
  * Recommended target architecture with rationale
  * Cost comparison across deployment options
  * Migration approach and estimated effort
  * Post-migration operational recommendations



We can review the report with you and answer questions. If you decide to proceed, we can support the migration execution or hand off a complete plan to your team.

## AWS Partnership

Command Prompt is an AWS Consulting Partner. We work with AWS clients on RDS, Aurora, EC2-hosted PostgreSQL, and GovCloud deployments. If you're working through the AWS Marketplace or have an existing AWS account team, we can coordinate through those channels.

  * [View our AWS Marketplace Professional Services listings](<https://aws.amazon.com/marketplace/seller-profile?id=08fa54ce-5b3c-402c-8cf0-d829d50e2f50>)
  * Check out our products available on the AWS Marketplace including [Audax Data Manager](<https://aws.amazon.com/marketplace/pp/prodview-rrd472rooejz2?sr=0-1&ref_=beagle&applicationId=AWSMPContessa>)



Every environment is different. Contact us with a brief description of what you're running and where you're headed — we'll come back with a clear scope, what the assessment will cover, and likely a few questions.

  * [Request your assessment](</contact-us/>)
  * [Migrating from Oracle or MySQL?](</services/database-migration/>)

---
[View this page online](https://www.commandprompt.com/products/cloud-migration-assessment/)

---

# Alternatives

> Command Prompt is the alternative to your current PostgreSQL and Open Source vendor.

# Find your alternative

The expert source and alternative to your current PostgreSQL and Open Source partner

[ Contact Us ](</contact-us/>) [ Get Support ](</support/>)

## How Command Prompt compares to the alternatives

## EDB

EDB sells a platform: EPAS, tooling, and cloud with support priced per core. Command Prompt sells support: direct access to Postgres engineers, at a fixed rate that doesn't grow with your core count. We've been doing it since 1997, and we support EPAS too, so you can change support vendors without changing databases.

[ Learn More ](</alternatives/edb/>)

## Percona

Percona is a strong open-source support company whose bench spans MySQL, MongoDB, and PostgreSQL. Command Prompt does one thing: Postgres and the open source stack around it, since 1997. If Postgres is your primary database, you want specialists, the same engineers who know your environment, every incident.

[ Learn More ](</alternatives/percona/>)

## Crunchy Data / Snowflake

Crunchy Data's subscription is anchored to its stack: Crunchy Certified Postgres, the Kubernetes operator, Crunchy Bridge. If you're on that stack, it's a good home. If you just run Postgres vanilla, on RDS or Aurora, on your own metal, Command Prompt supports what you already have, priced on service rather than software.

[ Learn More ](</alternatives/crunchy-data-alternative-command-prompt/>)

---
[View this page online](https://www.commandprompt.com/alternatives/)

---

# The EDB Alternative for Teams That Just Want Postgres Support

> Looking for an EDB alternative? Command Prompt has supported Postgres since 1997 — engineer-direct support with no per-core pricing, for community PostgreSQL and even EPAS.

# The EDB Alternative

For Teams That Just Want Postgres Support and Consulting

[ Contact Us ](</contact-us/>) [ Get Support ](</support/>)

## The EDB Alternative for Teams That Just Want Postgres Support

EDB sells a platform: EPAS, tooling, and cloud with support priced per core. Command Prompt sells support: direct access to Postgres engineers, at a fixed rate that doesn't grow with your core count. We've been doing it since 1997, and we support EPAS too, so you can change support vendors without changing databases.

EDB is a serious Postgres company with major upstream contributors on staff. Most teams who call us aren't leaving because the technology failed. They're leaving because:

  *  **Per-core subscription renewals grow with the estate.** Every scale-up event is a pricing event.
  *  **Support and product are bundled.** The subscription's value assumes you adopt EPAS and EDB tooling; if you run community Postgres or a cloud-managed service, you're paying for a platform you don't use.
  *  **Extended Life Support is quote-only.** If you need to stay on an EOL major version, the terms live behind a sales conversation.
  *  **The org chart is between you and the engineer.** Account managers and ticket tiers are the price of a large support organization.



What  |  Command Prompt  |  EDB   
---|---|---  
Focus  |  Postgres support & services  |  Postgres platform (EPAS, PGD, cloud) + support   
Pricing  |  Fixed hourly + SLA retainer, no per-core or per-instance pricing  |  Per-core/per-deployment subscription   
Who answers  |  The engineer who knows your system  |  Support organization, tiered   
Community Postgres  |  Fully supported  |  Supported (subscription)   
EPAS  |  Supported: no migration required  |  Native   
Cloud-managed PG (RDS, Aurora, Azure, GCP)  |  Supported  |  Varies by offering   
EOL versions  |  PgLTS: 8 years per release, 3 beyond community EOL — published timeline  |  Extended Life Support via sales   
Response  |  Under 1 hour for SLA clients, 24x7x365  |  Tiered by subscription level   
Ownership  |  Independent, founder-operated since 1997  |  Private-equity backed   
How Command Prompt compares

## Who should switch

  * You run **community PostgreSQL or cloud-managed Postgres** and need expertise, not a platform subscription.
  * You run **EPAS** but want support decoupled from the license relationship, we support EPAS as-is.
  * You run **EPAS** but want to migrate to an open ecosystem.
  * Your **core counts are growing** and your support bill is growing with them for no added service.
  * You're on (or heading toward) an **EOL major version** and want a written, published support timeline instead of a quote.



## Ready to switch?

Contacts us today

[Learn More](</contact-us/>)

## Who should stay with EDB

Honestly: if your applications depend deeply on **EPAS Oracle-compatibility features** , or you're committed to **EDB Postgres Distributed** for multi-master, EDB's product engineering is the point, and a support-only vendor doesn't replace it. Global enterprises that need a vendor matching a specific procurement mold may also prefer EDB's org scale.

## Switching is a support transition, not a migration

Your database doesn't move. Onboarding with Command Prompt means an environment review, runbook and access intake, and an engineer team assigned to your systems. We can have you up and running in just a couple of days.

If you later want off EPAS entirely, our [Database Migration service](<https://a53ec712-5798-486f-a242-1ba840b4ab03.frame.claudeusercontent.com/services/database-migration/>) handles EPAS-to-community-Postgres transitions.

## Talk to an engineer

No discovery call gauntlet. [Contact us](</contact-us/>) and describe your environment; a Postgres engineer will respond. See [support plans](</support/>) for how engagements work.

---
[View this page online](https://www.commandprompt.com/alternatives/edb/)

---

# The Percona Alternative for Postgres-First Teams

> Looking for a Percona alternative for PostgreSQL? Command Prompt is Postgres-dedicated — the same engineers on your systems since 1997, with written EOL support commitments.

# The Percona Alternative

Since 1997, Command Prompt is Postgres-dedicated and here to support your PostgreSQL and Open Source enterprise

[ Contact Us ](</contact-us/>) [ Get Support ](</support/>)

## The Percona Alternative for Postgres-First Teams

Percona is a strong open-source support company whose bench spans MySQL, MongoDB, and PostgreSQL. Command Prompt does one thing: Postgres and the open source stack around it, since 1997. If Postgres is your primary database, you want specialists, the same engineers who know your environment, every incident.

## Why teams look for a Percona alternative

Percona earned its reputation in MySQL, and its open-source ethos is genuine. Teams who come to us from a multi-database vendor usually say some version of:

  *  **"Postgres is our main database, and we want a Postgres-first partner."** A generalist bench covers three ecosystems; depth on any one of them is diluted by design.
  *  **"We want the same engineers each time."** Large support organizations rotate; context gets rebuilt on every ticket.
  *  **"We need more than the database supported."** Incidents rarely respect the boundary between Postgres, Linux, and the application layer.



What  |  Command Prompt  |  Percona   
---|---|---  
Focus  |  PostgreSQL and its open source stack, exclusively  |  MySQL + MongoDB + PostgreSQL   
Postgres history  |  Since Postgres95 (1997)  |  Postgres practice added to a MySQL-origin company   
Who answers  |  The engineer who knows your system  |  24/7 global support organization   
Advertised response  |  Under 1 hour for SLA clients, 24x7x365  |  15 minutes on mission-critical tiers   
Full-stack scope  |  Postgres + Linux + dev (Python/Ruby) + Ansible + monitoring  |  Database-focused, with managed options (ExpertOps)   
EOL versions  |  PgLTS: 8 years per release, 3 beyond community EOL — published timeline  |  Ask for terms per version   
Pricing  |  Fixed hourly + SLA retainer; no per-instance pricing  |  Subscription tiers   
Ownership  |  Independent, founder-operated  |  Privately held   
How Command Prompt compares

## Who should switch

  * **Postgres is your primary or only database** and you want a partner whose entire bench lives there.
  * You value a **standing engineer relationship** over a ticket queue — someone who already knows your schema, your replication topology, your quirks.
  * You need **written EOL commitments** — our supported-releases timeline is published, per version, through 2033.
  * Your incidents are **full-stack** — you want the same vendor debugging Postgres, the Linux host, and the app connection pool.



## Ready to switch?

Contact us today

[Learn More](</contact-us/>)

## Who should stay with Percona

If you run a **mixed MySQL + MongoDB + PostgreSQL estate** and consolidating on one support vendor matters more than per-database depth, Percona is built for exactly that. Their open-source tooling (PMM in particular) is good, and their scale suits organizations that want a large global org behind the SLA.

## Switching is a support transition, not a migration

Nothing about your databases changes. A quick phone call, a little paperwork (really) and we will have you up in running in no time.

## Talk to a Postgres engineer

## **Talk to a Postgres engineer**

[Contact us](</contact-us/>) with a description of your environment. See [support plans](</support/>) for engagement options, and [Postgres support](</support/postgres-support/>) for the platforms we cover.

---
[View this page online](https://www.commandprompt.com/alternatives/percona/)

---

# Crunchy Data Alternative: Command Prompt

> Looking for a Crunchy Data alternative? Command Prompt supports Postgres wherever it runs: vanilla, cloud-managed, or containerized.

# The Crunchy Data Alternative

Command Prompt supports Postgres wherever it runs: vanilla, cloud-managed, or containerized

[ Contact Us ](</contact-us/>) [ Get Support ](</support/>)

## The Crunchy Data Alternative When You Don't Need a Distribution

Crunchy Data's / Snowflake subscription is anchored to its stack Crunchy Certified Postgres, the Kubernetes operator, Crunchy Bridge. If you're on that stack, it's a good home. If you just run Postgres, vanilla, on RDS, or Aurora, on your own metal, Command Prompt supports what you already have, priced on service rather than software.

## Why teams look for a Crunchy Data alternative

Crunchy has real strengths: the best-known Postgres Kubernetes operator, serious upstream contributors, and a strong government story. The teams who call us instead usually say:

  *  **"We don't run Kubernetes."** The operator is the center of gravity of the offering; without it, the subscription buys software you won't deploy.
  *  **"We're on cloud-managed Postgres."** RDS, Aurora, Azure, Cloud SQLyou need expertise on top of the platform, not another platform.
  *  **"We want support priced on service."** Per-node software subscriptions scale with infrastructure, not with how much help you actually need.



What  |  Command Prompt  |  Crunchy Data   
---|---|---  
Center of gravity  |  Support and services on your existing Postgres  |  Crunchy Certified Postgres, CPK operator, Bridge   
Vanilla/community Postgres  |  Fully supported, as-is  |  Via Crunchy Certified packages   
Cloud-managed PG (RDS, Aurora, Azure, GCP)  |  Supported  |  Bridge is their managed offering   
Kubernetes  |  Supported (your operator of choice)  |  CPK — their flagship   
Government/compliance  |  FedRAMP-compliant patching  |  Certified/hardened containers, strong DoD story   
EOL versions  |  PgLTS: 8 years per release, 3 beyond community EOL — published timeline  |  Per subscription terms   
Pricing  |  Fixed hourly + SLA retainer; no per-instance pricing  |  Subscription around the Crunchy stack   
Ownership  |  Independent, founder-operated since 1997  |  Acquired by Snowflake   
How Command Prompt compares

## Who should switch

  * You run **Postgres with or without Kubernetes,** bare metal, VMs, or cloud-managed, and need engineers, not a distribution.
  * You're on **RDS/Aurora/Azure/GCP** and want a partner who supports managed Postgres daily.
  * You need **regulated-environment patching** (we provide FedRAMP-compliant patching) without adopting a new software stack to get it.
  * You're on an **EOL major version** and want the published PgLTS timeline rather than negotiated terms.



## Ready to switch?

Contact us today

[Learn More](</contact-us/>)

## Who should stay with Crunchy Data

If you're invested in **Crunchy Bridge** or run **defense/government programs already built on their certified containers**.

## Switching is a support transition, not a migration

Your databases stay exactly where they are supported by a company that has been doing it since 1997. No outside investors, No debt.

## Talk to an engineer

[Contact us](</contact-us/>) and describe your environment. See [Support Plans](</support/>) and [Postgres Support](</support/postgres-support/>) for platform coverage.

---
[View this page online](https://www.commandprompt.com/alternatives/crunchy-data-alternative-command-prompt/)

---

# Blog

---

# pgColumnar 1.0-alpha4 released

> pgColumnar is a columnar storage table access method for PostgreSQL, written as a clean-room, MIT-licensed implementation. It reads and writes its own native format, PGCN v1, and supports chunk-group skipping from zone maps, bloom filters and star-schema join runtime filters, vectorized aggregation, projections, Z-order and Hilbert clustering, retention, online compaction and reclustering, parallel bulk ingest and export, Apache Arrow and Parquet import and export, Apache Iceberg, and object storage.

## pgColumnar 1.0-alpha4 release notes

  * [Source](<https://github.com/commandprompt/pgcolumnar>)
  * [Docs](<https://commandprompt.github.io/pgcolumnar/>)
  * [Product page](</products/pgcolumnar/>)



2026-09-17

 **pgColumnar 1.0-alpha4 release notes**

Release date: 2026-09-17 Previous release: 1.0-alpha3 (2026-09-02)

pgColumnar is a columnar table access method for PostgreSQL. This is the fourth alpha. Its theme is layout and skipping. A table can now be laid out on the Hilbert curve, which keeps neighbouring keys closer together than Z-order does. A star-schema join now skips fact-table groups and rejects non-matching rows, and it does so without being asked. The on-disk native format, PGCN v1, is unchanged. Existing tables are read and written as before.

This release requires one upgrade command. See "Upgrading" at the end. The upgrade is the smallest of any release so far: it adds two functions and changes nothing else.

##  **Highlights**

  *  **Hilbert clustering**. pgcolumnar.cluster_hilbert and pgcolumnar.recluster_hilbert lay a table out on the Hilbert curve. The curve has no jumps at a bit boundary, so a range filter reads fewer chunk groups. Measured on 200,000 rows over two columns, Hilbert read 1.24x to 2.04x fewer groups than Z-order.
  *  **Star-schema joins skip and reject by default**. A serial inner Hash Join now uses the build-side keys to skip fact-table chunk groups and to reject non-matching rows. pgcolumnar.enable_join_runtime_filter is on.
  *  **An index-driven read of a wide table does less I/O**. Adjacent column reads in one row group are coalesced into a single read.
  *  **A parallel index build now uses its workers**. Every participant claims distinct row groups. Before this release one backend read the whole table while the launched workers sat idle.
  *  **The planner stops preferring a fetching index scan that does far more work**. A correlated range over tens of thousands of rows now takes the columnar scan.



##  **Hilbert clustering**

pgcolumnar.cluster_hilbert(table, VARIADIC columns) rewrites a table in Hilbert order. It holds AccessExclusiveLock, as CLUSTER and VACUUM FULL do. pgcolumnar.recluster_hilbert(table, VARIADIC columns) does the same work online under ShareUpdateExclusiveLock, so reads and writes continue.

The curve is sticky. Plain pgcolumnar.recluster maintains a Hilbert table rather than converting it back. Naming the Hilbert verb is how a Z-ordered table is switched to the curve.

Choose the curve by the predicate. Z-order is fine for point lookups. Hilbert wins on range filters over several columns, and the gap narrows as the query box grows. Measure your own corpus when the two look close. See docs/best-practices.md for the guidance and pgcolumnar.sort_status for how much of a table is currently in order.

There are two verbs rather than a parameter on the existing two because PostgreSQL cannot extend cluster(regclass, VARIADIC name[]) in either direction. A defaulted parameter cannot precede a VARIADIC one.

##  **Join acceleration**

A serial inner Hash Join over a columnar fact table now builds a filter from the join keys it has already hashed. The filter does two things. A key range skips whole fact-table chunk groups. A Bloom filter rejects rows that cannot match.

Three measured cases decided the default:

fact table

result

clustered on the join key

19 of 20 chunk groups removed, 1 read

scattered

0 groups removed, Bloom rejects over 15,000 of 19,800 non-matches

build side too large

the Bloom disables itself

The third case is why this is on for everyone. A filter that helps nothing turns itself off. Group skip still needs the fact table clustered on the join key. Set pgcolumnar.enable_join_runtime_filter to off to compare.

An ungrouped vectorized aggregate also keeps running over a unique-key inner Hash Join. A unique dimension acts as a filter of the fact table, so the fold does not have to stop. Duplicate-key dimensions and LEFT joins stay on the core plan.

##  **Reads and the planner**

  *  **Coalesced column reads**. An index-driven fetch of several columns in one row group issues one read for adjacent chunks instead of one per column.
  *  **Parallel index build**. The table access method's parallel scan claims row groups per participant from the shared counter, the way the custom scan already did. A parallel CREATE INDEX now spreads across its workers.
  *  **Parallel scan cost**. The planner no longer divides a parallel scan's I/O by the worker count. PostgreSQL divides CPU across workers and leaves the disk work whole, and the columnar cost now matches.
  *  **Clustered index fetch cost**. The fetch penalty now charges a per-row term, capped at half a chunk group. Without it a correlated range of 50,000 rows stayed on a fetching index scan while doing far more work than a scan.



##  **Correctness fixes**

  *  **A truncated column chunk is refused rather than read**. A chunk whose recorded length exceeded 4 GB was cast to 32 bits on the index-fetch path. A fetch could therefore read the wrong bytes and report them as data. Both cast sites now raise XX001.
  *  **A coalesced fetch cannot read past its buffer**. The validity bitmap copy is now bounded by the chunk length before it runs.
  *  **Projections survive DDL**. A rewrite re-records its projections. ALTER TABLE ... RENAME COLUMN carries the new name into the projection. ALTER TABLE ... DROP COLUMN is refused when a projection depends on the column. An in-place TRUNCATE clears each projection's storage as well as the base.
  *  **The block codec frees its buffer**. Both paths abandoned it.
  *  **Object storage refuses URL userinfo** on s3:// and gs://, as http(s):// has since #706.



##  **Known issues**

  *  **Setting a codec can make a table larger, on high-entropy text** (#1074). The writer keeps FSST only when it beats the alternative by fsst_min_gain_percent, and it measures both sides after the block codec has run. Storing the FSST codes uncompressed is never compared. Measured on 200,000 rows of random hex text, zstd wrote 1.777% more than compression = none. lz4 was unaffected. If a table stores long high-entropy text and size matters, measure both settings.
  *  **The block codec compresses a region it then discards** (#1075). On incompressible data this costs about 25% more write CPU. It does not affect what is stored or read.



##  **Upgrading**

Install this build, then run the following in every database that has the extension:

 **ALTER** EXTENSION pgcolumnar **UPDATE** ;

This is required. The upgrade creates pgcolumnar.cluster_hilbert and pgcolumnar.recluster_hilbert. It changes nothing else. No table data is converted, no existing function is replaced, no catalog column is added, and no SQL you write changes.

See docs/installation.md for the commands, including how to list the databases that need the update.

##  **Scope and limitations**

  * This is an alpha. Interfaces may change before 1.0.
  * Hilbert clustering orders whole row groups on rewrite. A table that is written to after the rewrite drifts out of order until the next one.
  * The join runtime filter applies to a serial inner Hash Join on a direct columnar scan. It does not wrap LEFT, SEMI, ANTI, CROSS, parallel, or projection scans.
  * On PGXN this release is 1.0.0-alpha.4, while CREATE EXTENSION reports 1.0-alpha4. PGXN requires a semantic version, which needs three integer components. The extension's own version has two. The two names refer to the same release.



The complete, itemized list of changes is in CHANGELOG.md.

---
[View this page online](https://www.commandprompt.com/blog/pgcolumnar-10-alpha4-released/)

---

# Part 3 Beyond Throughput: Efficiency Metrics for Cost-Aware PostgreSQL Tuning

> Optimize PostgreSQL for cost, not just speed. Explore how shared_buffers tuning can trade memory, disk I/O, and CPU to reduce infrastructure spend.

## Introduction

This is Part 3 of a three-part series benchmarking shared_buffers behavior on a 128 GB PostgreSQL 18 system. Parts 1 and 2 examined throughput, memory behavior, and huge page utilization across TPC-B and analytics workloads. This article explores the economic tradeoffs between memory and storage, introducing metrics that help identify workload-specific configurations that minimize the cost of delivering a given level of performance.

In modern cloud environments, resource consumption is metered across multiple independent dimensions like storage IOPS, throughput, CPU time, and sometimes WAL or network egress. Cloud infrastructure pricing is often discontinuous, a modern increase in required IOPS or CPU may require utilization of a higher resource tier, often at a much higher cost. This blog is focused on the cost of providing that performance and some possible ways of optimizing the cost.

I fully acknowledge that efficiency will absolutely depend on the actual hardware being utilized, and this set of metrics is based on a hardware sample of one. This is meant as a beginning and I am more than happy to continue this experiment for any systems I may be given access to. I do intend to follow up with both the code and instructions on how these metrics can be created for other environments, if anyone wants to re-create these or similar experiments.

## Normalizing Efficiency

All metrics below are expressed per million transactions (labelled mtxn) executed over 1 hour test duration. The transactions attempt to represent a relatively stable amount of work within each type of workload, although database drift due to random selection of parameters will cause some variation over test duration.

Throughout these experiments my system recorded 27.6 billion transactions, and I expect the random effects to largely average out.

The way to read these graphs is to:

  * First identify whether your workload is more similar to TPC-B (single value updates accessed via index and simple, highly specific filters) or Analytics (complex queries with joins between tables).
  * Identify whether your hot data fits within memory, ws_30, or ws_100 when it does not.
  * Examine the range of consumption of a resource to provide the same amount of work.



For example, for an Analytics style workload that fits in memory, the range of disk IO operations per second for the default 4kB pages ranges from 30 to 130 depending on shared_buffers allocation, representing a 5 to 6 fold difference in the rate of disk requests.

If we are trying to optimize the use of an overloaded disk, we can see that either reducing shared buffers to around 5% or increasing past 60% of total RAM should greatly reduce disk IOPS. Additionally, changing to huge_pages should allow for additional improvement.

More generally, effective memory utilization is often one of the most direct paths to better performance, but it can also be viewed as a cost tradeoff. In some environments, additional memory can reduce demand on more expensive or more constrained resources, especially disk I/O. This does not mean that maximizing memory allocation is always optimal from a cost perspective.

##  **IOPS per Million Transactions**

One of the first performance bottlenecks on a database is the disk, and a disk is often a very large component of the total cost of a cloud database. Also, hot standby environments and read replicas very frequently require identical size and specification disk as well. Differences in these graphs can be attributed to additional caching or swapping of memory, additional disk lookups when data is not available in various caches.

 **Definition:** This is the total number of disk reads and disk writes performed by postgresql processes divided by the total time performing IO by the same processes for each experiment. This metric is an average IOPS normalized per million transactions (mtxn) for each experiment.

[ ![TPC-B ws_30: IOPS Per Mtxn vs Shared Buffers](/media/images/image6_5XEFGWr.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image6_5XEFGWr.width-1200.format-webp.webp>)

[ ![TPC-B ws_100: IOPS Per Mtxn vs Shared Buffers](/media/images/image2_PbG792G.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image2_PbG792G.width-1200.format-webp.webp>)

[ ![Analytics ws_30: IOPS Per Mtxn vs Shared Buffers](/media/images/image11_qkxVeY0.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image11_qkxVeY0.width-1200.format-webp.webp>)

[ ![Analytics ws_100: IOPS Per Mtxn vs Shared Buffers](/media/images/image5.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image5.width-1200.format-webp.webp>)

For TPC-B style workload we see that increasing shared buffers as a percentage of total RAM will decrease the IO load on the disk to provide the same unit of work. When the work does not fit in RAM, the reduction is negligible as many requests have to retrieve data from disk as it is not available in a cache.

For analytics workloads, low memory and high memory allocation utilize the disk more efficiently than setting shared_buffers between 20 and 60 percent of total RAM. When both shared_buffers and the OS file cache are similarly sized, they will likely, largely, contain a duplicate of the same data when the database is the primary consumer of that machine. That effectively halves the available memory of the system.

In both TPC-B and Analytics style workloads we can see that the default 4kB data pages come with an increased disk utilization. My theory is that this is related to the behavior identified in [Part 2](</blog/when-to-use-huge-pages-postgresql/>) of this blog. When utilizing 4kB pages, the kernel appears to move things around in order to maintain a higher than anticipated file cache.

[ ![TPC-B ws_30: Median Cached GB vs RAM Range](/media/images/image20.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image20.width-1200.format-webp.webp>)

[ ![TPC-B ws_100: Median Cached GB vs RAM Range](/media/images/image7_5lWAdqY.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image7_5lWAdqY.width-1200.format-webp.webp>)

[ ![Analytics ws_30: Median Cached GB vs RAM Range](/media/images/image10_2zri1Xi.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image10_2zri1Xi.width-1200.format-webp.webp>)

[ ![Analytics ws_100: Median Cached GB vs RAM Range](/media/images/image15_P4dfW2x.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image15_P4dfW2x.width-1200.format-webp.webp>)

## Throughput (MB/s) per Million Transactions

While IOPS measures the number of requests, the size of requests can vary as well. In some circumstances the kernel is able to combine two, or more, IO requests into a single, longer one. This metric measures an overall, average MB / second required from the disk to support one million transactions.

 **Definition:** The average rate of disk reads and writes required for each million transactions. This metric helps distinguish between “chatty” workloads (high IOPS, low throughput) and “bulk-heavy” ones.

[ ![TPC-B ws_30: Throughput \(MB/s\) vs Shared Buffers](/media/images/image16.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image16.width-1200.format-webp.webp>)

[ ![TPC-B ws_100: Throughput \(MB/s\) vs Shared Buffers](/media/images/image22.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image22.width-1200.format-webp.webp>)

[ ![Analytics ws_30: Throughput \(MB/s\) vs Shared Buffers](/media/images/image8_9TbcfKI.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image8_9TbcfKI.width-1200.format-webp.webp>)

[ ![Analytics ws_100: Throughput \(MB/s\) vs Shared Buffers](/media/images/image14_Z4SaLLp.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image14_Z4SaLLp.width-1200.format-webp.webp>)

Just as before, we can see that TPC-B style workloads do not really affect the rate of disk reads and writes with changing shared_buffers. We continue to see that for Analytics workloads there is a significant average disk throughput, showing about three-fold difference between high and low when using huge_pages and over 5 fold difference when using 4kB pages.

## User + System CPU Seconds per Million Transactions

This metric tracks how many CPU slices postgresql processes used over each experiment, normalized to 1 million transactions. Effectively showing us how hard the CPU had to work to provide all information.

I am including both the user space and the kernel work attributed to each process, but removing any IO or network waits, as during those times the cpu would be available for other processes. Differences in these metrics could be attributed to buffer and lock management, kernel overhead, IO and memory management, context switching, etc.

 **Definition:** For every PostgreSQL process, how much time was actually spent running on a CPU, removing any time that was spent waiting on resources like IO. This is actual execution time when the scheduler has allocated this process to a CPU and includes system CPU time on behalf of the process and is normalized per mtxn.

[ ![TPC-B ws_30: User Sys CPU Seconds vs Shared Buffers](/media/images/image4_yhybiN5.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image4_yhybiN5.width-1200.format-webp.webp>)

[ ![TPC-B ws_100: User Sys CPU Seconds vs Shared Buffers](/media/images/image21.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image21.width-1200.format-webp.webp>)

[ ![Analytics ws_30: User Sys CPU Seconds vs Shared Buffers](/media/images/image1_RRDPNWH.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image1_RRDPNWH.width-1200.format-webp.webp>)

[ ![Analytics ws_100: User Sys CPU Seconds vs Shared Buffers](/media/images/image13_dTj4lCl.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image13_dTj4lCl.width-1200.format-webp.webp>)

These graphs are largely stable for TPC-B style workload, with an exception of specific data points. At this point I’m inclined to treat these points as anomalies, since the value does come back to the previous level during the next sample.

 **Analytics style workloads show about a 50% difference in CPU usage as between low and high shared_buffers allocation.**

I believe this is largely the overhead of managing small shared_buffers, and deciding which data pages to evict. Again, we see a higher CPU utilization when using the default 4kB pages, likely due to additional management and swapping being performed on by the kernel.

## Non voluntary Context Switches per Million Transactions

In a Linux kernel, a process is given access to a CPU for a specific time slice. If there are additional processes ready to execute, it can be switched out for another ready to run process. That type of switch is involuntary and shows that there were more processes ready to execute than CPUs available to run them.  
  
When a process is attempting to perform an IO operation and it knows it needs to wait, it can perform a voluntary context switch, giving up the CPU for another process that is ready to run. Non voluntary context switches represent contention for the CPU, where there is more work ready to go than there are processors available.

 **Definition:** Average number of involuntary context switches per million transactions.

[ ![TPC-B ws_30: Nonvoluntary Context Switches vs Shared Buffers](/media/images/image9_lSVJx3P.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image9_lSVJx3P.width-1200.format-webp.webp>)

[ ![TPC-B ws_100: Nonvoluntary Context Switches vs Shared Buffers](/media/images/image12_vdoIrlx.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image12_vdoIrlx.width-1200.format-webp.webp>)

[ ![Analytics ws_30: User Sys CPU Seconds vs Shared Buffers](/media/images/image1_RRDPNWH.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image1_RRDPNWH.width-1200.format-webp.webp>)

[ ![Analytics ws_100: User Sys CPU Seconds vs Shared Buffers](/media/images/image13_dTj4lCl.2e16d0ba.fill-400x400.format-webp.webp) ](</media/images/image13_dTj4lCl.width-1200.format-webp.webp>)

While context switching does impose a bit of overhead like reloading CPu registers and TLB caches, that overhead is very small compared to the overall CPU utilization. It does mean that many processes were ready to execute but had to wait. I would expect this behavior to show up as latency experienced by clients.

I am including this graph as an idea for a followup. My theory is that this overhead can become much more visible when using thousands of client connections, and it could be a metric to track operationally to see how it changes over time.

## Interpreting These Metrics Together

In conclusion, no single metric defines efficiency and these specific graphs only include an example of a single hardware and OS configuration. The intent is to look at orders of magnitude changes between various efficiencies. Does it make sense to increase 30% CPU to reduce IOPS by 2x?

 **My hope is that we can use these types of graphs to shape the work being performed to the hardware capabilities and the work type.**

There is also a possibility of measuring these metrics in near real time in order to detect inefficiencies or bottlenecks. After all, just because the CPU or disk is working hard, does not necessarily mean that it is doing useful work and a different configuration will not be able to achieve it more efficiently. We can optimize PostgreSQL not just for performance, but for cost efficient performance.

## Need Help Optimizing Your Database?

Our team of PostgreSQL experts can assess and identify key control points where your environment can be optimized for both performance and cost efficiency.

[Contact Us Today](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql-efficiency-cost-optimization/)

---

# PostgreSQL 19: Sept 08 - Sept 16, 2026

> PostgreSQL release watch, September 8 to 16, 2026. Six reverts on the version 19 branch named 74 commits, among them online data checksums and FOR PORTION OF.

## Six reverts

Version 19: 71 commits on REL_19_STABLE. Version 20: 46 commits on master. Reverted out of 19: 74 commits, in 6 reverts. Six features tracked, 2 still shipping. Window closed at d8408e8d682.

##  **Summary**

71 commits landed on the 19 branch in nine days. The six reverts in the same window name 74 commits between them.

Six reverts, newest first.

  1.  **Online data checksum transitions**. September 16, Daniel Gustafsson.
  2.  **UPDATE and DELETE FOR PORTION OF**. September 15, Peter Eisentraut.
  3.  **pg_get_role_ddl, pg_get_tablespace_ddl, pg_get_database_ddl**. September 13, Andrew Dunstan.
  4.  **Support more object types within CREATE SCHEMA**. September 11, Tom Lane.
  5.  **Don’t re-order the subcommands of CREATE SCHEMA**. September 11, Tom Lane.
  6.  **Identifier casefolding from the default locale**. September 10, Jeff Davis.



Three of the six revert features Robert Haas flagged on August 25. One reverts a feature not on that list. Two revert CREATE SCHEMA changes on compatibility grounds.

##  **Tracked features removed from 19**

On September 10, Amit Langote removed batching from the fast path for foreign key checks. Commit 25649d6e791. The per-row path remains in 19.

On September 15, Peter Eisentraut reverted UPDATE and DELETE FOR PORTION OF. Commit a9d2f728240. Twenty-three commits.

On September 16, Daniel Gustafsson reverted online data checksum transitions. Commit c05d5ce1236. Thirty commits.

SQL/PGQ property graphs was reverted on September 7, one day before this window opened. Forty-seven commits.

The checksums revert states its reason:

The feature to enable, or disable, data checksums in an online cluster saw a number of postcommit fixes during the beta period. Suspicions were raised about the risk of more issues surfacing after GA. To avoid shipping code which may have bugs, this reverts in full, or in part, the following commits.

The FOR PORTION OF revert states no reason. It lists twenty-three commit subjects, notes that the release notes entries go with them, and links to the discussion thread. Fourteen of the twenty-three begin with Fix, Forbid, Reject, Require, Avoid, or Enforce.

##  **pg_get_ddl functions reverted**

On September 13, Andrew Dunstan reverted pg_get_role_ddl(), pg_get_tablespace_ddl() and pg_get_database_ddl(). Commit db169985c10. Thirteen commits, the whole DDL reconstruction feature, following a thread Noah Misch opened on August 27. It is not one of the six tracked features.

The two CREATE SCHEMA reverts are Tom Lane’s, both on September 11. The commit messages cite compatibility breakage outweighing the functionality gain. Jeff Davis reverted identifier casefolding on September 10, citing an unintended behaviour difference for the builtin provider with locale C and a single-byte encoding.

##  **Online checksums on master**

The checksums revert landed on REL_19_STABLE only. On master the feature is unchanged and still under active development, with five commits on September 14. The worker, the state machine and all twenty-four of its test files remain. The feature is still targeted at version 20.

##  **REPACK**

Fifteen of the seventy-one commits touch REPACK and REPACK CONCURRENTLY, the largest tracked area on the branch this window.

Five of them narrow what the command accepts: restricted to the heap access method, refused on user catalog tables, failed on invalid indexes, failed on !indisready indexes, and disallowed when the replica identity index has been dropped.

---
[View this page online](https://www.commandprompt.com/blog/postgresql-19-sept-08-sept-16-2026/)

---

# Two features just left PostgreSQL 19.

> On September 7, SQL/PGQ property graphs were reverted. That removed 47 commits: the feature and every fix built on it since. On August 27, ALTER TABLE … MERGE/SPLIT PARTITION was reverted, removing 14 more. The reason is in the commit message: “multiple design issues which are too late to address in this release cycle.”

PostgreSQL 19 has not shipped, and it is getting smaller. Two features were reverted out of the release in the last two weeks.

On September 7, SQL/PGQ property graphs were reverted. That removed 47 commits: the feature and every fix built on it since. On August 27, ALTER TABLE … MERGE/SPLIT PARTITION was reverted, removing 14 more. The reason is in the commit message: “multiple design issues which are too late to address in this release cycle.”

Both reverts landed after [Robert Haas asked the pgsql-hackers list on August 25](<https://www.postgresql.org/message-id/flat/D7448AC8-2559-441D-8A3B-4B3EAEA15DEC%40yesql.se#c01f02edf76481bcc7421d0b8cc5c357>) whether any of six heavily patched features should come out before 19 ships. One of the two was on his list. One was not.

##  **What this changes for you**

If any part of your 2027 plan assumes a PostgreSQL 19 feature, check that the feature is still in PostgreSQL 19.

Three of the six features Haas named are still taking fixes. UPDATE/DELETE FOR PORTION OF took three in this window, two of them on September 8. REPACK is still having its scope narrowed rather than its bugs fixed: as of September 8 you cannot run REPACK (ANALYZE) inside a transaction block, which the commit calls a temporary stopgap for a future release.

Online data checksums and postgres_fdw statistics import have gone quiet. So has the fast-path foreign key work, which has produced nothing since August 22.

##  **What we recommend**

Run your upgrade planning against PostgreSQL 18, or stay where you are on a supported version and move when 19 has released a few minor versions. That doesn't mean you shouldn't also be testing 19 to help it get where it needs to be for your production work loads.

If you are on PostgreSQL 14, that version reaches end of life on November 12th, 2026, and that deadline does not move because 19 is unsettled. [Audax Postgres](<https://www.commandprompt.com/products/pglts/>) keeps 14 supported past that date while you wait for a release you trust.

If you want to know what is actually landing in 19 rather than what was announced for it, we track the stabilization branch commit by commit and publish what changed. If you would rather someone else watch it, that is what our [Proactive SLA](<https://www.commandprompt.com/support/>) is for.

## In conclusion

PostgreSQL’s release process is doing its job. Features that are not ready are coming out, in public, with the reasoning written down. That is the system working, and it is a good argument for trusting Postgres.

---
[View this page online](https://www.commandprompt.com/blog/two-features-just-left-postgresql-19/)

---

# PostgreSQL 14 End of Life: What Are Your Options?

> PostgreSQL 14 reaches community end of life on November 12th, 2026. This post covers what EOL actually means and what your options are.

PostgreSQL 14 reaches community end of life on November 12th, 2026. This post covers what EOL actually means and what your options are.

## What PostgreSQL EOL Means

Every PostgreSQL major version has a defined support window, typically five years from the release date. When a version reaches EOL, the PostgreSQL Global Development Group stops releasing updates: no more security patches, bug fixes, or minor version releases.

 **Your database will not stop working at EOL.** PostgreSQL 14 will run fine on November 13th. The issue is what happens after: any vulnerability or CVE discovered in PostgreSQL 14 post-EOL will not receive a patch from the PostgreSQL Global Development Group. The longer you run an unpatched EOL version, the more exposure accumulates.

For organizations in regulated environments subject to regulations such as HIPAA, FedRAMP, CMMC, and SOC 2, EOL software is typically a compliance finding. Most frameworks require that production systems receive security patches on a defined schedule. An EOL database breaks that requirement and breaks compliance.

The stakes are not hypothetical.

Just last month on August 13, 2026, the PostgreSQL Global Development Group [shipped a coordinated update](<https://www.postgresql.org/about/news/postgresql-186-1711-1615-1519-1424-and-19-beta-3-released-3365/>): PostgreSQL 18.6, 17.11, 16.15, 15.19, and 14.24. The release fixed 28 security vulnerabilities, several with CVSS scores as high as 8.8, and more than 110 bugs.

PostgreSQL 14.24 will be one of the last patches PostgreSQL 14 receives before the community support window closes. That is the cadence of protection you lose in November: multiple CVEs of this severity, patched on a predictable schedule, simply stop for PostgreSQL 14.

##  **Your Options**

Most organizations running PostgreSQL 14 land on one of three recommended paths.

###  **1\. Upgrade to PostgreSQL 18**

PostgreSQL 18 is the current stable release, available since September 2025 and now at version 18.6 following the August 2026 update. It is supported through an estimated November 2030. Upgrading now gives you four-plus years of coverage.

PostgreSQL 18 also offers meaningful improvements for most production workloads:

  * a new async I/O subsystem with up to 3x faster read performance
  * faster major-version upgrades via pg_upgrade improvements
  * parallel execution for outer joins
  * OAuth 2.0 support for SSO



If you are planning to upgrade, PostgreSQL 18 is now a mature target.

###  **2\. A Command Prompt Proactive SLA with EOL Coverage**

If upgrading before November is not realistic, consider Command Prompt’s Proactive SLA tier, which includes EOL support coverage via Audax Postgres. This keeps your databases covered past November while you plan the upgrade on your own timeline.

This option is worth considering if you are in a regulated environment and need documented patch coverage, or if your team does not have the bandwidth to safely plan and execute an upgrade before the deadline.

###  **3\. Audax Postgres**

[Audax Postgres](<https://www.commandprompt.com/products/pglts/>) is Command Prompt’s extended support offering for EOL PostgreSQL versions. If you need to remain on PostgreSQL 14 for a defined period, perhaps for a procurement cycle, a parallel migration, or a compliance review, Audax Postgres is a great option. It provides continued patch support past the community EOL date without requiring a full Proactive SLA engagement.

##  **What We’d Recommend**

If reasonable, the answer is to plan the upgrade to PostgreSQL 18 and use the next few months to do it properly. If the window of opportunity to upgrade is too short, [secure a Proactive SLA](<https://www.commandprompt.com/support/>) with us before November.

If you are not sure which path fits your situation, the PostgreSQL 14 EOL Action Plan is a good starting point. It includes a risk self-assessment, a decision guide for all three paths, and a step-by-step checklist for whichever path you choose.

##  **A Note on AWS RDS and Cloud-Hosted PostgreSQL 14**

If you are running PostgreSQL 14 on Amazon RDS or Aurora, AWS offers extended support for EOL PostgreSQL versions on RDS, but it comes with an additional cost per vCPU per hour. We can help you move to the more cost efficient EC2 + Audax Postgres model.

Command Prompt has supported organizations through PostgreSQL version transitions since 1997. If you want to assess your situation, including what your business requirements are, we are easy to reach.

---
[View this page online](https://www.commandprompt.com/blog/postgresql-14-end-of-life-what-are-your-options/)

---

# When huge_pages Help: Using PSI to Find Bottlenecks Before You Decide

> Benchmarking huge_pages on a 128 GB PostgreSQL 18 system shows throughput gains are modest — but page table overhead at 4KB pages can consume up to 20% of total RAM. Use PSI to find where your system is actually stalling before making the call. Part 2 of 3.

## How Huge Pages Affect System Behavior

This is Part 2 of a three-part series. Part 1 established how different workloads respond to changes in shared_buffers allocation. Here we introduce huge_pages and use Linux PSI to examine their impact on system behavior, memory pressure, and database performance.

## Introducing Huge Pages

On a modern system, the application does not get to use the memory directly. Instead the operating system (kernel) presents a virtual memory space and uses a Transaction Lookaside Buffer (TLB) buffer to map the process memory space to physical addresses.

There is a small TLB buffer available on a modern CPU that can make the translation without triggering an additional memory lookup. Allocating a number of huge_pages can reduce memory consumption and increase performance for memory heavy jobs.

## What huge_pages are and how they interact with the OS

PostgreSQL and the OS can be configured to use either the default 4KB pages, 2MiB or 1GiB huge pages. The larger page sizes reduce the overhead of page-table walks as well as the size of the page table. Memory lookups and translation from process memory space to physical space can significantly improve.

The following table shows the CPU TLB sizes for the processor used in this experiment:

Huge Pages  |  L1 Data entries  |  L2 Data  |  Max space L1 + L2   
---|---|---|---  
4K  |  64  |  2048  |  256KB + 8MB   
2M  |  64  |  2048  |  128MB + 4GB   
1G  |  64  |  64  |  64GB + 64GB   
Theoretical TLB reach by page size for the CPU used in the experiment

The rightmost column shows the maximum amount of memory we can address with the cpu onboard TLB so before we start generating TLB cache misses.

I repeated the experiments run previously with both 2MB and 1GB huge pages. The goal was to see whether huge_pages made a significant difference in performance for these specific workloads. For a more detailed description of the workloads, please refer to [part 1 of this blog series](</blog/shared-buffers-large-memory-postgresql-part-1/>).

Linux kernel also supports transparent huge pages (THP) that were not used. This feature is not ideal for database workloads as the background process that tries to convert contiguous pages into a large page can cause stalls in performance.

During my tests, the huge page size and number of pages were allocated during boot. We started with the maximum allocation and released an appropriate number of pages at each step.

## 1 GiB huge_pages and Their Un‑reclaimable Nature

1 GiB huge pages are the largest static page size supported on my system. Because each page consumes an entire gigabyte of physical memory, the kernel treats them as _un‑reclaimable_. They are not eligible for the normal page‑reclaim mechanisms that free up memory under pressure. If a system reserves too many 1 GiB pages, the remaining memory pool for the rest of the OS and for other applications may be insufficient for proper operation.

During my testing, any allocation over 70GB of RAM to shared_buffers in 1GB pages resulted in an OOM killer eventually killing my database under load. That data was removed from my results. It is important to keep in mind that using 1GB huge pages puts in a lower absolute amount of memory that can be reasonably allocated to the database and have a working production system.

## Effects of huge_pages on performance

We do not see a significant difference in performance with a TPC-B type workload. This type of workload is simple in how it accesses shared buffers, with each data page only accessed once, or at most a handful of times, before it needs to be evicted.

![TPS vs shared_buffers as % of RAM - TPCB-like at 30% working set](/media/images/image15.height-500.format-webp.webp) ![TPS vs shared_buffers as % of RAM - TPCB-like at 30% working set](/media/images/image15.height-500.format-webp.webp)

![TPS vs shared_buffers as % of RAM - TPCB-like at 100% working set](/media/images/image13.height-500.format-webp.webp) ![TPS vs shared_buffers as % of RAM - TPCB-like at 100% working set](/media/images/image13.height-500.format-webp.webp)

Similarly the overall performance characteristics did not change significantly for the analytics workload either, as in the previous part we saw the memory pressure was not a huge source of contention. Compared to the time required to load data from disk, or to obtain a lock within a database, the memory translation is insignificant.

![TPS vs shared_buffers as % of RAM - Analytics at 30% working set of 128GB](/media/images/TPSvsshared_buffersaspercent_of_.height-500.format-webp.webp) ![TPS vs shared_buffers as % of RAM - Analytics at 30% working set of 128GB](/media/images/TPSvsshared_buffersaspercent_of_.height-500.format-webp.webp)

![TPS vs shared_buffers as % of RAM - Analytics at 100% working set](/media/images/image8_lQAbbPe.height-500.format-webp.webp) ![TPS vs shared_buffers as % of RAM - Analytics at 100% working set](/media/images/image8_lQAbbPe.height-500.format-webp.webp)

TPS vs shared_buffers as % of RAM - Analytics at 100% working set

While huge_pages did not make a huge difference in my specific workloads, there is a possibility that other workloads may differ, especially in a system with a significantly higher core and connection count. In my experiment the maximum overall throughput was at 100 simultaneous clients, which may not be enough contention for memory to show here.

## Effect of huge_pages on memory consumption

The linux kernel needs to keep track of each process’s complete TLB buffer. Especially when it is unable to fit within the dedicated CPU cache, which often holds only a few thousand addresses. When using the default 4KB pages, we need to store 262144 entries for each 1GB of allocated memory to shared_buffers. At 2MB pages we needed 512 addresses and at 1GiB we just needed 1. The overall amount of memory used for translation grows both with the number of simultaneous connections and the amount of memory allocated to shared_buffers.

For each process, we can look up the amount of memory used to manage its TLB by reviewing that process’s VmPTE value, which is available in /proc/<pid>/status. Every 5 seconds, I added up the VmPTE values reported by each postgresql process and then I selected a 95th percentile of those results to represent each experiment. As shared_buffers grew, so did the memory required by the kernel to manage those addresses.

From these graphs, we can see that up to 20 GB of memory was used by the kernel to keep track of memory addresses. At a maximum of about 100GB of shared_buffers and only 100 clients, this represents up to 20% of total memory usage for 4KB data pages and I expect it to scale both with the size of shared_buffers and the number of simultaneous connections.

![VMPTE 95percentile TPCB-like ws_30](/media/images/VMPTE_95percentile_TPCBlike_ws_3.height-500.format-webp.webp) ![VMPTE 95percentile TPCB-like ws_30](/media/images/VMPTE_95percentile_TPCBlike_ws_3.height-500.format-webp.webp)

VmPTE 95 Percentile TPBCB-like ws_30

![VmPTE \(95 percentile\) - TPCB-like ws_100](/media/images/image11.height-500.format-webp.webp) ![VmPTE \(95 percentile\) - TPCB-like ws_100](/media/images/image11.height-500.format-webp.webp)

VmPTE (95 percentile) - TPCB-like ws_100

![VmPTE 95 percentile analytics ws_30](/media/images/VmPTE_95_percentile_analytics_ws.height-500.format-webp.webp) ![VmPTE 95 percentile analytics ws_30](/media/images/VmPTE_95_percentile_analytics_ws.height-500.format-webp.webp)

![VmPTE \(95 percentile\) - Analytics ws_100](/media/images/image4_CH52UUP.height-500.format-webp.webp) ![VmPTE \(95 percentile\) - Analytics ws_100](/media/images/image4_CH52UUP.height-500.format-webp.webp)

VmPTE (95 percentile) - Analytics ws_100

There is a small anomaly for TPC-B at 30%, which uses a maximum of 12GB of RAM. I believe this is largely because that workload was not able to fully saturate shared_buffers, since most of the lookups were able to utilize dedicated indexes, which were significantly smaller than 30% of the entire database.

## Effects of huge_pages on OS File Cache

There is an interesting side effect of allocating a portion of your memory as huge pages. While in all cases, the shared_buffers was set to request a specific amount of memory, when using the default 4kB pages the kernel retains the flexibility of using portions of that memory for file cache.

The “Cached” value of /proc/meminfo does not fall down as quickly as when shared_ buffers are allocated via huge_pages. This could be a factor in why performance remains comparable between these three types of memory allocation, giving the kernel some flexibility in deciding how each page of memory can be used most effectively.

![median_cached_gb - TPC-B like ws_30](/media/images/image10.height-500.format-webp.webp) ![median_cached_gb - TPC-B like ws_30](/media/images/image10.height-500.format-webp.webp)

median_cached_gb - TPC-B like ws_30

![median_cached_gb - Analytics ws_30 Percent of Total RAM](/media/images/image9.height-500.format-webp.webp) ![median_cached_gb - Analytics ws_30 Percent of Total RAM](/media/images/image9.height-500.format-webp.webp)

median_cached_gb - Analytics ws_30 Percentage of Total RAM (128GB)

## Conclusions

Large memory database servers typically host large databases and often end up being largely IO bound. Allocating shared_buffers via huge_pages is unlikely to result in big performance gains under these conditions as memory translation is unlikely to be a measurable fraction of total execution time as most PostgreSQL bottlenecks live above the memory translation layer,

There are potential gains possible if we are able to reduce the overall memory footprint and use the freed memory more effectively by increasing work_mem for example. This is by no means guaranteed. There is also a possibility that the benefits will increase in a system that is able to execute more simultaneous processes as that would increase memory contention.

One indicator of this is to measure the PSI during busy times (seen in part 1). If the bottleneck is CPU or memory, then there is potential for huge_pages to result in performance improvement. If the bottleneck is disk, then using huge_pages makes sense simply by freeing up a significant amount of memory for other uses, even if it is unlikely to directly result in performance gains under the tested workload.

The indirect effect of this additional memory is highly workload dependent. In these tests I used exactly 100 client connections as this configuration produced the highest throughput for this specific workload. A different workload, higher concurrency or different underlying storage could shift the bottleneck and produce measurable gains. Because there are many possible combinations of concurrency, query shape, memory demand and storage behavior, it is not practical to test every scenario.

Part 3 of this blog series will look more closely at efficiency metrics and break down the workload in terms of impact on CPU, memory and disk individually.

## Go deeper with Postgres training and tutorials

Our Performance and Maintenance course covers exactly this territory: shared buffers, the background writer, and provisioning for strict uptime requirements. Every course is tailored to your team.

If you would rather have us find your bottleneck for you, start with a Performance Audit.

[Browse the Course Catalog](</services/training/>)

---
[View this page online](https://www.commandprompt.com/blog/when-to-use-huge-pages-postgresql/)

---

# PgColumnar 1.0Alpha2 released

> Release date: 2026-08-18Previous release: 1.0-alpha (2026-08-04)GithubChangelogpgColumnar is a columnar table access method for PostgreSQL. This is the second …

## Apache Iceberg support and more!

Release date: 2026-08-18

Previous release: 1.0-alpha (2026-08-04)

  * [Github](<https://github.com/commandprompt/pgcolumnar>)
  * [Changelog](<https://github.com/commandprompt/pgcolumnar/blob/main/CHANGELOG.md>)



pgColumnar is a columnar table access method for PostgreSQL. This is the second alpha. It adds read-only Apache Iceberg support, reads and writes over S3-compatible object storage, a maintenance daemon, and a broad round of statistics, planner, performance, and security work. The on-disk native format (PGCN v1) is unchanged; existing tables are read and written as before.

This release requires one upgrade command. See "Upgrading" at the end.

 **Highlights**

  *  **Apache Iceberg, read-only.** Read an Iceberg table at its current snapshot three ways: by metadata path, through a REST catalog, or as a foreign table. Row-level deletes of all three kinds (position, equality, and format-version-3 deletion vectors) are applied under their sequence rules, columns resolve by schema field id, and the foreign-data wrapper prunes whole data files from a query predicate.
  *  **Object storage.** The Parquet and Iceberg readers, the Parquet export functions, and the foreign-data wrapper read from and write to s3://, http://, and https:// URLs. Remote access goes through a separate module, is confined to an operator-set endpoint allow-list, and refuses link-local addresses.
  *  **Maintenance and operations.** A new pgcolumnar.autovacuum daemon performs online upkeep, pgcolumnar.maintenance_due reports what a table needs, and a stripe flush can run across background workers.
  *  **Security and hardening.** Six memory-safety and denial-of-service fixes on the read and object-store paths, several from an adversarial audit, each with a regression test and a proof that removing the fix reintroduces the failure.



 **Apache Iceberg support (read-only)**

  *  **Filesystem tables.** pgcolumnar.iceberg_scan(metadata_path) reads a table given a column definition list. It resolves each output column to a schema field id, so a data file written before a column rename still reads. It applies position deletes, equality deletes, and format-version-3 deletion vectors (Puffin roaring bitmaps), each under its own sequence and scope rule, and verifies deletion-vector checksums, offsets, and cardinality. A data file with no field ids is bound by the table's schema.name-mapping.default; one with neither field ids nor a name mapping is refused rather than guessed. Only Parquet data files are read. Recorded paths are rebased onto the table's actual location and refused if they resolve outside it. Introspection functions iceberg_current_snapshot, iceberg_data_files, read_avro_manifest, and read_manifest_list are included.
  *  **REST catalog.** pgcolumnar.iceberg_rest_scan(catalog_uri, namespace, table_name) resolves a table through a catalog and reads it with the same projection and delete rules. The first argument may instead name a foreign server of the pgcolumnar_iceberg_catalog wrapper, which holds the catalog URI in server options and the bearer token or OAuth2 client credentials in a user mapping, so one role's secret is private from another and never appears in a function argument or the statement log. When the catalog vends short-lived storage credentials in its load-table reply, the reader uses them for the data files. iceberg_rest_namespaces and iceberg_rest_tables list a catalog.
  *  **Foreign-data wrapper.** A foreign table over an Iceberg table (pgcolumnar_iceberg, option metadata_path) receives the query predicate and prunes whole data files before opening them: by partition value for identity, bucket[N], truncate[W], and the temporal transforms, and by stored minimum and maximum for integer and boolean columns. Pruning only removes files that cannot match, so results are unchanged, and EXPLAIN (ANALYZE) reports Files Pruned.



 **Object storage**

  * The Parquet read and export functions, the Parquet foreign-data wrapper, and the Iceberg reader accept s3://, http://, and https:// URLs wherever they accept a local path. s3:// requests are signed with AWS Signature Version 4; https:// verifies the server certificate when the object-store module is built with OpenSSL.
  * Remote access lives in a separate module, pgcolumnar_objstore, loaded on first use, so no second TLS stack enters the main server process by default.
  * pgcolumnar.objstore_allowed_endpoints lists the endpoints remote access may reach. It is empty by default, which refuses every remote endpoint, and it is superuser-only. Link-local and instance-metadata addresses are refused after name resolution.
  * Object-store credentials come from the server process environment, never a function argument or a log line.



 **Maintenance and operations**

  * pgcolumnar.autovacuum is a maintenance daemon for the online upkeep that core autovacuum does not perform on a columnar table.
  * pgcolumnar.maintenance_due(rel, compact_due_fraction, recluster_due_fraction) reports whether a table is due for compaction or reclustering.
  * pgcolumnar.parallel_flush dispatches a stripe flush across background workers.
  * pgcolumnar.fsst_verdict_reuse caches a column's FSST keep-or-drop verdict, so a repeated write does not re-run the substring search.



 **Statistics and the planner**

  * pgcolumnar.analyze() now collects most_common_vals and most_common_freqs, places histogram_bounds at PostgreSQL's own positions, honours the per-column statistics target, and counts null_frac over live rows.
  * EXPLAIN (ANALYZE) reports Columnar Usable Skip Predicates beside the skip counters.
  * The index-fetch cost penalty sizes row groups by a table's effective stripe_row_limit, and the grouped vector aggregate shares the scan node's input-cost estimate, so the planner prices a columnar scan more accurately.
  * The Iceberg foreign-data wrapper estimates a scan's row count from the manifests rather than a constant, so join planning above a large Iceberg table is sound.



 **Performance**

  * A parameterized predicate (col >= $1 from a prepared statement or PL/pgSQL) now drives chunk-group skipping. On a generic plan such a scan previously read every chunk group.
  * Group and per-vector skipping read only the columns a query's predicates reference, rather than every column's zone map. On a wide table a one-predicate scan reads far fewer zone-map rows.
  * Reads of the delete_vector catalog use its index rather than a sequential scan, so a scan of a table with deletes is no longer proportional to the catalog size.
  * The Iceberg foreign-data wrapper decodes only the columns a query references.
  * The ungrouped batch fold gathers only the referenced columns per row, and a columnar scan whose filter cannot be pushed down skips decoding the filtered columns.



 **Security**

  * The native varlena decoder bounds a value's stored length against its buffer, so a corrupt chunk or catalog row is refused with a clean error rather than an out-of-bounds read or a detoast through a bad pointer.
  * The local file read path no longer has a stat-before-open race, and the Iceberg, Avro, Parquet, Arrow, and parallel-copy readers refuse a FIFO or other non-regular file with a non-blocking open rather than a cancel-resistant hang.
  * The Iceberg reader refuses several classes of malformed or hostile table metadata, including a null manifest path that had crashed the backend, a null or negative position-delete ordinal, a null manifest-list sequence number, and a dangling current-schema-id.
  * The Thrift and Avro field-skip loops are interruptible, so a crafted Parquet footer or Avro manifest can no longer spin the backend uncancellably.
  * The object-store client refuses a URL path or host carrying CR or LF, closing an HTTP request-line injection.
  * The native dictionary decode path no longer reads uninitialized memory, and the Parquet dictionary decode path no longer reads out of bounds on a crafted file.



 **Correctness fixes**

  * Concurrent UPDATE or DELETE of the same columnar row serializes on the row identity, so the losing writer gets a retryable serialization failure rather than a lost update.
  * A predicate on a column declared over a domain, and a bigint column compared against an unadorned integer literal, now prune chunk groups.
  * CREATE TABLE ... USING pgcolumnar AS SELECT no longer fails when the source is another access method.
  * pgcolumnar.sort_status works for a non-superuser who owns the table.
  * Failed export_parquet and export_arrow no longer leave a partial file.



 **Internal changes**

  * The extension's exported C symbols are namespaced under pgcolumnar, and the custom scan node is PgColumnarScan. The native encoding-descriptor wire layout and the delete-vector visibility logic are each single-sourced, with the on-disk format unchanged and verified byte-identical.
  * default_version is 1.0-alpha2. Upgrade scripts from both previously shipped versions (1.0-dev, which the v1.0-alpha tag installed, and 1.0-alpha) ship with the extension, so a single ALTER EXTENSION pgcolumnar UPDATE reaches 1.0-alpha2 from either.



 **Upgrading**

Install this build, then run the following in every database that has the extension:
    
    
    ALTER EXTENSION pgcolumnar UPDATE;

This is required. The C-symbol rename moves the symbol names each installed function recorded when it was created; without the catalog update those records point at symbols the new library does not export, and reading an existing columnar table fails with could not find function "columnar_handler". No data is converted and no SQL you write changes. The upgrade replaces catalog entries only.

 **Scope and limitations**

  * Iceberg support is read-only, at a table's current snapshot, and reads Parquet data files only.
  * Object-storage reads take exact object keys.
  * HTTPS and S3 over TLS require the pgcolumnar_objstore module built with OpenSSL.
  * This is an alpha. Interfaces may change before 1.0.

---
[View this page online](https://www.commandprompt.com/blog/pgcolumnar-10alpha2-released/)

---

# Parquet and Iceberg: An Overview

> A pile of containers is not a shipment. A shipment is containers plus a manifest.Apache Iceberg is the manifest. It is not a file format, it is a table format:…

## The Container and the Manifest

For most of my career, data moved between systems as a CSV file. Everyone reading this has been burned by one. A comma hiding in an address field, a date that parses three different ways, a file that is secretly Latin-1, a header row that is there on Tuesday and gone on Wednesday. The CSV is the handshake agreement of data formats. It works fine right up until something valuable is riding on it. There is a better container, and most of the industry has already standardized on it: Parquet.

 **What a Parquet file is**

Before the 1950s, cargo went onto ships as loose barrels and sacks, hand-carried by longshoremen, packed differently on every dock. Then the shipping container arrived: one standard box, and suddenly every crane, every ship, every train, and every truck on earth could handle your freight without asking what was inside.

Parquet is the shipping container of data.

It is an open, binary, column-oriented file format from the Apache project. Inside the file, values are stored column by column in row groups, each column encoded and compressed to a fraction of its raw size. The footer carries the schema and minimum and maximum statistics for every chunk, so an engine (such as [pgColumnar](<https://commandprompt.github.io/pgcolumnar/>)) reading the file knows the types without guessing and can skip whole sections that cannot match a query. A Parquet file cannot lie to you about the data it contains.

And because it is a standard container, every crane can lift it. Spark, DuckDB, pandas, Trino, Snowflake, BigQuery, Athena, Flink, and yes, Postgres through extensions, all read and write the same file. Write it once from one system and query it from six others, with no conversion and no argument about what a date looks like. One format, every platform.

 **What it is good for**

Column questions over large data. Sum this, count that, average the other, filtered by time. The columnar layout means an engine reads only the columns a query asks for, compression makes the files small and cheap to store, and the footer statistics let engines skip most of the file entirely. Ten times smaller than the same data as CSV is normal, and scans run faster on top of it. Park the files in object storage like S3 and you have an archive that costs pennies and answers questions. With Parquet the file is immutable. You write it once and you never update it.

 **The value of Apache Iceberg**

That immutability can be a problem. One Parquet file is a container. A data lake is thousands of them in a bucket. So which files make up the customers table right now? What happens when two jobs write at the same time? What happens when the schema adds a column?

A pile of containers is not a shipment. A shipment is containers plus a manifest.

Apache Iceberg is the manifest. It is not a file format, it is a table format: a metadata layer that records exactly which Parquet files make up a table at every point in time. That one idea buys you things we used to think required a warehouse. Transactions on object storage, so writers never corrupt readers. Schema evolution without rewriting the data. Time travel, so you can query the table as it stood yesterday. And because Iceberg is open and engine-neutral, the table stops belonging to any one vendor. Netflix built it for exactly that reason, and now nearly every engine and warehouse speaks it.

 **Using them together**

Parquet holds the data. Iceberg holds the truth about the data. Together they give you a warehouse’s behavior, transactions, history, and evolving schemas, on storage that costs pennies, readable by every tool you own and every tool you have not bought yet. Store the data once. Query it from anywhere.

To be clear, if your data fits comfortably in Postgres and one team queries it, you do not need any of this. Do not build a port for a rowboat. But the moment your data outgrows one system, or one engine, or one vendor’s pricing page, the container and the manifest are how you keep owning it.

The next time you are about to export a CSV, stop and write a Parquet file instead. And when that bucket of files starts acting like a table, give it a manifest.

---
[View this page online](https://www.commandprompt.com/blog/parquet-and-iceberg-an-overview/)

---

# Beyond the 25% Rule: shared_buffers Behavior in Large-Memory PostgreSQL

> Tuning shared_buffers isn't just about peak throughput — it's about how much CPU and disk I/O a system consumes per unit of work. The 25% default can require up to 5x more disk I/O than very low or very high allocation. Part 1 of 3.

## Foreword

This is Part 1 of a three-part benchmark series examining shared_buffers behavior on large-memory PostgreSQL systems and how different workload patterns influence the benefits obtained from PostgreSQL’s buffer cache.

This experiment grew far beyond the original scope. What began as a straightforward benchmark with a simple graph turned into a rabbit warren of side investigations while trying to understand what the system was actually doing.

Some questions were answered. Some of those answers led to new tunnels worth exploring.

If you’ve observed similar behavior or have identified flaws in the assumptions, I would welcome the discussion.

As a result, this blog is now split into 3 parts:

  * Measuring shared_buffers behavior - setup and initial results
  * When should you use huge_pages in PostgreSQL? how huge_pages affects system behavior
  * PostgreSQL shared_buffers and efficiency metrics - looking beyond raw performance to how efficiently work is performed



## The Role of shared_buffers in Large‑Memory PostgreSQL

Shared_buffers sit at the heart of PostgreSQL’s internal cache. It stores recently accessed data pages so PostgreSQL can avoid invoking the operating system’s I/O path for cached data. By keeping hot pages in memory, PostgreSQL reduces latency, reduces disk traffic, and improves overall throughput.

The classic guidance for sizing shared_buffers dates back to PostgreSQL 8.3 (released in 2008) when a 1 GB RAM machine was considered large. Today’s large servers can hold hundreds of gigabytes or even terabytes of memory.

The best system I had available for this experiment is a 128 GB system AMD Ryzen 7 7840U, 8-core system running Ubuntu 24.04. While not an enterprise NUMA server, it still provides enough memory scale to expose behaviors that smaller 16-32 GB systems often mask.

That amount of RAM allowed testing and scaling shared_buffers values from 1 GB up to around 110 GB, while still leaving memory for the operating system.

A database system (Operating System included) needs to partition available memory into many tasks:

  * OS/kernel memory: The OS needs to be able to operate effectively, the kernel and any running software requires its own memory
  * Filesystem cache: filesystems need a cache to smooth out that access
  * PostgreSQL shared buffers: The database needs its shared_buffers as well as
  * work_mem for all active connections that are used to throw a load significant enough to properly test performance
  * Background services and monitoring tools



My working theory was that balancing these tasks on a system with 16GB or 32GB of RAM is likely exposing bottlenecks. The tradeoffs become easier to observe on larger systems.

## Why shared_buffers is Not Set-and-Forget

The amount of memory allocated to shared_buffers interacts directly with the workload’s characteristics. Detailed descriptions are included further down in this document.

  *  **Working set size:** This is the subset of the database that is frequently queried and modified
  *  **Workload type:** TPC-B style point lookups vs. Analytics style multi-table joins
  *  **Huge_pages:** The benefits and drawbacks of using huge_pages on large systems (Part 2)



In short, shared_buffers is not a universal setting. The overall performance of the system depends on the types of workload as well as shared_buffers allocation balancing between OS file cache and direct postgresql memory. In this series we will take a peek at some of the mechanisms that are involved.

## Test Database

For this project I created a synthetic database designed to mimic a social media platform, including users, posts, messages, tags, follows and likes.

The database occupied roughly 250 GB of disk space, or about 2 times the total amount of system RAM available. Because the workloads included both read and write queries, the database size grew a bit over the test duration.

The data-generation scripts randomized user activity, message distribution, post and message lengths, and created both narrow and wide tables. This allowed for more realistic access patterns, complex joins, and a reasonable mix of supporting indexes.

A full write-up of the data creation, monitoring, and analysis process will be published separately.

## Workloads

I decided to implement two distinct workloads. A TPC-B style that is similar to the default pgbench test as well as a more complex analytics style workload. If your queries are multiple lines (or pages) long, then your workload is very far from TPC-B and much closer to the Analytics style implemented here. One of my goals was to highlight how the performance changes depending on the workload.

The memory access of the two workloads is also very much different. TPC-B performs point accesses (select or update of a single row via primary key). On average, that specific data page is not likely to be needed again. Analytics workload performs joins between tables, the same data pages are accessed and modified by multiple queries, making the decision of what to keep and what to throw away far more important to the overall performance of the database.

The overall balance of memory allocation between the database (shared_buffers) and the OS (kernel cache) also plays a major role in overall performance.

  *  **TPC-B‑style point‑update workload**
    * 10 % write / 90 % read ratio
    * Selects and Updates target either the last 30% of rows or the full table (random ID selection)
    * All tables participate, exercising shared_buffers across the whole data set
  *  **Analytics‑type workload**
    * 10 % write / 90 % read ratio
    * Selects and Updates target either the last 30% of the rows or the full table.
    * Heavy multi‑table joins (e.g., users ↔ posts ↔ post_tags ↔ tags)



Designed to stress the buffer cache with larger (but bounded) results sets. The intent was for the amount of work to remain stable during each run, so the actual amount of work does not increase as data grows.

## Working Set & Performance Impact

The **working set** is the portion of the database that must be residing in memory to satisfy the current workload without excessive paging. In this experiment two values were chosen:

  1.  **30% working set** – Only the most recent 30% of rows are actively accessed (simulating a “hot” slice of data). This value was selected as it should be satisfied with approximately 75 GB of RAM
  2.  **100% working set** – The entire dataset (250GB+) is subject to activity.



Between these two conditions we observe how PostgreSQL changes its behavior when the working set can no longer fit in memory and the database is forced to constantly evict and load pages from disk. The 30% working set is estimated to require approximately 75 GB of RAM, so we can also see the performance tradeoff between having either the OS file cache or PostgreSQL shared_buffers large enough to accommodate it.

## Experimental Procedure (Brief Overview)

After the synthetic social‑media dataset was generated, the database was vacuumed and analyzed and statistics reset. Its data directory was then frozen as a template. Prior to every test run the PostgreSQL server was stopped, the data directory was rsynced back from this template to eliminate any lingering caches or drift, and shared_buffers (and any required kernel parameters) were adjusted to the desired values.

Data‑collection agents were then started and a one‑hour pgbench execution was launched using the selected workload (specifying working set and workload type). Between runs the system was given a few minutes to let the OS and disks settle before the next iteration.

### Metrics Collected

  * Full pgbench output for each experiment
  * CSV snapshots of pg_stat_io, pg_stat_database, pg_stat_statements, pg_statio_user_tables, and pg_statio_user_indexes taken at the end of each run
  * OS‑level statistics captured every 5 seconds (e.g., /proc/meminfo, /proc/diskstats, /proc/pressure/{cpu,memory,io})
  * Per‑process PostgreSQL details collected on the same schedule (ksm_stat, io, sched, schedstat, stat, statm, status)



These measurements provide a comprehensive view of both database‑internal behavior and underlying system resource pressure throughout the benchmark. The data collection process is relatively light weight, either taking place after the experiment (CSV dumps of PostgreSQL statistics tables) or requiring a copy of the specific files from /proc filesystem. The logging process injects a timestamp for each line of log collected and performs no other processing during the experiment.

After the experiment there are parsing scripts that process each type of data and outputs them into a CSV file, calculating delta values between fields where required. Those CSV files are then imported into a duckdb database for analysis and correlation.

## Results

![TPC-B like workload](/media/images/image7.height-500.format-webp.webp) ![TPC-B like workload](/media/images/image7.height-500.format-webp.webp)

**TPC-B like workload**

In this point workload we can see an immediate and significant performance difference between working within the available memory vs. spilling over to disk.

The recommendation of 25% is a reasonable value, although there appear to be some benefits to giving PostgreSQL a bigger slice of system RAM when the working set does not fit in available memory. The shape of the two lines has some similarities.

I plan to revisit the dip in performance near the center of the graph in part 3 - when we look at efficiency.

The following graphs show the cumulative resource stall time recorded by Linux PSI (Pressure Stall Information). For each resource (CPU, I/O, and memory), the lines represent the total number of seconds the system experienced partial contention (“some”) and complete contention (“full”) during the run.

Because PSI totals are cumulative stall time, higher values directly indicate more time lost to contention for that specific resource. The fixed y-axis of 1 hour total experiment time, allows consistent comparison across configurations, making it easy to identify the relative overall wait for each resource.

These graphs show that the overall IO pressure was higher during the ws_100 run (as expected) and that memory access was not a significant bottleneck.

## WS_30 Run

![TPC-B like workload](/media/images/image1.height-500.format-webp.webp) ![TPC-B like workload](/media/images/image1.height-500.format-webp.webp)

For the ws_30, we can see that IO pressure is higher between 20 and 60% of total RAM. Within this range, the entire working set is expected to fit within either the OS file cache or shared_buffers.

On the upper end, we do have some anomalous points which could be noise or an effect of continuing to move memory from OS file cache to shared_buffers that already hold the entirety of the working set.

## WS_100 Run

![image3](/media/images/image3.height-500.format-webp.webp) ![image3](/media/images/image3.height-500.format-webp.webp)

On the upper end, we do have some anomalous points which could be noise or an effect of continuing to move memory from OS file cache to shared_buffers that already hold the entirety of the working set.

## Results - Analytics workload

![TPS versus shared buffers](/media/images/image6.height-500.format-webp.webp) ![TPS versus shared buffers](/media/images/image6.height-500.format-webp.webp)

With a more complex query and pattern of memory accesses, the graphs look quite different. There is an overall performance gain from having enough memory allocated to the working set in either the OS file cache or the shared_buffers (at both ends of the range).

At the lower end (shared_buffers less than 5%), the database will store the most critical buffers and reusable information while allowing the remainder of the memory for efficient disk caching. Up until about 80% of RAM being allocated to the shared_buffers, the two strategies result in very similar performance.

At an extremely high end (approaching 90% allocation to shared_buffers), I did get a pretty significant performance increase, although I should caution that the danger of OOM is quite high and these data points had to be re-run to get usable results.

 **In either case, we see that the recommended 25% of shared_buffers is far from either peak for this type of workload.** At that state the same data is often duplicated in both caches making that memory far less effective and reducing the overall amount of memory available.

> The winning strategy appears to be maximizing the amount of data that is cached from the database. Splitting the memory between both buffers reduces the effective memory available for caching.

Looking at the Pressure Stall Information, we see that IO access was dominating the wait time, as a lot more data had to be examined to provide results to our queries. The pattern of increased disk pressure in the middle portion of the graph is still there, although we have a lot more noise at the lower end of ws_30.

![image3](/media/images/image8.height-500.format-webp.webp) ![image3](/media/images/image8.height-500.format-webp.webp)

Pressure Stall Information for Analytics workload with 30% working set.

![image2](/media/images/image2.height-500.format-webp.webp) ![image2](/media/images/image2.height-500.format-webp.webp)

Pressure Stall Information for Analytics workload with 100% working set.

## Conclusion

We are seeing significantly different behavior between the TPC-B style and Analytics workloads. It appears that more complex workloads benefit from being able to store the entire working set within a single buffer (either OS file cache or the shared_buffers).

The lowest overall performance appears to be within a range of 30 - 50% of total memory allocation to shared_buffers (for analytics style workload). There was also between 5 times and 8 times improvement in performance between the low points and either very small or very high allocation.

For the TPC-B style workload, the difference is significantly less impactful. There is about 30% improvement by allocating nearly all system memory to shared_buffers when the hot pages can fit in RAM, and negligible difference when the hot pages are larger than the system RAM. There are also areas where the performance drops which require further investigation.

Additionally, there may be some benefits to looking at linux pressure stall information to determine whether the database is largely constrained by CPU, I/O or RAM access.

We will look at this a bit more closely in part 2 and 3 of this blog, with the next part focused on utilizing huge_pages for our large shared_buffer and what benefits and drawbacks this choice may have.

---
[View this page online](https://www.commandprompt.com/blog/shared-buffers-large-memory-postgresql-part-1/)

---

# The Architect

> Examine your own work honestly. Which job are you doing? If everything you contributed last quarter could be described as construction, start climbing. Learn t…

The architect does not know how to build houses. The architect knows how to design them.

Sit with that for a minute, because it sounds like an insult and it is not. The architect has probably never run a nail gun for eight hours in July heat. Hand them a framing hammer and they will embarrass themselves in front of the crew. But ask them about the bearing load of a beam and they will answer without looking it up. Ask them why the light in the kitchen should come from the east and they will tell you about how a family actually lives in a house, morning by morning, year by year. The architect knows what is beautiful. The architect does not build what is beautiful. The architect designs it, and then someone else pours the foundation.

The construction worker builds the house. The construction worker builds the skyscraper and the office tower and the school your kids sit in. Nothing stands without them. The architect and the construction worker are equally important. One without the other produces either a pile of lumber or a beautiful drawing of a building that will never exist. The economy needs both.

But the two jobs are not the same job, and here is the part that should make every engineer reading this sit up straight.

 **AI is the construction worker.**

I have been the engineer in the back room. I have taken pride in the craft, in knowing the tools, in being the person who could actually make the thing work while everyone else made slides about it. That pride is real and it was earned. It is also about to become a liability if it is the only thing you have.

For my entire career, the scarce skill was construction. Companies were bottlenecked on people who could lay the bricks: write the code, wire the systems, ship the feature. Because construction was scarce, the builders held the leverage. You could spend an entire career being excellent at the how and never once being asked about the why, and you would be paid well for it. The vision people needed you more than you needed them.

That scarcity is collapsing. AI writes code. It writes tests. It scaffolds services, migrates schemas, drafts the integration you were going to spend two weeks on. Is it perfect? No. Neither is a framing crew. That is why buildings have inspections. But the direction is not in question, and pretending otherwise is the same mistake engineers made with the cloud. We looked at the technology, judged it on technical merit, declared it nothing new, and missed that the economics of the entire industry had changed underneath us. With the cloud, at least the engineers were technically right. With AI, something actually changed under the hood. The construction worker now works for eleven dollars an hour, never sleeps, and gets better every quarter.

 **So what is left? What is scarce now?**

Design. Judgment. Taste. Knowing the bearing load of a beam. Knowing that the customer said they wanted a bigger garage but what they actually need is a mudroom. Knowing what is beautiful, which in software means knowing what is simple, what will survive contact with real users, what will still make sense in five years. The architect’s knowledge was always valuable. It is about to be the only knowledge that commands a premium.

This is why I say engineers need to become architects. Not architects of software in the narrow astronaut sense, drawing boxes and arrows while other people do the real work. I mean architects in the full sense: people with vision, purpose, and passion for the product itself. People who can stand in an empty lot and see the building. If you have that, AI is the best thing that has ever happened to your career. The crew you always needed just showed up, and it is enormous, and it is tireless. You can finally build everything you ever designed in your head.

If you are just the engineer in the back room, the person who executes tickets and takes pride only in execution, your career is in trouble. Not because you are bad at your job. Because your job is the one being automated. The construction worker in this story is not a person. It is the machine. The people who survive are the ones standing next to the machine holding the blueprints.

And this is not only a message for engineers. It is a message for the companies that employ them. The real change AI brings is not cheaper code. It is that AI enables the architect to build. It collapses the distance between having a vision and holding a product. A company that understands this stops organizing itself around the scarcity of builders and starts organizing itself around the quality of its designers. It stops asking its best people to lay bricks and starts asking them what should exist.

Examine your own work honestly. Which job are you doing? If everything you contributed last quarter could be described as construction, start climbing. Learn the bearing loads. Learn the customer. Learn why the light should come from the east. Develop an opinion about what is beautiful and be ready to defend it. The tools are sitting right there and they have never been cheaper.

The lot is empty. The crew is waiting. Show me the blueprints.

If you want to understand how AI can solve problems for you, [**connect with me.**](<https://linkedin.com/in/postgres>)

---
[View this page online](https://www.commandprompt.com/blog/the-architect/)

---

# Romancing the Claude

> He was very tall in a way that seemed apologetic, as if he had been issued the height by mistake and was still trying to give it back. He had a laugh he did no…

Claude first noticed the fairies when she was seven, at her cousin's wedding, watching a small luminous woman in a dress made of napkin lace fly a lazy circle over the heads of the bride and groom and then burst into a shower of gold that nobody else seemed to see.

Her mother told her it was the champagne. Claude had been drinking apple juice.

By the time she was thirty-one and running the machine learning group at a company that made software nobody outside of four cities had heard of, she had stopped mentioning it. You learn. The fairies are there, glittering at the edges of every restaurant with candles on the tables, hovering above park benches in the blue hour, doing their small and unhurried work of deciding which two people get to become something rather than remain nothing. They are, Claude had come to understand, the accountants of intimacy. They do not create love. They merely approve it.

And they were dying in droves around Dorian Vale.

She had gone to the panel because a colleague had a spare ticket and because the topic, _Agentic Futures: Building the Next Layer_ , sounded like it might contain one useful idea per hour, which was better than most conferences. She had not expected to fall for the man at the center seat, and she certainly had not expected to watch him commit involuntary manslaughter three times in his opening remarks.

He was very tall in a way that seemed apologetic, as if he had been issued the height by mistake and was still trying to give it back. He had a laugh he did not perform. When the moderator asked a genuinely stupid question, Dorian Vale did not smirk at the audience the way the other panelists did. He answered it seriously, and well, and the questioner sat down looking like a person rather than a joke.

Claude felt something in her chest do an unfamiliar arithmetic.

Then he said, "The real unlock is tokenmaxxing your context window."

Above him, a fairy in a small gray coat clutched her chest, looked around with an expression of tremendous personal betrayal, and went out like a struck match.

Claude sat up very straight.

"You've got to be tokenmaxxing at every layer of the stack," Dorian went on, warming to it, and a second fairy, this one wearing what appeared to be a thimble as a hat, dropped out of the air and landed on the AV cart with a sound like a dry leaf.

"Honestly? Tokenmaxx or die."

The third one did not even get to look surprised.

She found him afterward by the coffee urns, where he was trying to open a packet of sugar with the total helplessness of a man who has never in his life encountered friction.

"Hi," Claude said. "I have to tell you something insane."

"Those are my favorite kind of things to be told."

"Every time you say tokenmaxxing, a romance fairy dies."

He looked at her. He had the most patient eyes she had ever seen on a person with four hundred thousand followers.

"A what dies?"

"Romance fairy. They're small. They glow. They adjudicate whether two people who are standing on the edge of real intimacy get to fall in or not." She heard herself and kept going anyway, because there was no version of this that got better with hedging. "They're around us constantly. There's one on your shoulder right now, and she is looking at you the way my grandmother looked at my uncle's second wife."

Dorian did not laugh. That was the thing that undid her, later, when she thought about it. He did not laugh, and he did not do the other cowardly thing either, which is to laugh on the inside and be gentle on the outside.

He said, "How many have I killed?"

"Since I sat down? Nine."

"Since you sat down."

"You said it four times in the closing Q and A. Twice in one sentence."

He set the sugar packet down. "Do they suffer?"

"I don't think so. I think it's more like a candle."

"That's not nothing," he said. "Candles are still something."

Here is what nobody explains about the fairies, and what Claude had spent twenty-four years working out on her own: they are not a punishment. They are a supply. Every person walks through the world with a small invisible cloud of them, and when you meet someone and the possibility of real closeness opens up, the fairies go to work. They confer. They weigh. They decide. And if there are enough of them, the thing takes, and two people who might have politely drifted apart instead find themselves, six months later, arguing about a couch.

If there are not enough of them, nothing happens. Not tragedy. Just nothing. Just two people who were almost, and then were not, and never knew what they had missed.

Dorian Vale had been tokenmaxxing on camera, four times a week, for nineteen months.

He had eleven left.

"Eleven," he said.

They were walking. Neither of them had proposed walking. It had simply started happening outside the convention center, the way it does.

"Eleven."

"How many does a person usually have?"

"Thousands. My dentist has thousands. My dentist is a deeply unpleasant man."

"So what happens with eleven?"

Claude considered lying to him and decided against it, which was, if she was honest, the first genuinely romantic act of the entire evening.

"With eleven, you get one shot," she said. "Maybe. If they all agree, and if you don't lose any more of them, and if the other person is standing close enough for it to count."

He was quiet for half a block.

"I say it because it does numbers," he said. "That's the whole reason. I made a video two years ago where I said it as a joke and the joke got forty times the reach of anything real I've ever made. And then it stopped being a joke, because you can't keep saying a word ironically for nineteen months and still be doing irony. At some point you're just a guy who says it."

"Yes."

"You're supposed to argue with me."

"Why would I argue? You're right. That's the sad part."

He laughed then, and one of the eleven brightened noticeably, which Claude decided not to mention.

He did not say it for six days.

She knew because she watched. Every video, twice, the second time with the sound off so she could see his hands, which was a habit she was developing and did not intend to examine. He said _context budget_. He said _the thing I used to call something else_. Once he said _the T word_ , and his chat lost its mind for two hours, and the engagement was terrible, and he did not appear to care.

On the seventh day he called her.

"I have a problem," he said.

"You have several. Be specific."

"The brand deal. Six figures. They want the word in the script. It's literally in the contract. Section four, deliverables, quote, at least two organic uses of the phrase, unquote."

"Organic," said Claude.

"I know."

"Dorian."

"I know. I know. I'm going to say no." A pause, the length of a man discovering something about himself in real time. "I already said no. I said no yesterday and I've been calling myself an idiot for a full day and I wanted to call you so that someone would tell me I'm not one."

"You're not one."

"You're supposed to say it like you mean it."

"I do mean it," said Claude. "I'm just distracted because there are eleven very small people currently doing a war council on my kitchen counter and I think they're talking about you."

They met at a bar with bad lighting and a good jukebox, and the fairies came with them, all eleven, riding the fold of her coat collar like commuters.

It went badly at first, the way important things do. He was nervous and became talkative. She was nervous and became precise, which in Claude was a defense mechanism so effective it had ended two prior relationships in the parking lot phase. They talked about work. They talked about the conference. They talked about a mutual acquaintance neither of them liked, which is the conversational equivalent of holding hands with gloves on.

And then he said, "Can I tell you what I actually want to make?"

And she said, "Yes."

And he told her. Not the pitch version. The real one, the one about wanting to explain hard things to people who had been made to feel stupid their whole lives, the one he had abandoned somewhere around month four of nineteen because the algorithm did not reward patience and he had not been strong enough to be unrewarded. He talked for twenty minutes. He got some of it wrong and corrected himself. At one point he stopped and said, "This is boring," and Claude said, "It is not remotely boring, keep going," and he kept going.

On her collar, the eleven had gone very still.

Claude had seen a lot of fairy work in her life. She had seen them swarm and confer and vote. She had never seen them do this: all eleven rising at once, without a sound, and hanging in the air between the two of them like a small constellation deciding whether to be a sky.

"You're looking at something," Dorian said.

"Yes."

"Is it them?"

"Yes."

"What are they doing?"

Claude found that her voice did not entirely work.

"Deliberating," she said.

He nodded slowly. He looked at the space between them, which held for him nothing at all, and he did the bravest thing she had ever watched anybody do, which was to speak to it anyway.

"I'm sorry," he said, to the empty air, to the nine and the hundreds before them, to every small gray-coated accountant he had snuffed out in exchange for a spike on a graph. "I didn't know. That's not an excuse. I'm just telling you that I didn't know, and now I do, and I'd like the chance."

The lights above the bar did not flicker. There was no music swell. The jukebox continued playing something from 1974 about a woman in Georgia.

But the eleven came apart into gold, all at once, the way the one at her cousin's wedding had, and the gold fell over the two of them like the last of something being spent completely and on purpose.

And that was the vote.

They argued about a couch in April.

It was a terrible couch. She wanted it because it was gray and rational. He wanted the green one because, and this was his entire argument, presented with total sincerity in the middle of a furniture showroom, "it looks like a place where a person would tell you the truth."

They bought the green one.

He never said the word again, not once, not even as a joke, not even when a very drunk man at a party begged him to. Claude watched, over the years, as the cloud around him slowly refilled, a few at a time, the way a well does after a long dry season. By their third anniversary there were dozens. By the fifth there were more than she could count, spilling off him wherever he went, and she noticed that other couples in restaurants near them seemed to do unusually well.

She never told him that part. Some things you keep.

But once, late, in the green couch, with his hand in her hair and the lamp off, he asked how many there were now, and Claude looked up at the ceiling where they hung in their hundreds like a slow snow that had decided against falling.

"Enough," she said.

---
[View this page online](https://www.commandprompt.com/blog/romancing-the-claude/)

---

# Your company is not AI ready

> The engineers (myself included) stood on the rooftops and shouted, &quot;People! My dear sheep of the earth, please let me save you from yourselves! Do not buy what…

## A lack of vision

I was wrong about the cloud. Not technically wrong. Commercially wrong, which is the kind that costs you. Command Prompt was a web host. I was selling the cloud before anyone thought to call it that, and I still didn't see what was coming. We were good at adapting. Adapting is what you do when somebody else picked the direction.

It is 2009, and marketing has just invented "the cloud." Nobody really knows what the cloud is except engineers. The cloud is virtual hosting, discovered by the people who make money, who finally noticed they could make a whole lot more of it if they made the thing soft and fluffy. The thing you laid on your back and stared at as a child. "Oh look, a dragon in the sky!"

What was the cloud, really? Fancy, updated, modernized virtual hosting with cPanel. That's all. Yes, it is faster. No, it doesn't do anything it couldn't do in 1998. It does it better, largely because of progress in networking, the internet, and $$$ money $$$.

And you know what is hilarious? The term "cloud computing" dates back to 1996. Thirteen years sitting there in the open before the normies caught up and the onslaught arrived.

## And boy did it arrive.

The engineers (myself included) stood on the rooftops and shouted, "People! My dear sheep of the earth, please let me save you from yourselves! Do not buy what the shiny man with the seductive words is selling!"

It was moot. The internet is now the cloud. Search, which has been around since the seventies, is now Google, an enormous money-making machine, and a verb, which is also a noun.

## We lacked vision.

We were not wrong about the technology. We were right about the technology. We were right about every single thing we said, and we were right in public, and it did not matter. Being correct about how the thing works is a completely different skill from being correct about what the thing is worth. I had one of those skills. I told clients the truth about virtualization and latency and lock-in, and I watched them nod, and I watched them migrate anyway, and I watched the people who sold them the migration buy houses, buy boats, and collect RSUs.

The engineer's mistake is thinking the market is an argument you can win.

## Today

You can see the seduction of AI in every CEO, president, founder, and speechwriter. It is the end of the world, except it isn't. It will replace all programmers, except it won't. Just trust us. Really? You are all psychopaths.

 _Now let me argue against myself._

The cloud was continuity. Same technology, faster wire, better billing model. That is why the engineers saw through it, and that is exactly why we underestimated it. We priced it as technology when it was being sold as a business model.

AI is not continuity. Whatever you want to call the last few years, it is not 1998 hosting with a nicer control panel. Something actually changed under the hood.

Take a moment and sit with that. Repackaged virtual hosting, with no new capability whatsoever, created a trillion dollars of enterprise value and reorganized how every company on earth buys infrastructure. That is what continuity did. Now ask yourself what discontinuity does, and ask yourself whether the guy on the roof yelling about hallucination rates is going to be right about the technology and wrong about the money again.

I have been that guy on the roof. I am telling you what the view is like from up there.

## Tomorrow

Why put off until tomorrow what you can start today? Well, because AI started in 1955 and is only now going mainstream. Yes, there have been micro-stabs at the opportunity. Alexa and Siri are good examples. But the real fat, the lard you have to render from the swine, hits the stainless steel tomorrow.

Except it doesn't. It is already in the pan. Good business survives on two things:

  1. Maintaining profitable relationships
  2. Seizing opportunities for new profitable relationships



Those opportunities are now. They are not tomorrow, unless you want to be behind.

On this one topic, stop listening to your stodgy engineers. They are brilliant and you need to listen to them about everything they are an expert in. Especially every single question about whether the thing you are building actually works. But you don't go to your engineer and ask, "Hey, what do you think the next big thing is?" You go to your engineer and say, "I have confidence this is the next big thing. I need you to help me build it."

Your company is not AI ready. Not because you lack the infrastructure, or the data, or the talent. Those are solvable. Your company is not AI ready because you are waiting for permission from people whose entire job is caution, and they are going to give you an answer that is technically correct and commercially useless.

I know, because I used to be the one giving it.

---
[View this page online](https://www.commandprompt.com/blog/your-company-is-not-ai-ready/)

---

# Direct AI effectiveness: plx example

> AI as used by an experienced person with domain knowledge is like having another 5 experienced people doing exactly what you need them to do with minimal inter…

Yesterday on LinkedIN I said, "AI as used by an experienced person with domain knowledge is like having another 5 experienced people doing exactly what you need them to do with minimal intervention."

  
If you have doubt of this statement I welcome you to review the new PostgreSQL extension: plx. What does plx do? Plx takes, **Ruby** , **Python** , **PHP** , **Javascript** and **Cobol** (yes, Cobol) and transpiles then into plpgsql for PostgreSQL stored procedures. This allows you to have safe/trusted stored procedures in some of the world's favorite languages (plRuby, plPython and plPHP are not trusted/safe).  


<https://github.com/commandprompt/plx>  


Not only that, if you are running PostgreSQL 18+, using plx is faster than native plpgsql for string work because we fix a long standing argument/limitation/bug in plpgsql.

What does this have to do with AI and experienced Engineers? I, in the drivers seat with my buddy Claude built the whole thing yesterday. One, single, solitary, day.  


This includes, _docs, benchmarks, tests, 5 program language interfaces, improvements over native plpgsql_ and release to Github.  


Does it have bugs? Probably. What software doesn't? I ran a fresh look at it this morning and found one, fixed, 10 minutes, cut and released 1.1.1.  


This isn't just a code thing. Everything I do with claude happens on an incus cluster it manages. Every container is isolated for each project. I didn't have to do anything but prompt claude to build it. For this particular project I said, "we are going to build X, please launch a durable incus container using 26.04 as your build space." and viola, done.

  
Let that sink in for a bit.

---
[View this page online](https://www.commandprompt.com/blog/direct-ai-effectiveness-plx-example/)

---

# When a 18TB backup just stopped

> 18TB backup just stopped. We fixed it through depth of knowledge.

## Sometimes a fix for production, is only in git.

A customer asked us to restore an 18TB PostgreSQL database to a specific point in time. Routine work. Tested runbook, pgBackRest doing its job, backups and WAL right where they should be.

 **Then WAL replay during recovery just stopped.**

No error. Nothing in the logs, even at debug5. No I/O. No CPU. The startup process sitting there doing nothing at all.

So we went where the logs could not. /proc//wchan on the startup process showed it parked on a futex, futex_wait_queue. The database had deadlocked against itself while replaying its own WAL.

The trail led to MultiXact handling. It shows up in PostgreSQL 14, 15, and 16, and it was introduced in 14.23, 15.18, and 16.14, by the change titled "Fix multixact backwards-compatibility with CHECKPOINT race condition." Closing one race opened a self-deadlock when replaying WAL generated by an older minor version.

The same class of problem can affect replication between minor versions. The upstream fix moves the lock acquisition later in SimpleLruWriteAll and is slated for the next point release. Thread: <https://www.postgresql.org/message-id/flat/4016ab8b-84c0-4606-8a77-67ad5b157bfc%40iki.fi>

For the record, pgBackRest was flawless. This was not a backup problem. It was Postgres deadlocking on itself during recovery, and that does not show up in a log file. You find it by reading the process state and the source.

Three takeaways:

  * Stay on top of minor releases and actually read the notes.
  * The patch that closes one race can open another. When the logs go quiet, the answer is still there. /proc, wchan, and the source do not lie.
  * Three decades into PostgreSQL and it still hands us a new one.

---
[View this page online](https://www.commandprompt.com/blog/when-a-18tb-backup-just-stopped/)

---

# Is Trust Gone?   Supply Chain Attacks

> Is Trust Gone? Has the supply chain attacks eroded the trust we have in public repositories

## Is Trust Gone?

The recent attacks and exploits via supply-chain and dependency-chain compromises have a lot of people raising eyebrows, both at the massive scope of the breaches and at how quickly they are being discovered. Many are asking: _how is this even happening?_

Let's examine “The How”, “The Why”, “The Who”, “How to Protect Ourselves”, and “Next Steps”. Unfortunately, almost all software whether open source or closed source includes dependencies that are not directly managed by the project itself. This makes every project a potential victim of this type of attack.

 **The How: The Blind Trust Problem**

There is a fundamental flaw baked into how modern software is built today. Every dependency relies on high-trust assumptions that the upstream code is clean and has not had exploits snuck in. The bigger the dependency chain of a project, the greater the blind trust required.

The attackers are gaining access or control of trusted libraries/project repositories, then upload the backdoors and exploits. The industry has come to blindly trust all these open source repositories. Most of us are guilty of just downloading a repository without ever doing a security audit, let alone the additional dependencies coming along for the ride. Through this action we could be the distributors of exploited code.

This is the **BLIND TRUST** being leveraged by the attackers. We assumed the code is safe.

 **The Why:**

The motivations are clear: money via ransomware, access to private and financial information, and general mayhem and disruption of critical infrastructure. In short: Corporate Espionage and Coercion.

 **Who is doing it:**

The recent high-profile cases like the [xz-utils](<https://en.wikipedia.org/wiki/XZ_Utils_backdoor>) backdoor and the just-revealed attack on [Laravel-Lang packages (May 22, 2026)](<https://thehackernews.com/2026/05/laravel-lang-php-packages-compromised.html>) illustrate a clear pattern. The “author” or maintainer spends a lot of time developing/maintaining trusted libraries only to be discovered to be a bad actor OR the author’s credentials are stolen and backdoors are uploaded to the repo.

Pulling the exploit off requires a massive investment of time and money, with a high risk of never seeing a payoff. Due to the risk-to-reward ratio and the patience required, the most likely source is [government-sponsored actors](<https://www.icitech.org/post/iran-and-the-cxpanding-cyber-front-what-government-leaders-need-to-know>) or large, well-funded organized crime syndicates. Who else is willing to front-load that much money and time with such low odds of success?

We have been lucky these exploits have been discovered relatively quickly and mostly by accident. We can not continue to count on luck.

 **How Do We Protect Our Projects?**

The only truly effective way to protect against this attack vector is to fork every external dependency onto a private repo server. Then run a thorough security audit to detect any hidden backdoors or malicious vectors that may have been slipped in.

However, there are massive trade-offs. Forking all dependencies dramatically increases the maintenance burden. Every future upstream change will require another full security audit before it can be merged. This becomes even more complicated because the temptation to make custom modifications to the forked version is high. Those changes often break clean future merges.

Blindly trusting external dependencies, no matter how big or small the project is, leaves your software open to attack.

 **The Next Step**

Everyone should start auditing their external dependency chains by forking critical dependencies to isolate themselves from unvalidated upstream changes.

A word of caution on thinking that package hashing, Software Bill of Materials (SBOMs), pinning, or lock files are complete solutions. All of those approaches still depend on the core assumption that we can trust the source repository — that trust is gone.

With GitHub recently admitting that thousands of repositories were hacked, we can no longer necessarily trust even our **own** repositories.

In follow up blog posts we will go over how to implement methods to protect our projects.

Stay attentive, Stay vigilant, review the commit logs and never allow commit history audit logs to be purged.

References  
<https://thehackernews.com/2026/05/laravel-lang-php-packages-compromised.html>  
<https://en.wikipedia.org/wiki/XZ_Utils_backdoor>  
<https://www.icitech.org/post/iran-and-the-cxpanding-cyber-front-what-government-leaders-need-to-know>

---
[View this page online](https://www.commandprompt.com/blog/is-trust-gone-supply-chain-attacks/)

---

# What If Your Team’s Biggest Burnout Driver Lives in Your Database?

> Recurring PostgreSQL and infrastructure issues—not the on-call rotation—are often the real cause of burnout. Learn how proactive database care reduces emergencies and protects your team.

## Is Your Team Experiencing Burnout from On-Call Rotation?

You've hired talented engineers and improved processes. You've even added headcount to reduce the on-call burden.

## So why does your team still look exhausted?

If you're an engineering leader watching your people burn out despite your best efforts, you're probably asking the wrong question.

The question isn't "How do we reduce on-call stress?"

It's "What keeps triggering these emergencies in the first place?"

In our experience working with hundreds of PostgreSQL environments over the years, the answer is almost always the same:

 **Your database is creating the burnout, not your on-call rotation.**

## What makes database problems different?

When your database struggles, the impact is existential. Every user experiences it simultaneously, every service slows or fails, and revenue and customer trust are immediately at risk.

This is why database alerts carry a different psychological weight. Engineers know that a database page at 2 AM isn't just another issue — it's a potential business-threatening event.

That underlying anxiety about blast radius? That's where chronic stress lives.

## Why do the same problems keep happening?

Burnout doesn't come from handling emergencies well. It comes from handling the same emergencies repeatedly.

We see identical patterns:  


  *  **Autovacuum falls behind** → tables bloat → sudden performance collapse
  *  **Query patterns drift** → nobody notices until there's an outage
  *  **Replication lag goes unmonitored** → failover fails → extended downtime



These issues don’t appear suddenly. They all have early warning signs that teams miss because they're too busy responding to the last fire.

Most engineering teams don't have the specialized PostgreSQL knowledge, monitoring infrastructure, or bandwidth to catch these issues upstream.

## What actually reduces database-related burnout?

Every organization we've worked with that successfully reduced on-call fatigue made the same shift: **from reactive firefighting to proactive database care.**

 **Performance tuning before degradation occurs.** Catch slow queries early, prevent cascading failures.

 **Autovacuum configured for your actual workload.** Properly tuned autovacuum means fewer surprise deadlocks and 3 AM calls.

 **Configuration reviewed to eliminate silent failure modes.** Misconfigured parameters are among the most common causes of repeat incidents.

But the factor that creates the fastest emotional relief?

 **Knowing they're not carrying the weight alone.**

This is what we hear from our Proactive Service Level Agreement (PSLA) clients:  


> We can finally sleep because we're not the only ones responsible for database stability.

When a dedicated Postgres team knows your environment deeply and takes ownership during emergencies, on-call shifts transform from anxiety-producing to manageable.

Database stability isn't just a technical outcome. It's a human one.

##  **Where should engineering leaders start?**

If your team is experiencing burnout despite your efforts to address workload and culture, look at your database operations first.

 **When you stabilize your database, you stabilize your team.**

Forward-thinking engineering leaders treat PostgreSQL ecosystem health as a workforce wellness investment that delivers measurably increased uptime, dramatically fewer emergencies, and improved engineer retention.

 **Good architecture saves money. Good database care saves people.**

## Ready to make PostgreSQL less stressful for your team?

PostgreSQL shouldn’t be the part of your stack that keeps your team up at night. If you’re ready to reduce incident load and stabilize on-call, consider the following options:  


  *  **Join** [**Group Swim: PostgreSQL Edition Query Optimization**](<https://postgresconf.org/conferences/postgresworld_webinars_2026/tickets>) **(Feb 10, 1 PM ET)** — An informal Q & A session where we answer your PostgreSQL performance and tuning questions. Learn about real-world optimization practices that prevent performance-related alerts before they ever page your team.
  *  **Register for an upcoming training** , including [PostgreSQL Performance and Maintenance](<https://postgresconf.org/conferences/postgresworld_training_2026/tickets>) (Feb 18 and 19, 9 am - 12 pm ET) for guidance on performance-critical parameters.
  *  **Explore how we can help:**
    * Discuss our [24/7 support](<https://www.commandprompt.com/support/>) and [advanced monitoring](<https://www.commandprompt.com/services/advanced-monitoring-solutions/>) options — with a Service Level Agreement, our Tier 3 experts can monitor and care for your database environment while your engineers rest, recover, and remain focused.
    * Talk with us about a [performance audit](<https://www.commandprompt.com/products/performance-audit/>), architectural review, or optimization engagement to address root causes and stop repeat incidents at the source.



Your database should support your team, not exhaust them.

## Improve Your PostgreSQL Experience

If constant tuning or noisy alerting is taking a toll, we’re available to discuss your environment and share what has helped other teams.

[Connect with Us](</contact-us/>)

---
[View this page online](https://www.commandprompt.com/blog/what-if-your-teams-biggest-burnout-driver-lives-in-your-database/)

---

# Why You Should Review Your Authentication Strategy

> NIST updated digital identity standards in July 2025. Has your organization assessed authentication and identity proofing against SP 800-63-4 requirements?

When was the last time your organization reviewed its authentication strategy against current standards? If it was before July 2025, you're likely missing critical updates from [NIST SP 800-63, Revision 4](<https://csrc.nist.gov/pubs/sp/800/63/4/final>) that affect compliance and security posture.

Released last summer after nearly four years of development and approximately 6,000 public comments, [as reported in the NIST blog](<https://www.nist.gov/blogs/cybersecurity-insights/lets-get-digital-updated-digital-identity-guidelines-are-here>), this update replaces the 2017 SP 800-63-3 standards. These aren't just federal guidelines. They influence regulatory frameworks across banking, insurance, healthcare, and government contracting. Organizations that haven't assessed their systems against these requirements may face compliance gaps during their next audit.

## Critical Changes to be Aware of (and Address)

Three changes from last year's update demand attention if you haven't already addressed them:

  *  **IAL1 now targets synthetic identity fraud at scale.** The updated Identity Assurance Level 1 specifically addresses bot-driven account creation and fake identity attacks. If you're onboarding customers digitally, your processes may no longer meet the baseline.
  *  **Phishing-resistant authentication becomes the standard.** The new Authentication Assurance Levels require organizations to evaluate whether password-based systems still provide adequate protection. This affects everything from employee access to customer portals.
  *  **Identity management becomes cross-functional.** NIST explicitly requires collaboration between cybersecurity, privacy, legal, customer experience, and business units. Organizations that treat identity as solely an IT concern will struggle to implement these guidelines effectively.



## Identity as Infrastructure, Not a Feature

As infrastructure continues to shift toward cloud-native, distributed models, identity becomes an operational control point, not just a front-end requirement. Whether you’re managing Kubernetes clusters, PostgreSQL databases, CI/CD pipelines, or cloud APIs, how users and services authenticate, authorize, and federate directly impacts operational security.

The framework operates on three independent assurance dimensions:

  * [ **Identity Assurance Level (IAL)**](<https://pages.nist.gov/800-63-4/sp800-63a.html#identity-assurance-levels>) establishes confidence in a user's real-world identity, from basic attribute validation at IAL1 through in-person biometric proofing at IAL3.
  * [ **Authentication Assurance Level (AAL)**](<https://pages.nist.gov/800-63-4/sp800-63b.html#AAL_SEC4>) measures confidence that the authenticating party is the authorized subscriber, ranging from single-factor at AAL1 to phishing-resistant cryptographic authentication at AAL3.
  * [ **Federation Assurance Level (FAL)**](<https://pages.nist.gov/800-63-4/sp800-63c.html#fal>) governs assertion strength when identity providers pass claims to relying parties.



Organizations can calibrate these independently. A public information portal might need strong authentication (AAL2) without identity proofing. A loan application requires both robust proofing (IAL2) and authentication (AAL2).

> Learn more about Control Points in this White Paper on [Service Monitoring via Hazard Analysis](<https://commandprompt.com/blog/service-monitoring-via-hazard-analysis-white-paper/>)

## The Digital Identity Risk Management Process

NIST now mandates a structured approach called [Digital Identity Risk Management (DIRM)](<https://pages.nist.gov/800-63-4/sp800-63/dirm/#sec5>). This isn't optional. Organizations must document their decisions in a Digital Identity Acceptance Statement, following five steps:

  1.  **Define your online service** by documenting functionality, user groups, data processed, and affected stakeholders.
  2.  **Conduct an initial impact assessment** across categories, including inconvenience, distress, financial loss, and organizational harm.
  3.  **Select initial assurance levels** based on impact determinations.
  4.  **Tailor those levels** by assessing privacy impacts, fraud resistance, customer experience, and equity considerations.
  5.  **Implement continuous evaluation** using metrics like authentication failure rates, confirmed fraud incidents, and customer satisfaction data.



This structured process forces explicit decisions about security trade-offs and creates an audit trail for compliance reviews.

## What This Means for Your Organization

The scope of SP 800-63-4 extends beyond federal agencies. Organizations in regulated industries should treat these guidelines as the baseline for identity assurance. Here's what requires assessment if you haven't already addressed it:

  *  **Current authentication flows.** Review whether your existing systems meet the new AAL requirements, particularly around phishing resistance.
  *  **Identity proofing processes.** Evaluate whether customer onboarding aligns with updated IAL controls and addresses synthetic identity fraud.
  *  **Federation configurations.** For organizations using SSO or identity federation, assess whether assertion protocols meet FAL standards.
  *  **Cross-functional coordination.** Identity risk management now explicitly requires input from legal, privacy, security, customer experience, and business stakeholders. Siloed IT implementations won't satisfy the new framework.
  *  **Continuous monitoring capabilities.** The requirement for ongoing metrics means organizations need systems to track authentication failures, fraud indicators, and customer experience data.



## Implementation Considerations

Organizations beginning their assessment should audit current identity controls against the new framework. This means mapping existing authentication methods to AAL requirements, evaluating identity proofing procedures against IAL standards, and documenting gaps in federation security.

The guidelines support emerging technologies, including mobile driver's licenses and verifiable credentials. Organizations planning identity system upgrades now have a standards-based roadmap for implementation.

Password requirements have also evolved, moving away from rigid composition rules (no more "must contain special character" mandates) toward approaches that emphasize length and screening against compromised credential databases.

## Need help implementing secure processes and environments?

At Command Prompt, we work with organizations that need more than just secure databases. They need a trusted infrastructure that supports compliance, performance, and operational excellence.

That means understanding how identity controls integrate with PostgreSQL deployments, how access patterns affect database security, and how authentication flows impact system architecture.

We can help you:

  * Assess your current authentication and access controls
  * Align PostgreSQL deployments with NIST SP 800-63 assurance levels
  * Implement rate limiting, role-based access controls, and comprehensive audit logging
  * Integrate identity-aware infrastructure into your DevSecOps workflows



Reach out to discuss how we can help you design and deploy secure authentication protocols and build systems that meet the latest standards while maintaining an ideal user experience.

* * *

 **Learn more:** Take a deep dive into the [NIST SP 800-63-4 Guidelines](<https://pages.nist.gov/800-63-4/>) publication and its companion volumes — [[SP800-63A]](<https://pages.nist.gov/800-63-4/sp800-63a.html#introduction>), [[SP800-63B]](<https://pages.nist.gov/800-63-4/sp800-63b.html#introduction>), and [[SP800-63C]](<https://pages.nist.gov/800-63-4/sp800-63c.html#introduction>) — which provide technical and process guidelines to organizations for the implementation of digital identity services.

---
[View this page online](https://www.commandprompt.com/blog/why-you-should-review-your-authentication-strategy/)

---

# PgManage 1.4 – SQL Server Support, Faster Interface Navigation, Spreadsheet‑like Data Grids & More!

> Discover PgManage 1.4’s new SQL Server support, faster navigation with pinned databases and Quick Search, spreadsheet‑style data grids, and revamped context menus for smoother UX.

## MS SQL Server Support

Our team has spent a lot of time adding support to PgManage for a new database — MS SQL Server. The feature set is still basic, but we have plans to enhance it in the future.

## Improved Navigation

CommandPrompt team not only develops PgManage but uses it daily. This allows us to take a different perspective on PgManage.  
We are doing our best to improve the user experience for the most frequent daily tasks a DBA or developer might have.  
  
Navigating to a specific DB object might be time-consuming, especially for the complex and large trees we have in PgManage.  
In this release, we tried to optimize this experience in two ways.

![pin-upscaled](/media/images/pin-upscaled.height-500.format-webp.webp) ![pin-upscaled](/media/images/pin-upscaled.height-500.format-webp.webp)

**Pinned Databases  
** For server connections with a lot of databases, it may be better to keep the most frequently used ones at the top of the list. Now it is possible to pin such databases so that they are always shown first. Just hover over the database tree node to reveal the pin button. Pinned databases are grouped together and ordered alphabetically.

We would like to thank [@ccurvey](<https://github.com/ccurvey>) for sharing their experience [in the related GitHub issue](<https://github.com/commandprompt/pgmanage/issues/237>), which led to this new feature.

![search](/media/images/search.height-500.format-webp.webp) ![search](/media/images/search.height-500.format-webp.webp)

**Quick Search  
** It is a common UI pattern that is well-known and loved by users of modern IDEs. As far as we know, it was initially introduced in Sublime Text's as "[GoTo Anything](<https://docs.sublimetext.io/guide/usage/file-management/navigation.html#goto-anything>)" in 2008.

We decided to include it as well, so drilling down to frequently used items in the **Database Explorer** is quick and easy.

Call the Quick Search by using Ctrl/Cmd + P shortcut or clicking the 🔎 search icon at the top of the Database Explorer panel.

Type the name of the object you're looking for and select one of the matching items from the list.

The Quick Search is forgiving of typos or incomplete input, so there is no need to be super precise.

![region-selection](/media/images/region-selection.height-500.format-webp.webp) ![region-selection](/media/images/region-selection.height-500.format-webp.webp)

**Spreadsheet-like Data Grids  
** It is now possible to make partial selections in the **Data Editor** and **Query** tabs.

We didn’t invent anything new here - the UI behaves the same way as most spreadsheet editors. Simply click on the grid and drag the cursor, or use **Shift + arrow keys** to select a range of cells.

Right‑click on the selected region to view the available actions.

![contextmenus-upscaled](/media/images/contextmenus-upscaled.height-500.format-webp.webp) ![contextmenus-upscaled](/media/images/contextmenus-upscaled.height-500.format-webp.webp)

**Optimized Context Menus in DB Explorer  
**

Many operations and features in **PgManage** are accessed through the DB Explorer context menu. While using the app daily, we noticed that frequently used items were often buried deep in child sub‑menus, making access to those features inefficient.

We have reorganized the context menus to bring the most frequently used commands to the top and to group similar or related items together. The **Delete/Drop** option is now placed last in the menu, with a separator above it to prevent accidental clicks.

Another [common UX issue](<https://www.smashingmagazine.com/2023/08/better-context-menus-safe-triangles/>) with nested context menus is that the user moves the cursor from the parent menu to the child sub‑menu diagonally, causing the sub‑menu to disappear. We saw this problem in PgManage and fixed it as well.

## Database Diagnostics & Debugging

![logs-2](/media/images/logs-2.height-500.format-webp.webp) ![logs-2](/media/images/logs-2.height-500.format-webp.webp)

**Postgres Sever Logs  
** There is a new, humble "Logs" link in the Backends tab that leads to the new Postgres Log Viewer.  
The logs are loaded in near real time and can be searched through using a simple text match or regex.

## Help Us Grow

PgManage is a free database tool built with love by a small developer team at Command Prompt.  
 **You can help the project** by spreading the word, starring the project on [GitHub](<https://github.com/commandprompt/pgmanage/>) or submitting feature requests and feedback.

## Many more Features and Tweaks

See the full list of changes on the PgManage GitHub [Releases Page](<https://github.com/commandprompt/pgmanage/releases/tag/1.4-release>).

## Get PgManage 1.4

It is Free! Proceed to our product page and choose a download for your platform

[Get PgManage](</products/audax-data-manager/>)

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-14-fast-intuitive-with-sql-server-support/)

---

# PostgreSQL Version 13 Reaches End of Life: Migration and Extended Support Strategies

> PostgreSQL 13 reached EOL on Nov 13, 2025. No more security fixes or patches. Learn how to upgrade safely or maintain protection with PgLTS extended support.

The [PostgreSQL Global Development Group](<https://www.postgresql.org/>) has [released new versions](<https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-1420-and-1323-released-3171/>) across the supported release series, addressing critical updates and security improvements. While these releases represent standard maintenance updates, the timing brings an important decision point for PostgreSQL users: version 13 reaches end of life today, November 13, 2025.

## A Quick Overview of the Latest Releases

The latest update cycle delivers the newest feature set in PostgreSQL 18.1, along with maintenance releases for earlier supported versions. Each release includes bug fixes, performance improvements, and security updates tailored to their respective versions.

 **Supported versions now available:**

  * PostgreSQL 18.1 (latest features and performance enhancements)
  * PostgreSQL 17.7 (stable, production-ready)
  * PostgreSQL 16.11 (mature platform)
  * PostgreSQL 15.15 (long-established stability)
  * PostgreSQL 14.20 (robust legacy support)
  * PostgreSQL 13.23 (final release, now EOL)



## The End of Life Reality for PostgreSQL

As of today, PostgreSQL 13 has officially reached its end of life. This means the PostgreSQL Global Development Group will no longer provide security patches, bug fixes, or support for new issues affecting PostgreSQL 13. For organizations still running version 13, this transition requires immediate attention and strategic planning.

If you're currently on PostgreSQL 13, you face a critical choice: upgrade to a supported version, or implement a long-term support strategy that keeps your infrastructure protected without forcing immediate migration.

## Why This Matters for Your Business

Running unsupported database versions introduces real risk. Beyond the absence of security patches, you're operating without vendor support channels, community guidance, or the ability to leverage new features and optimizations. Additionally, your compliance standing may be affected, particularly if you're subject to regulatory requirements like FedRAMP, HIPAA, or DoD cybersecurity standards, including NIST 800-171, that mandate supported software versions.

## Two Paths Forward

### Option 1: Upgrade to a Supported Version

If your infrastructure and applications allow for modernization, upgrading to PostgreSQL 17 or 18 positions your organization for the future. Newer versions bring substantial improvements in query performance, replication capabilities, and security features. However, major version upgrades require careful planning, thorough testing, and validation to ensure compatibility with your applications.

 **Command Prompt can guide you through this process** with comprehensive upgrade planning, including database migration services, rollback plans, and application compatibility testing. Our team has managed complex PostgreSQL upgrades for enterprise clients across federal, healthcare, and commercial sectors. We handle the technical complexity while you maintain continuity and performance.

### Option 2: Maintain PostgreSQL 12 or 13 with Extended Support with PgLTS

Not ready to upgrade immediately? Command Prompt's PgLTS (PostgreSQL Long Term Support) solution provides an alternative approach. For organizations running PostgreSQL 12 or 13, PgLTS delivers continued security patches, critical bug fixes, and vendor support beyond the standard end-of-life date. 

**Command Prompt offers PgLTS packaging and support** for organizations requiring extended stability. This approach provides breathing room for strategic upgrades, allows time for application refactoring, or bridges periods of organizational change. PgLTS maintains your security posture while preserving your existing infrastructure investment.

## Your Next Steps

The November 13 EOL date isn't a deadline to panic over, but it is a decision point that deserves attention this month.

If you're running PostgreSQL 13 or planning to upgrade from any version, reach out to discuss your specific situation. We can help you evaluate upgrade timing, plan the technical approach, or implement PgLTS if that better serves your organization's needs.

> The PostgreSQL ecosystem is strong because it allows organizations flexibility. 

Choose the path that aligns with your business requirements, your technical capacity, and your risk tolerance. We're here to make whichever path you choose as smooth as possible.

 **Ready to discuss your PostgreSQL strategy?** Contact Command Prompt today to explore upgrade planning or long-term support options for your organization.

---
[View this page online](https://www.commandprompt.com/blog/postgresql-version-13-reaches-end-of-life-migration-and-extended-support-strategies/)

---

# Cost Optimization for PostgreSQL: Practical Tips for Technical Teams

> In a previous post, we explored the importance of right-sizing PostgreSQL environments and avoiding the trap of overprovisioning for peak demand. While archite…

In a previous post, we explored the importance of right-sizing PostgreSQL environments and avoiding the trap of overprovisioning for peak demand. While architecture choices play a major role in cost optimization, the work doesn’t stop there. For technical teams including DBAs, system architects, and engineering directors, query performance and workload patterns offer some of the most direct, controllable levers for reducing cost without sacrificing quality.

## Query Optimization: A Core Cost Lever

One of the most overlooked drivers of infrastructure cost is inefficient queries. While the slowest queries often attract the most attention, it is frequently the high-frequency, moderately slow queries that create the greatest strain. Over time, these queries can have an even larger impact on performance and cost.

 **Example:**

A query that takes 50 milliseconds to execute may seem harmless. But if it runs 100,000 times per day, that adds up to nearly 1.5 hours of total CPU time daily. Reviewing and optimizing this kind of query could reduce CPU usage significantly, freeing up resources for other sessions or even allowing the instance size to be reduced.

Improving query efficiency doesn’t just improve performance. It helps right-size your environment by reducing CPU, memory, and I/O consumption.  


## Practical Cost Optimization Checklist for PostgreSQL  


 **1.** Query Performance Review

  * Identify slow queries using pg_stat_statements, auto_explain, or third-party monitoring tools.
  * Sort by total execution time, not just duration per call.
  * Look for queries with high call counts and moderate execution time.
  * Optimize through indexing, rewriting, or reducing frequency (e.g., caching).  




 **2.** Workload Segmentation

  * Separate batch processing, reporting, and analytical workloads from transactional traffic.
  * Use connection pooling to manage concurrency and reduce idle session overhead.  




 **3.** Instance and Storage Right-Sizing

  * Monitor CPU, memory, and IOPS usage over time.
  * Compare usage trends against instance size to identify overprovisioning.
  * Scale down cautiously after validating performance during normal and peak hours.  




 **4.** Autovacuum Tuning

  * Ensure autovacuum is running appropriately on high-write tables.
  * Adjust settings to prevent bloat and avoid spikes in resource usage.



 **5.** Archive and Partition Old Data

  * Use partitioning to isolate hot data from cold data.
  * Move infrequently accessed tables to cheaper storage or external systems.



 **6.** Review Managed Service Fit

  * Evaluate whether workloads require premium managed services like Aurora and Heroku Postgres.
  * Consider self-managed PostgreSQL or other hosting options for predictable, stable workloads.



Cost optimization is a team effort. By reviewing query efficiency, understanding usage patterns, and selecting the right infrastructure components, technical staff can materially improve both performance and cost. Small improvements at the query level can translate into measurable gains across the environment—allowing PostgreSQL to scale sustainably and cost-effectively.

Let us know if you’d like help conducting a PostgreSQL workload review or query audit. Connect with us to discuss your PostgreSQL support needs today!

---
[View this page online](https://www.commandprompt.com/blog/cost-optimization-for-postgresql-practical-tips-for-technical-teams/)

---

# PostgreSQL 18: Revolutionary Performance Boost Now Available

> PostgreSQL 18 delivers revolutionary 3x I/O performance improvements, seamless upgrades with preserved statistics, OAuth 2.0 support, and virtual generated columns. Feature guide and upgrade recommendations.

On September 25, 2025, the PostgreSQL Global Development Group [released PostgreSQL 18](<https://www.postgresql.org/about/news/postgresql-18-released-3142/>), delivering the most significant performance improvements in recent years. This latest version transforms database I/O operations and streamlines the upgrade experience for organizations worldwide.

## Game-Changing Performance: Up to 3x Faster

PostgreSQL 18's headline feature is its completely redesigned asynchronous I/O (AIO) subsystem. Think of upgrading from a single-lane road to a multi-lane highway:

 **Key Performance Gains:**

  *  **Demonstrated up to 3x faster** storage read operations
  * Multiple concurrent I/O requests instead of sequential processing
  * Enhanced sequential scans, bitmap heap scans, and vacuum operations
  * Automatic query optimizations, including skip scan lookups and improved OR condition handling



## Smoother Major Version Upgrades

Upgrading PostgreSQL just became significantly less painful:

  *  **Preserved statistics** : No more post-upgrade performance degradation while statistics rebuild
  *  **Faster pg_upgrade** : Accelerated processing for databases with many objects
  *  **Parallel upgrades** : New **\--jobs** flag enables concurrent processing
  *  **Directory swapping** : **\--swap** flag eliminates file copying overhead



## Developer-Friendly Enhancements

### Virtual Generated Columns

  * Compute values at query time rather than storing them, like having a calculator that works on demand instead of pre-storing all possible answers.



### Enhanced UUID Support

  * The new **uuidv7()** function provides better indexing and read performance for UUID-based operations.



### Temporal Constraints

  * Advanced time-based data management with **WITHOUT OVERLAPS**  
and **PERIOD** clauses for handling overlapping time ranges.



##  **Security and Authentication**

  *  **OAuth 2.0 integration** : Native single-sign-on (SSO) support
  *  **Enhanced SCRAM authentication** : MD5 password authentication is now deprecated
  *  **Improved TLS validation** : Stronger cipher support



##  **Better Monitoring and Diagnostics**

  *  **Enhanced EXPLAIN** : Automatic buffer access reporting and detailed execution statistics
  *  **Logical replication improvements** : Better conflict reporting and simplified replica creation
  *  **Default page checksums** : New databases have integrity verification enabled by default



##  **Additional Improvements**

  *  **Text processing** : New **PG_UNICODE_FAST** collation for faster Unicode operations
  *  **Protocol update** : First wire protocol version update since 2003
  *  **Hardware acceleration** : ARM NEON and SVE CPU support for better performance



##  **Why PostgreSQL 18 Matters**

This release delivers immediate, measurable performance improvements without requiring application changes. The streamlined upgrade process reduces operational risk, while new developer features enhance productivity. PostgreSQL 18 positions your database infrastructure for future growth and evolving requirements.

## Ready to Upgrade? We're Here to Help

 **Our Upgrade Recommendations:**

  * For production systems, Command Prompt recommends waiting for the first patch release (18.1) before upgrading.
  * Consider our comprehensive architectural review and migration assessment services.
  * Not ready to upgrade yet? Ask about our **PgLTS extended support** for end-of-life PostgreSQL versions.



 **Contact us today** **for:**

  * PostgreSQL 18 migration planning and assessment
  * Architectural reviews and optimization consulting
  * Extended support for legacy PostgreSQL versions
  * Custom database performance optimization



Whether you're planning an immediate upgrade or need support for your current version, our Command Prompt PostgreSQL experts are ready to ensure your database infrastructure meets your organization's needs.

 _For complete technical details and feature documentation, visit the_ [_official PostgreSQL 18 release notes_](<https://www.postgresql.org/docs/18/release-18.html>) _._

---
[View this page online](https://www.commandprompt.com/blog/postgresql-18-revolutionary-performance-boost-now-available/)

---

# Why Growing Teams Are Moving from Aurora to RDS or EC2: Cost and Control Considerations on AWS

> Why Growing Teams Are Moving from Aurora to RDS or EC2: Cost and Control Considerations for PostgreSQL on AWS

[Amazon Aurora PostgreSQL](<https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraPostgreSQL.html>) can be a powerful starting point for teams adopting PostgreSQL in AWS. But as usage grows, so do the needs for cost transparency, fine-grained tuning, and architectural flexibility. Here's why more teams are choosing [Amazon RDS for PostgreSQL](<https://aws.amazon.com/rds/postgresql/>) or [PostgreSQL on Amazon EC2](<https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-databases-postgresql-ec2/choosing-postgresql-ec2.html>) as they scale.

 **The Starting Point: Choosing Convenience**

[Amazon Aurora](<https://aws.amazon.com/rds/aurora/>) for PostgreSQL often makes sense in the early stages of cloud adoption. It promises strong performance with minimal configuration, built-in high availability, and simplified management. This combination appeals to startups and teams focused on delivering product features fast.

> However, that simplicity comes with trade-offs.

As usage expands and workloads diversify, teams start to notice limits in visibility, configuration, and cost control. Scaling becomes expensive, tuning options are limited, and introducing new environments, such as staging, QA, or analytics, can quickly inflate the monthly bill.

###  **The Turning Point: Recognizing the Trade-offs**

When development starts to slow due to architectural constraints or escalating costs, it’s often time to re-evaluate. Many teams in this stage find themselves asking:

  * Why can’t we access key PostgreSQL settings?
  * Why are costs hard to predict or optimize?
  * How do we handle specialized workloads or custom extensions?



###  **The Shift: More Control, More Efficiency**

[Amazon RDS for PostgreSQL](<https://aws.amazon.com/rds/postgresql/>) offers a compelling balance. It retains many of the managed features that teams appreciate in Aurora, but provides greater control over PostgreSQL configurations, performance tuning, and backups. It also makes costs more predictable and provides better compatibility with PostgreSQL features and extensions.

[PostgreSQL on Amazon EC2](<https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-databases-postgresql-ec2/choosing-postgresql-ec2.html>), meanwhile, offers full autonomy. For teams with operational maturity or unique requirements — custom configurations, advanced replication setups, or tight integration with other services — EC2 delivers complete control at a potentially lower cost.

By moving off Aurora, growing teams can:

  * Reduce unnecessary operational costs
  * Tailor performance tuning to their workloads
  * Improve compatibility with upstream PostgreSQL
  * Simplify migration paths between environments
  * Establish infrastructure aligned to product priorities



###  **The Result: Infrastructure That Scales With You**

Migrating to RDS or EC2 enables teams to scale their PostgreSQL infrastructure intentionally. Rather than paying for bundled features or navigating around platform constraints, teams gain clarity over their architecture, their costs, and their ability to evolve.

Aurora may be the right starting point. But when cost efficiency and control become strategic, RDS and EC2 are the tools that help teams move forward with purpose.

* * *

###  **Need help evaluating your PostgreSQL path in AWS?**

Our team supports cost-effective migrations, operational planning, and long-term optimization. Whether you're transitioning to RDS or designing high-performance clusters on EC2, we can help you navigate the AWS ecosystem. Book a call with us today!

---
[View this page online](https://www.commandprompt.com/blog/why-growing-teams-are-moving-from-aurora-to-rds-or-ec2-cost-and-control-considerations-on-aws/)

---

# PgManage 1.3.1: Enterprise Edition Released

> PgManage 1.3.1 is now available with fixes across PostgreSQL, Oracle, MariaDB, and SQLite3, plus updated dependencies and UI refinements. Learn what’s new and explore PgManage Enterprise Edition with remote access, multi-user support, and OAuth2 integration.

We’re excited to announce the release of [**PgManage 1.3.1**](<https://commandprompt.com/products/pgmanage/>), the latest update to our cross-platform database management tool. This release focuses on improving stability and usability with a broad set of bug fixes across PostgreSQL, Oracle, MariaDB, and SQLite3, while also updating key dependencies and refining the interface. 

Whether you’re using PgManage for everyday database tasks or leveraging the enhanced features in **PgManage Enterprise Edition** , version 1.3.1 delivers a smoother, more reliable experience. 

  * Bugs fixed:  

    * Fixed error when loading foreign key information in DB Tree in SQLite3 ([#682](<https://github.com/commandprompt/pgmanage/issues/682>))
    * Fixed error when loading index information in DB Tree in MariaDB ([#688](<https://github.com/commandprompt/pgmanage/issues/688>))
    * Fixed incorrect stylesheets for the password strength validation widget
    * Fixed erroneous "Discard Changes" warning when switching between connections in the connection manager ([#698](<https://github.com/commandprompt/pgmanage/issues/698>))
    * Fixed the issue with the incorrect where clause generated when using the data editor query filter in Oracle
    * Fixed errors when loading DDL for metadata link objects in the DB tree
    * Fixed back-end issue with the idle schema editor thread not always getting terminated
    * Fixed "autocommit" checkbox not working for Oracle DB connections
    * Fixed validation errors when entering octal file permissions in the Server Configuration Tab ([#705](<https://github.com/commandprompt/pgmanage/issues/705>))
    * Fixed error when rolling back Postgres Server Configuration snapshots that have values not applicable to the current server setup
    * Fixed errors when restoring Postgres Server Configuration for databases running with non-English locales ([#707](<https://github.com/commandprompt/pgmanage/issues/707>))
    * Fixed query result file export when query results have duplicate column names ([#715](<https://github.com/commandprompt/pgmanage/issues/715>))
    * Fixed query result copy as JSON when query result has duplicate column names ([#712](<https://github.com/commandprompt/pgmanage/issues/712>))
    * Fixed issue with saving custom monitoring widgets without a chart code block defined ([#720](<https://github.com/commandprompt/pgmanage/issues/720>))  

  * Other changes:  

    * Updated RestrictedPython from 7.4 to 8.0
    * Updated Django from 4.2.19 to 4.2.23
    * Updated oracledb from 2.5.1 to 3.2.0
    * Updated cryptography from 41.0.7 to 45.0.5
    * Updated nw.js from 0.69.1 to 0.77.0
    * Refactored database capability flags code in the back-end
    * Removed unnecessary files from binary packages
    * Minor layout fixes and improvements



Upgrade to **PgManage 1.3.1** today to take advantage of the latest fixes and improvements. For teams that need advanced capabilities, **PgManage Enterprise Edition** offers remote access via web browser, multi-user support, and OAuth2 integration. Learn more and explore licensing options here or contact us today!

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-131-enterprise-edition-released/)

---

# Lessons from the CISA and USCG Joint Advisory: What “No Breach” Still Reveals

> CISA & USCG’s AA25-212A advisory highlights systemic security gaps. No breach doesn’t mean no risk—resilience requires proactive hardening.

The July 31st [advisory from CISA and the U.S. Coast Guard (AA25-212A)](<https://www.cisa.gov/news-events/cybersecurity-advisories/aa25-212a>) should serve as a wake-up call to many. Not because of what _did_ happen, but because of what _could have happened_.

The advisory detailed a proactive threat hunt conducted at a U.S. critical infrastructure organization. While no active malicious activity was discovered, the assessment revealed significant systemic weaknesses that could have been easily exploited.

Among the issues identified:

  * Insecurely stored credentials
  * Shared local admin accounts across multiple systems
  * Unrestricted remote access for privileged users
  * Insufficient logging and monitoring
  * Weak segmentation between IT and OT environments
  * Misconfigured devices with elevated access



This is a textbook case of what many in the field call **“security theater.”** When policies, tools, or procedures are present on paper or in tooling, but lack real-world enforcement, oversight, or operational discipline.

###  **The Danger of “No Breach” Thinking**

“No evidence of compromise” is not the same as “no risk.”  
Yet too often, the absence of a breach becomes a reason to defer improvement.

Imagine applying this logic to the physical security of a facility:

  * Doors have locks, but keys aren't tracked, or worse, a spare set is left lying around for everyone to use
  * There are security cameras, but no one watches the footage or ensures they are actually working
  * Entry policies exist, but there is no enforcement - the door is propped open or the lock is broken



We’d never call these scenarios safe. So why are they acceptable in digital environments?

###  **Why This Advisory Matters for Cloud and Regulated Environments**

Whether you're operating in AWS GovCloud, pursuing FedRAMP compliance, or managing a hybrid infrastructure with open-source technologies like PostgreSQL, the message is clear:

>  **Security is not a static state. It’s an evolving practice.**

Security must be dynamic, not reactive. Waiting until a threat materializes before reacting is an ineffective and inefficient strategy. Modern and robust security requires iterative and adaptable practices that can anticipate and respond to current and emerging threats.

It’s no longer just a question of whether you've been breached.

It’s about whether you’ve hardened your systems to withstand failure and recover quickly when it happens. More importantly, it's about situational awareness and understanding the risk and consequences of complacency.

###  **What This Means in Practice**

This advisory points to the need for:

  * Continuous auditing of access and configuration
  * Active enforcement of change control
  * Real-world validation of logging and alerting pipelines
  * Operational segmentation between environments
  * Internal accountability, not just compliance paperwork



In an upcoming post, we’ll explore what can be learned from public water system resilience to shape a multibarrier approach to cloud security (i.e., the "Swiss Cheese Model"). Hardening isn’t about reacting to threats. It’s about preparing your systems to resist them at every layer, ensuring they are secure and reliable.

 **Coming up next:** “From Turbidity to Tenancy — What Public Water System Management Taught Me About Hardening the Cloud.”

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-cisa-and-uscg-joint-advisory-what-no-breach-still-reveals/)

---

# Upgrading PostgreSQL and Citus for Enhanced Database Functionality

> Learn how PostgreSQL and Citus were upgraded from 11/8.3 to 15.5/12.1 with improved performance and scalability in this real-world case study.

## Upgrading PostgreSQL and Citus: A Real-World Case Story

When your organization relies on PostgreSQL and Citus, a PostgreSQL upgrade isn’t just about version numbers—it’s about unlocking new features, improving scalability, and optimizing performance. Yet in modern distributed environments, with Docker, Kubernetes, and custom extensions, upgrades can be complex without the right approach.

## The Challenge

Our client needed to move from PostgreSQL 11 to 15.5 and Citus 8.3 to 12.1—an ambitious step that required:

  * Preserving performance across distributed environments
  * Simplifying a custom extension
  * Ensuring compatibility with Kubernetes, Docker, and Ansible
  * Coordinating upgrades across development, testing, and production



This PostgreSQL case study demonstrates how a real-world client faced the challenges of a distributed architecture while still achieving Postgres upgrade best practices.

## The Journey

The upgrade followed a carefully structured plan to ensure success in a containerized environment:

  *  **Development:** Reworked the custom extension, built Docker images, and validated core functionalities.
  *  **Testing:** Simulated production loads, validated ZFS snapshot functionality, and collaborated on flushing out data issues.
  *  **Production:** Executed with pre-approved scripts, live monitoring, and rollback-ready safeguards.



Not every step was smooth, as advisory lock inconsistencies and historical production anomalies meant careful adjustments. Collaboration, thorough testing, and PostgreSQL performance optimization expertise delivered a cleaner, more scalable system.

## The Results

The outcome of this PostgreSQL Citus upgrade included:

  * Enhanced performance with PostgreSQL 15 and Citus 12.1
  * Future-ready scalability for distributed workloads
  * Reduced complexity as custom extensions gave way to native Citus features
  * Improved practices for distributed PostgreSQL performance tuning



This was more than a version change; it was a Postgres upgrade best practice that ensured long-term stability and growth.

## Why This Matters for You

If your organization runs PostgreSQL in distributed or containerized environments, upgrades are not optional—they’re essential for keeping pace with scalability and security needs. With careful planning and the right PostgreSQL consulting services, upgrades don’t have to be disruptive.

 **Download the full white paper below** — _Upgrading PostgreSQL and Citus for Enhanced Database Functionality_ — to explore the detailed case study, processes, and lessons learned that can help you prepare for your upgrade.

 **New to Citus?** Check out our [**Citus tutorials YouTube playlist**](<https://youtube.com/playlist?list=PLivUNqHOPMw4pgam103hujI6VJIv9wZnx&si=9C6nsktGLfSATGmV>) to start building distributed PostgreSQL confidence:

* * *

## Need Help with PostgreSQL?

At Command Prompt, we guide you through the complexity so you can stay focused on delivering value to your business and customers. As the world’s oldest dedicated Postgres services and consulting company, we bring deep expertise in performance optimization, troubleshooting, and open-source database support.

Ready to plan your next PostgreSQL upgrade or tackle a database challenge? **Book a call with our team** and let’s explore the right path forward together.

---
[View this page online](https://www.commandprompt.com/blog/upgrading-postgresql-and-citus-for-enhanced-database-functionality/)

---

# Lessons From The Road: More Intention, Less Autopilot

> How much of our time is spent on autopilot?Most people can agree that our internal autopilot systems enable us to be efficient and effective. It allows us to d…

How much of our time is spent on autopilot?

Most people can agree that our internal autopilot systems enable us to be efficient and effective. It allows us to do things like listen to a client while trying to find the bug they are describing in the source code. Or make dinner while holding a conversation. Or even have Spiderman-like reflexes when a child falls out of a chair across the room. Our autopilot and established habitual patterns can help us achieve things we wouldn’t otherwise.

While autopilot offers many benefits, it also comes with drawbacks. For example: not really listening to someone because context shifting takes an exorbitant amount of energy. When we do not listen because we are either in our own heads or we are doing other things, we can damage the relationship with whomever is present. Or another example: driving and talking on the phone (or *gasp* texting). Whenever we split our attention, we might be more efficient but we are often tuning out to the point where we don’t actually file any memories of what is happening.

Why that matters: A few weeks ago a colleague and I were on the phone waiting for another individual to join us. We started talking about how fast the time goes the older you get. Of course two days later I started seeing articles such as, “Why time slows down as you age.” I skimmed a couple and the common thread was that when we are children everything is new. As we get older, our lives become a constant version of, “rinse and repeat.” We do the same things, day in and day out. We make coffee the same way, we get ready for work the same way, we drive the same routes. In other words, we rely on autopilot as a way of life. With the world’s constant demands, we are almost forced to. How else can we do it all, all the time, and not incur downtime?

The sad truth I am learning is that the more time I spend trying to do it all, the less I remember about what I did. The more I try to help solve a friend’s problem, the more I miss out on being actually there for them. The more I try to add to my resume, the less _living_ I actually do. When autopilot is in the front seat, my present, paying attention pilot is in the back **completely missing out**.

We have the power to slow down time and reduce our “rinsing and repeating.” It may not be as new and exciting as life is for children, but we can still make memories and be more purposeful in our day-to-day. When we choose intention over automatic responses, we increase our autonomy and are able to see the wealth of opportunities that lay before us.

Some questions to help re-instate the intentional pilot and let the autopilot take a back seat:

  * What do you remember about your day? Which things stood out? Which things were clearly habitual and not even thought about?
  * What are your rinse and repeat routines?
  * What kinds of things do you completely lose yourself in and give 100% focus? What makes them so encapsulating?
  * What is happening right now? Not in your head - but around you, outside of you.
  * When was the last time you took a shower and shut off your brain for a few minutes?
  * What are you protecting yourself from that instead should be faced?
  * What are you desensitized to? Or, what no longer matters to you that should?



* * *

 **Explore More Lessons from the Road**

This post is part of an ongoing series by our CEO, Amanda Nystrom, reflecting on the most important lessons carried forward from life on the road. These insights aren't just about living in a school bus or being a digital nomad. They're about rethinking the status quo and uncovering purpose in unexpected places.

Browse the full series here: Lessons from the Road » <https://www.commandprompt.com/blog/tag/lessons-from-the-road/>

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-road-more-intention-less-autopilot/)

---

# Service Monitoring via Hazard Analysis White Paper

> Apply hazard analysis and Critical Control Points (CCPs) to IT monitoring. Improve service reliability, reduce costs, and detect issues before they impact users.

**Overview:**  
This white paper introduces a proactive, hazard-based framework for service monitoring, drawing inspiration from the HACCP (Hazard Analysis and Critical Control Points) model widely used in the food industry. Instead of reactive troubleshooting based on generic metrics, this method centers on identifying and monitoring _critical control points_ across IT systems to manage potential hazards before they escalate into service-impacting incidents.

###  **Key Takeaways**

  *  **Industry Challenge:**  
The [2023 Cloud Native Computing Foundation (CNCF) Survey](<https://www.cncf.io/reports/cncf-annual-survey-2023/>) shows 90%+ container usage in production; top challenges include security (40%), complexity (36%), and monitoring (35%).
  *  **New Monitoring Lens:**  
Traditional frameworks (e.g., [RED](<https://grafana.com/blog/2018/08/02/the-red-method-how-to-instrument-your-services/>), [USE](<https://www.brendangregg.com/usemethod.html>), and [Google’s Four Golden Signals](<https://sre.google/sre-book/monitoring-distributed-systems/#xref_monitoring_golden-signals>)) fall short in complex systems. This paper proposes a hazard-based alternative that offers more context-aware monitoring.
  *  **Hazard Classes Identified:**
    * Capacity & Resource Utilization
    * Undesirable Effects of Change
    * Hardware Failure
    * Security Events
    * External Dependencies
    * Compliance & Internal SLAs
  *  **Guiding Principles for Indicators:**
    * Indicators must tie to real hazards.
    * Alerts should include user impact and response steps.
    * Visualizations must be consistent, scaled, and well-labeled.
  *  **Efficiency-Driven Metrics:**  
Track CPU, memory, and I/O _per unit of work_ to benchmark performance, compare deployments, and detect anomalies early.
  *  **Change Monitoring:**  
Covers both internal (e.g., hardware config, deployments) and external (e.g., SSL certs, upstream SLAs) environments—ensuring no blind spots.
  *  **Outcome:**  
Enables faster root cause analysis, improved resource planning, and early warning systems—resulting in better service reliability and reduced costs.



 **Download the full white paper below** to explore the framework, real-world examples, and how your team can implement hazard-driven observability.

* * *

##  **Need Help?**

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. [Contact us today](<https://commandprompt.com/contact-us/>) for Postgres and open source support.

---
[View this page online](https://www.commandprompt.com/blog/service-monitoring-via-hazard-analysis-white-paper/)

---

# Critical Security Alert: Immediate Action Required for Self-Hosted SharePoint Servers (CVE-2025-53770)

> A critical, newly disclosed, and actively exploited vulnerability, CVE-2025-53770, affects all self-hosted / on-premises Microsoft SharePoint Server versions. …

A critical, newly disclosed, and actively exploited vulnerability, [CVE-2025-53770](<https://nvd.nist.gov/vuln/detail/CVE-2025-53770>), affects all self-hosted / on-premises Microsoft SharePoint Server versions. This critical issue does not impact SharePoint Online (Microsoft 365).

The exploit enables attackers to:

  * Bypass authentication
  * Install persistent backdoors
  * Launch ransomware
  * Steal sensitive data



### Immediate Steps to Take:

  * Patch all on-premises SharePoint servers immediately following [Microsoft guidance](<https://msrc.microsoft.com/blog/2025/07/customer-guidance-for-sharepoint-vulnerability-cve-2025-53770/>)
  * Disconnect unpatched servers from the Internet immediately
  * For versions older than SharePoint 2016:
    * Block external access now
    * Plan and execute an upgrade to a supported, patched version urgently
  * Even servers only accessible internally must be patched due to the ease and severity of the exploitation.



 **Note:** If you suspect an attack has occurred and/or been successful, any suspected compromised machine must be isolated immediately, including shutting it down.

It is also recommended to isolate those instances using zero-trust practices to prevent lateral movement of any malware already present in the system.

This vulnerability is being weaponized in the wild and poses a significant risk to data integrity and network security.

 **CVE Reference:** [CVE-2025-53770](<https://nvd.nist.gov/vuln/detail/CVE-2025-53770>)

Be aware that there may be additional vulnerabilities connected to this incident, including CVE-2025-53771, which is related to path traversal in Microsoft Office SharePoint and is currently awaiting analysis as of this publication date.

We highly recommend following and subscribing to the [CISA Cybersecurity Alerts & Advisories](<https://www.cisa.gov/news-events/cybersecurity-advisories>) for the latest updates.

Additional Sources:

  * [https://www.microsoft.com/en-us/security/blog/2025/07/22/disrupting-active-exploitation-of-on-premises-sharepoint-vulnerabilities/](<https://www.microsoft.com/en-us/security/blog/2025/07/22/disrupting-active-exploitation-of-on-premises-sharepoint-vulnerabilities/ 
   
https://www.cisa.gov/news-events/alerts/2025/07/20/update-microsoft-releases-guidance-exploitation-sharepoint-vulnerabilities
>)
  * [https://www.cisa.gov/news-events/alerts/2025/07/20/update-microsoft-releases-guidance-exploitation-sharepoint-vulnerabilities](<https://www.microsoft.com/en-us/security/blog/2025/07/22/disrupting-active-exploitation-of-on-premises-sharepoint-vulnerabilities/ 
   
https://www.cisa.gov/news-events/alerts/2025/07/20/update-microsoft-releases-guidance-exploitation-sharepoint-vulnerabilities
>)



* * *

## Need Help?

If you need assistance evaluating your systems or applying patches, contact us right away.

Thank you,

Command Prompt Team

---
[View this page online](https://www.commandprompt.com/blog/critical-security-alert-immediate-action-required-for-self-hosted-sharepoint-servers-cve-2025-53770/)

---

# Lessons from the Road: What actually matters

> Amanda Nystrom explores the profound question of what truly matters in life, prompted by the final words of her sister‑in‑law. What legacy do you want when it’s time to say your last words?

What actually matters to you?

The inclusion of the word “actually” is important because typically a lot of things matter to us. Doing a good job at work, spending time with the family, having a nice car, having enough vacation time, making progress on our goals; all of it matters. In the end though: what **actually** matters?

When I initially brainstormed this post, I was coming from a place of emphasizing our values and our key facets of life. Establishing what matters helps us define what is essential, and knowing our values helps us make decisions. A good way to determine what actually matters is this age-old question: At the end of your life, what do you want to have done to feel whole?

And then my sister-in-law died.

She was 43.

While the original point of this post is still valid, it behooves me now to ask: what do you want your last words to be? **What do you want your life composed of so that when it’s time to say your last words, they are spoken without regret?**

My sister-in-law’s last words were, “It is well.”

She then spent a week in a coma fighting for her life and wasn’t able to say anything else.

When I was informed of her last words, I didn’t believe it. I expected, “Tell my family I love them.” To be in that space mentally and emotionally as your body is going through [Tumor Lysis Syndrome](<https://www.ncbi.nlm.nih.gov/books/NBK518985/>) after weeks of debilitating pain and a Stage Four cancer diagnosis is astonishing.

What I took from this was a sign that she had narrowed down what actually mattered. She may have had regrets, but in the end she was so strongly aligned with her values that she went with grace. There was no, “I wish I had done X.” She found her footing in the chaos and embraced it.

 **What would it take for your last words to be, “it is well?”**

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-road-what-actually-matters/)

---

# Part 6: Prevention and Monitoring Strategies

> Avoid PostgreSQL downtime from autovacuum issues. Learn how to prevent failures caused by temp tables and proactively monitor your cluster’s health. Includes diagnostic query and white paper.

_Series Summary: This is the final part of a_ [_multi-part series_](<https://www.commandprompt.com/blog/tag/autovacuum-failure-blog-series/>) _on PostgreSQL autovacuum failures._

⬅️ [Back: Part 5: Temp Tables and XID Wraparound in Single-DB Clusters](<https://www.commandprompt.com/blog/part-5-temp-tables-and-xid-wraparound-in-single-db-clusters/>)

We’ve identified two major pitfalls that can disrupt PostgreSQL’s autovacuum: temp tables in multi-database clusters that halt maintenance activity, and lingering temp tables in single-database environments that risk triggering an emergency shutdown.

In this final installment, we’ll share actionable steps to help you prevent these problems and proactively monitor your cluster’s health.

## Prevention Tips

To keep your PostgreSQL environment resilient:

  *  **Clean up temp tables proactively**
    * Use CREATE TEMP TABLE ... ON COMMIT DROP when appropriate
    * Ensure application logic terminates sessions cleanly
    * Avoid leaving sessions idle with persistent temp tables
  *  **Set conservative thresholds**
    * Use a lower autovacuum_freeze_max_age in test or dev environments
    * Monitor age(relfrozenxid) for critical tables
  *  **Terminate stale sessions**
    * Regularly audit open sessions
    * Consider using connection poolers that recycle idle connections properly  




## Monitoring Recommendations

A robust monitoring strategy can catch early signs of autovacuum failure:

  * Track XID age across all databases, not just the one in active use
  * Alert when temp tables exceed a certain lifetime or size
  * Review pg_stat_user_tables and pg_class for tables approaching wraparound
  * Log and alert on autovacuum cancellations (e.g., "canceling autovacuum task")



At Command Prompt, our monitoring platform tracks these metrics out of the box, helping clients avoid exactly these types of edge cases.  


## Diagnostic Query You Should Bookmark
    
    
    SELECT
        datname,
        age(datfrozenxid) AS xid_age,
        current_setting('autovacuum_freeze_max_age')::int - age(datfrozenxid) AS tx_before_wraparound
    FROM pg_database
    ORDER BY tx_before_wraparound;

This query shows how close each database is to XID wraparound and whether a cluster-wide autovacuum issue might be brewing.

## Conclusion

Thank you for following along through this deep dive into PostgreSQL’s autovacuum mechanics and its hidden edge cases. We hope this series has helped surface some of the nuances behind keeping your cluster healthy and what can happen when overlooked.

If you’ve run into similar issues or have questions about monitoring and maintenance, we’d love to hear from you.

* * *

## Need Help?

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. Contact us today for Postgres and open source support.

---
[View this page online](https://www.commandprompt.com/blog/part-6-prevention-and-monitoring-strategies/)

---

# Lessons from the Road: Gratitude

> I was on the phone with one of my most active clients at Command Prompt when I had to interrupt the call because my dogs somehow opened the bus door and went r…

I was on the phone with one of my most active clients at Command Prompt when I had to interrupt the call because my dogs somehow opened the bus door and went running after horses. The client and Command Prompt have a good relationship so I wasn’t too worried about the fallout. However, what the client said when I returned to the call and explained the interruption was surprising.

## “I think I have been doing life all wrong…”

The additional context for the response is that he found out about how I travel and work for the first time. The fact that I had to chase after French Bulldogs chasing after horses (let that image sink in for a sec) added to the impression.

This moment of vulnerability had a deep effect. Having an alternative work style is far from easy and often has me striving for the stability of a stationary life. But when I heard these words, I was flooded with memories from before I decided to take the risk of working on the road. I felt trapped, with “stressed” being my primary answer to the question, “how are you?” I too felt like I was doing life all wrong.

I deeply appreciated this experience with my client, not only because it demonstrated the trust we have built, but also because it enabled me to lean into gratitude. Without my clients and the Command Prompt team, I wouldn’t be able to travel and work the way I do. Without the blessing of being able to do my job remotely, I definitely wouldn’t live in a skoolie. And I’m sure to some that it makes sense, but I don’t believe we are meant to be stationary most of our lives. I believe that our need for adventure has been suppressed by distractions, including the almighty cell phone and media. Or put it another way: we’re getting our “fix” from devices instead of life. We are, to quote a recently read book, a [dopamine nation](<https://www.annalembke.com/dopamine-nation>).

When I think back on the years I’ve been doing this (since 2018), there have definitely been some hard moments, a lot of tantrums, and a ton of physical pain. I wouldn’t trade the adventures I have had - even the bad ones. They make me a better person; a more grateful person.

If you are in my life: **Thank You**.

If you are not in my life: **Thank you for being in my life now**.

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-road-gratitude/)

---

# Part 5: Temp Tables and XID Wraparound in Single-DB Clusters

> Learn how lingering temp tables in PostgreSQL can trigger shutdowns from XID wraparound, and what steps to take to prevent downtime in your database environment.

_Series Summary: This is Part 5 of a_ [_multi-part series_](<https://www.commandprompt.com/blog/tag/autovacuum-failure-blog-series/>) _on PostgreSQL autovacuum failures._

While the previous posts focused on multi-database clusters, single-database PostgreSQL setups aren’t immune. In this part, we explore a separate gotcha: a long-lived temp table can cause PostgreSQL to panic and shut down as the transaction ID (XID) approaches wraparound.

##  **Gotcha #2: Temp Tables and XID Wraparound**

If a temporary table persists for too long, it will never be vacuumed, because autovacuum can’t touch temp tables. Despite this, temp tables still accumulate transaction IDs. As the XID nears wraparound, PostgreSQL will force a shutdown to protect against data corruption.

This process may clean up the temp tables during restart, but by then, you’re experiencing unexpected downtime.

##  **The Fix**

Preventative hygiene and monitoring:

  * Use DROP TABLE or ON COMMIT DROP to ensure temp tables are removed when no longer needed.
  * Avoid leaving long-lived sessions running indefinitely.
  * Implement monitoring that tracks XID age and temp table usage across your cluster.



##  **Key Takeaways**

  * Always clean up temp tables:
    * DROP TABLE
    * CREATE TEMP TABLE ... ON COMMIT DROP
    * Recycle long-lived sessions
  * Implement a comprehensive monitoring solution to catch these scenarios early.



Even a single lingering temp table can destabilize your cluster, whether you have one database or many. These preventive practices are essential for keeping your PostgreSQL environments stable, especially in production systems where uptime matters.

⬅️ Back: Part 4 – Debugging Limitations in RDS and Cloud Environments

➡️ Next: Part 6 – Autovacuum Failure Prevention and Monitoring Strategies

* * *

##  **Need Help?**

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. [Contact us today.](<https://www.commandprompt.com/contact-us/>)

Can't wait for the full series? Receive a link to download the full series as a white paper by submitting your contact information below.

---
[View this page online](https://www.commandprompt.com/blog/part-5-temp-tables-and-xid-wraparound-in-single-db-clusters/)

---

# Lessons from the Road: Know your footprint

> Discover how life on the road revealed hidden waste habits and how small, mindful changes can make a big impact on your environmental footprint.

What is the weight of your footprint?

What is the cost of your footprint?

One of the most surprising things I experience when I go from a house to a school bus is the sheer amount of waste we as humans produce. From packaging to paper towels to food scraps to everything else I won’t mention here, it’s a _lot_. When I am stationary at home, my trash hides in a 13 gallon bucket under my countertop. My food scraps go in a compost pile. My dirty dish remnants and gray/black water go into the septic system. For the most part, I barely have to deal with my own waste. Even to the extent of getting rid of something like a broken bookshelf or old couch: it goes to the dump to never be seen again.

The problem is: the waste continues, and the [waste grows](<https://www.epa.gov/lmop/basic-information-about-landfill-gas#methane>).

We all know about landfills and the damage we’re doing to sea life, etc. This post isn’t about that, as much as asking you to consider this question:

 **Can you measure the waste that you produce?**

Before living in a bus, I certainly couldn’t. To be honest with you, I am _mortified_ by how much I contribute to landfills and the pollution of the earth. The [never-ending plastics](<https://www.plasticpollutioncoalition.org/blog/2022/5/16/what-really-happens-to-your-plastic-recycling>), even from the grocery store, are mind-boggling.

What can we do about it?

We pay attention, and actively be intentional.

The key here is shutting off the auto-pilot when we’re shopping and bringing things into our home. We must be intentional and focus on the present moment. Like the previous post mentioned, every item we bring in adds weight to our lives. Likewise, _every item we buy comes with the responsibility of dealing with the garbage_ \- even if that’s just the plastic bag that carries the tomatoes. Paying attention allows us to choose what we are responsible for and what we can leave behind.

Some ways to be intentional when shopping:

  * Make an “essentials” list and don’t stray from it.
  * When evaluating an item, consider its packaging. Is there a biodegradable option?
  * Do some research into paying attention and/or overriding the auto pilot. Good keywords for this include: mindfulness, mindful awareness, and Jon Kabat-Zinn.
  * Buy in bulk.
  * Take your eco-friendly friend or family member with you so they can give you judgmental glances when you go for the less earth-safe thing.

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-road-know-your-footprint/)

---

# Part 4: Debugging Limitations in RDS and Cloud Environments

> Part 4 of our PostgreSQL Autovacuum Failure Series explores how session-level temp tables in RDS can silently stall autovacuum—and how we resolved it. Learn wh…

**Part 4: Debugging Limitations in RDS and Cloud Environments**

 _Series Summary: This is Part 4 of a_ [_multi-part series_](<https://www.commandprompt.com/blog/tag/autovacuum-failure-blog-series/>) _on PostgreSQL autovacuum failures._

Even if you understand the root cause, fixing it isn’t always straightforward, especially in managed environments like Amazon RDS. In this post, we show how limited visibility complicates recovery and how we eventually resolved the issue.

## Tracing the Root Cause

After confirming stalled autovacuum, we ran cluster-wide diagnostics. Using the previously shared query, we discovered a temp table with XIDs over 100 million — a clear sign that something was wrong.

But identifying the session that owned it? That was the challenge.

After encountering this issue, we turned to Google and the PostgreSQL mailing list archives.[One relevant message from 2008 in the pgsql-hackers list](<https://www.postgresql.org/message-id/flat/20080210234756.GA7093%40alvh.no-ip.org#6325092e2071c4f5443d88834ecb01f1>) said this behavior is "normal."

Is it technically normal? Yes. Is it ideal for production environments? Definitely not.

Digging further into the PostgreSQL source code and discussions on pgsql-hackers and pgsql-general, we found this behavior is by design:

Autovacuum allocates all available workers to the database with the oldest XID.

This is explicitly noted in the source: [Autovacuum Source Code (line 1188)](<https://github.com/postgres/postgres/blob/170e416034ec0231d9e9238f2577eeb76ca8d181/src/backend/postmaster/autovacuum.c#L1188>)

## A Lightbulb Moment

That’s when the lightbulb went off: this cluster contains multiple databases, so let’s check all of them.  
  
Using the diagnostic query shared earlier, we discovered a lingering temp table with XIDs that were over 100 million transactions old. That was the smoking gun.

## When You’re in Amazon RDS...

The next challenge was identifying which session owned the temp table. This proved far more difficult than expected, primarily because we were working in Amazon RDS for PostgreSQL, which restricts OS-level access. Without shell access, we could not:

  * Inspect the pg_temp directory
  * Match temp file names to backend PIDs
  * Identify long-lived sessions by open files



That meant we had to take an educated guess.

## The Fix

We contacted the client and requested permission to terminate the sessions that were likely holding the temp table open. Once approved, we ran:
    
    
     SELECT pg_terminate_backend(pid);

Lo and behold! Just like that, autovacuum sprang back to life. Victory!

 **The Culprit: A Persistent Temp Table**  
The session holding open the temp tables never cleaned up after itself. It repeatedly executed the following commands within a PL/pgSQL function:
    
    
    CREATE TEMP TABLE IF NOT EXISTS temp_table; 
    TRUNCATE temp_table;

Because the session remained open indefinitely, the temp table was never dropped. In PostgreSQL, temp tables live for the entire duration of a session. If that session never ends, the table never disappears.

## Monitoring Would Have Prevented This

Once we understood why autovacuum wasn’t progressing, it was clear how much time could have been saved if the client had allowed us to implement our custom-built monitoring solution from the start.

Our system continuously scans all databases and tables within a cluster and flags any that are in a critical vacuum state.

We’ve seen this scenario multiple times — clients unknowingly leave sessions open for weeks or months, with temp tables accumulating unmaintained XIDs.

Our platform would have raised an alert such as:  

    
    
    ALERT XXX temp_table has not been vacuumed in a long time.

⬅️ Back: Part 3 – Why Autovacuum Stops - PostgreSQL Internals Explained

➡️ Next: Part 5 – Temp Tables and XID Wraparound in Single-DB Clusters

* * *

## Need Help?

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. [Contact us today.](<https://www.commandprompt.com/contact-us/>)

Can't wait for the full series? Receive a link to download the full series as a white paper by submitting your contact information below.

---
[View this page online](https://www.commandprompt.com/blog/part-4-debugging-limitations-in-rds-and-cloud-environments/)

---

# PgManage 1.3 Release: Powerful New Features and Enhanced Usability

> Explore what's new in PgManage 1.3, including improved dashboards, JSON export, PostgreSQL 17 support, and performance upgrades. Read the full release notes.

We’re excited to announce the release of **PgManage 1.3**, packed with powerful new capabilities, user experience enhancements, and bug fixes. Whether you're working with PostgreSQL, MariaDB, MySQL, SQLite, or Oracle, this Community Edition release delivers improvements to streamline your workflow, improve performance, and enhance visibility across your databases.  


## What’s New in PgManage 1.3

This release brings a mix of much-requested features and UI/UX refinements designed to make your daily database tasks faster and more intuitive.  


## Feature Highlights

  *  **Visual Data Filtering in the Data Editor**  
A new filtering UI now lets you apply conditions to your data with ease—no manual queries required.
  *  **Dashboard Improvements**
    * The new dashboard configuration UI allows for easy widget reordering.
    * A redesigned widget layout presents data in a cleaner, easier-to-read format.
    * Dashboard graphs have been reimplemented for improved clarity and better handling of large datasets.
  *  **MariaDB Support Extended**  
The MySQL dashboard has been expanded to include MariaDB compatibility.
  *  **JSON Export for Query Results**  
You can now export query result sets directly to JSON.
  *  **Query Editor Upgrades**
    * Code folding support is now available for navigating complex queries.
    * You can run EXPLAIN/ANALYZE on a selected portion of a query.
    * Autocomplete now includes column aliases.
  *  **Smarter Backups**  
The backup type will now automatically adjust based on the file extension, and vice versa.
  *  **PostgreSQL Documentation Integration**  
SQL templates now include quick-access links to relevant sections of the PostgreSQL docs.
  *  **Advanced Clipboard Options**  
Query results can be copied as CSV, JSON, or Markdown, ideal for sharing or documentation.
  *  **Improved SQL Preview Features**  
A new “Copy to Editor” option is now available in the DDL tab and generated SQL preview boxes.
  *  **New Cell Data Viewer**  
This modal includes syntax highlighting and handles various data types elegantly.
  *  **PostgreSQL 17 Support**  
PgManage now supports the latest PostgreSQL release, ensuring compatibility with the latest advancements in PostgreSQL.  




## Bug Fixes

  * Cleaned up info.plist entries on Mac builds to avoid inappropriate file associations.
  * Correctly handle mutually exclusive --create and --single-transaction options in Database Restore.
  * Resolved several dark theme visual inconsistencies, including disabled input colors and autocomplete switches.
  * Fixed issues with the PostgreSQL Alter View template and loading of database object tree nodes.
  * Prevented duplicate backup/restore jobs from being started.
  * Ensured only one monitoring dashboard per DB workspace.  




## UI/UX Improvements

  * The console tab now handles resizing more gracefully.
  * Backends tab UI readability has been improved.
  * The Data Editor tab now shows loading and saving indicators.
  * Keyboard navigation is now supported in searchable dropdowns.
  * Toolbar layout in the Server Configuration tab has been cleaned up.
  * Query result messages now display across all supported databases.
  * Enhanced the date-range picker and layout in command history modals.
  * Widget font size and color now update live when theme settings change.
  * Improved data grid rendering performance in both the Data Editor and cells containing large data.
  * Combined "Run" and "Run Selection" into a single button group; Autocommit moved to the dropdown menu.
  * Backup/restore jobs are now sorted by start time (newest first).
  * Improved context menu behavior in the data grid when multiple cells are selected.
  * Long backup/restore paths are now truncated in the middle for better readability.
  * Added a "Discard Changes" warning when closing the Data Editor.  




## Get Involved

Thank you to all our contributors and testers. Your feedback and support were essential to making PgManage 1.3 our best release yet.

Found a bug? Have a feature suggestion? Want to contribute to the project?

We welcome your input and involvement. You can file an issue or submit a pull request on [GitHub](<https://github.com/commandprompt/pgmanage>).

Check out the full [PgManage 1.3 documentation on ReadTheDocs](<https://pgmanage.readthedocs.io/>)  
[See the full change log on GitHub](<https://github.com/commandprompt/pgmanage/releases/tag/1.3>)

* * *

Want to receive blog updates straight to your inbox? Subscribe to the [Command Prompt Substack here](<https://cmdpromptinc.substack.com/>).

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-13-release-powerful-new-features-and-enhanced-usability/)

---

# Part 3: Why Autovacuum Stops — PostgreSQL Internal Mechanics Explained

> Series Summary: This is Part 3 of a multi-part series on PostgreSQL autovacuum failures.In Part 2, we reproduced the autovacuum failure issue — now let’s under…

_Series Summary: This is Part 3 of a_ [_multi-part series_](<https://www.commandprompt.com/blog/tag/autovacuum-failure-blog-series/>) _on PostgreSQL autovacuum failures._

In Part 2, we reproduced the autovacuum failure issue — now let’s understand why it happens. This post dives into PostgreSQL internals, explaining how autovacuum allocates its resources and why certain databases get “stuck” in maintenance limbo.

##  **Why Does This Occur?**

This behavior stems from how the autovacuum daemon allocates its resources. Autovacuum identifies the database with the oldest XID, and prioritizes it by assigning all available background workers to that database. **As a result, no autovacuum activity occurs in other databases, even if they’ve exceeded important thresholds.**

Over time, as XIDs continue to be consumed without proper vacuuming, the affected databases edge closer to XID wraparound and are placed in an unhealthy state. If a database contains large tables that haven’t been vacuumed in a while, a VACUUM FREEZE operation can take days to complete. In urgent cases, a full offline VACUUM may be required, resulting in downtime.

##  **Why Autovacuum Skips Temp Tables**

Temporary tables are scoped to the session that created them, and other processes, including autovacuum, cannot access them. Despite this, temporary tables still follow the same visibility and transaction rules as regular tables, meaning they still contribute to XID consumption and maintenance requirements.

##  **PostgreSQL Won’t Warn You**

PostgreSQL does not issue a warning when autovacuum halts across databases. Instead, it silently logs a vague message like:
    
    
    ERROR: canceling autovacuum task

No table name, no reason, and no obvious fix.

A more helpful log entry might look something like this:
    
    
    ERROR: Cannot VACUUM  pg_temp_XXX.hi_there  manually vacuum the table

Instead, you’re left with an ambiguous error message, scratching your head, and possibly yelling at the screen, wondering “why is vacuum broken?!”

##  **Can Monitoring Tools Catch This?**

Yes, but only if they are specifically configured to monitor XID age across all databases and tables. For example, Command Prompt’s customized monitoring solution includes this capability by default, providing early visibility into autovacuum stalling and potential wraparound risks.

In Part 4, we will discuss debugging limitations and how to trace the root cause.

⬅️ Back: Part 2 – Reproducing and Diagnosing Autovacuum Failures

➡️ Next: Part 4 - Debugging Limitations in RDS and Cloud Environments

* * *

##  **Need Help?**

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. [Contact us today.](<https://www.commandprompt.com/contact-us/>)

Can't wait for the full series? Receive a link to download the full series as a white paper by submitting your contact information below.

---
[View this page online](https://www.commandprompt.com/blog/part-3-why-autovacuum-stops-postgresql-internal-mechanics-explained/)

---

# Lessons from the Road: The weight of consumerism

> How many things do you own? How many things are you responsible for?Every thing we have comes with a cost beyond the purchase price. From maintenance to cleani…

How many things do you own? How many things are you responsible for?

Every _thing_ we have comes with a cost beyond the purchase price. From maintenance to cleaning to relocating to using: we are required to do much more with our things than we usually think about. Let’s consider a lawn mower: it has the original purchase price, the sales tax if applicable, the time to transport, the space it takes up, the time and resources it takes to prep the mower for use, the physical energy that must be expounded to mow the lawn, the cleanup of the mower itself and whatever it leaves behind, then consistent maintenance to keep it from turning into a rust bucket. Sans the original cost, we rinse and repeat this energy, resources, and time consumption throughout many years.

If every item we own carries weight in time and energy, how much weight are we carrying that we don’t need without even realizing it? When we get overloaded by stress and life, how much of that comes from the situation itself or the _accumulation of all of the weight we are carrying across all facets of our lives?_

Take your eyes off the screen for a minute and think about what you are actually responsible for. In work, relationships, financial obligations, debt, home keeping, family. Then go one step further and think about the little things: the lawn mower, the junk drawer, the closet, the shoes, the car payment.

Likely, quite a few things came to mind. That’s a lot of responsibility.

We all have things we need - while a lawn mower comes with a lot of required maintenance, if you have a lawn, a lawn mower is essential. The purpose of this post is about being mindful about what we choose to buy and accumulate. Do we really need that third laptop? Do we need that game we will never finish? That subscription so we can binge watch? That fourth dog? _It’s not about what is needed, it’s about having purpose in our things_ and not accumulating unnecessary items. Accumulation infringes on our ability to rest and recharge. If we weren’t bound by so many things, what could we accomplish?

An excellent resource for learning more about the impact of the weight we carry: [The Minimalists](<https://www.theminimalists.com/>). They have just about every option for you: books, audio books, a social media presence, a [podcast](<https://www.theminimalists.com/podcast/>), videos, and more.

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-road-the-weight-of-consumerism/)

---

# Part 2: Reproducing and Diagnosing Autovacuum Failures

> Series Summary: This is Part 2 of a multi-part series on PostgreSQL autovacuum failures.In Part 1, we introduced the scenario where autovacuum mysteriously hal…

_Series Summary: This is Part 2 of a_ [_multi-part series_](<https://www.commandprompt.com/blog/tag/autovacuum-failure-blog-series/>) _on PostgreSQL autovacuum failures._

In Part 1, we introduced the scenario where autovacuum mysteriously halts in a multi-database PostgreSQL cluster. Now, we’ll reproduce the issue using a lightweight test setup. This walkthrough will help you see the failure in action and understand how quickly your system can degrade.

## How to Reproduce the Problem (and Watch PostgreSQL Go Sideways)

Let’s set up a minimal test environment that demonstrates how this scenario plays out and can quickly put your PostgreSQL instance into an unhealthy state.

 **Step 0:** Set up Postgresql to trigger the emergency vacuum event by using the following commands:
    
    
    psql -d postgresql -c ‘ALTER SYSTEM SET vacuum_freeze_min_age TO 100000;’  
    -- 100,000 is the lowest value freeze age can be set to
    -- Restart PostgreSQL

For example, execute the following commands in two different open psql sessions.  


 **Pro tip:** keep the session open while running the code below.  


 **Step 1:** Create a database to hold the temp tables:
    
    
    CREATE DATABASE temp_tables;
    \c temp_tables;
    CREATE TEMP TABLE  hi_there(id serial);
    INSERT INTO hi_there VALUES (DEFAULT);

 **Step 2:** Create a database that won’t get vacuumed:  

    
    
    CREATE DATABASE  not_vacuumed;
    \c not_vacuumed;
    CREATE TABLE please_vacuum(id integer);

 **Step 3:** Create a procedure to burn up 100,000 transactions:
    
    
    CREATE OR REPLACE PROCEDURE test_vacuum()
    LANGUAGE PLPGSQL
    AS $$
        DECLARE 
        _count integer = 0;
        BEGIN
            LOOP 
                BEGIN
                    INSERT INTO please_vacuum VALUES(default);
                    _count = _count + 1;
                    COMMIT;
                END;
                EXIT WHEN _count > 100000;
            END LOOP;
        END;
    $$
    call test_vacuum();

To perform this in Bash instead of within PostgreSQL, run the following command:
    
    
    for i in $(seq 1 10000); do psql -d not_vacuumed -c 'INSERT INTO please_vacuum VALUES(default);'; done;

 **Step 4:** Confirm that VACUUM has not been initiated. Run the query below to verify that autovacuum has not started, even though vacuum_freeze_min_age has been exceeded:
    
    
    SELECT
           oid::regclass::text AS table,
           age(relfrozenxid) AS xid_age, 
           mxid_age(relminmxid) AS mxid_age, 
           least( 
    (SELECT setting::int
                FROM    pg_settings
                WHERE   name = 'autovacuum_freeze_max_age') - age(relfrozenxid), 
    (SELECT setting::int
                FROM    pg_settings
                WHERE   name = 'autovacuum_multixact_freeze_max_age') - mxid_age(relminmxid)  
    ) AS tx_before_wraparound_vacuum,
    pg_size_pretty(pg_total_relation_size(oid)) AS size,
    pg_stat_get_last_autovacuum_time(oid) AS last_autovacuum
    FROM    pg_class
    WHERE   relfrozenxid != 0
    relkind IN (‘r’,’t’)
    ORDER BY tx_before_wraparound_vacuum;

In Part 3, we’ll go deeper, reviewing how PostgreSQL chooses which database to vacuum and what the logs (don’t) tell you.

⬅️ Back: Part 1 – When Autovacuum Silently Fails Across Databases

➡️ Next: Part 3 – Why Autovacuum Stops — Internal Mechanics Explained

* * *

## Need Help?

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. Contact us today.

Can't wait for the full series? Receive a link to download the full series as a white paper by submitting your contact information below.

---
[View this page online](https://www.commandprompt.com/blog/part-2-reproducing-and-diagnosing-autovacuum-failures/)

---

# Lessons from the Road: Know your values

> Ever wonder why we so often don’t follow through on the goals we set for ourselves? Or why it is so easy to slide back into our old habits?One part is neurolog…

Ever wonder why we so often don’t follow through on the goals we set for ourselves? Or why it is _so easy_ to slide back into our old habits?

One part is neurological: our brain is full of established neural pathways that get larger the longer we reinforce the same behavior.

The other part is not having clarity on our values.

We can have all of the “right” motivation, including a strong infrastructure of smart goals, and even an accountability partner, but if we do not know our values like they are our guiding light in the darkness, then our strong neural pathways will continue to override every decision we make.

The “special sauce” for building new neural pathways is getting into the nitty gritty of our underlying selves. A few ways of doing this:

  * Remember when you were a kid and kept asking your parents “why?” to the point where they often gave up and said, “because I said so?” Take a page from that book and use it now: Ask yourself why, answer, then ask why again. Do this until you learn something about yourself [or have gone crazy].
  * Think about what is most important to you. Then ask: what about it is most important? What value is that?
  * Check out this [values list](<https://brenebrown.com/resources/dare-to-lead-list-of-values/>) from [Brene Brown](<https://brenebrown.com/>) and write down what stands out to you. Then put them into categories: Essential Values and Aspirational Values. Essential Values are core to who you are every day - they are your decision making pillars. Aspirational Values are values that may be important depending on the situation and may not apply everywhere, or may be values you want to add to your Essential Values list.
  * Think of a habit or trait you want to rewire. For example: showing up late to meetings. What is the underlying value from that habit? In this example, it could be flexibility. What is important to you about flexibility that is contributing to showing up late to meetings?
  * Ask yourself: What values are you holding onto that may not accurately reflect who you are now?



Values can ebb and flow through life, and it is important to revisit these types of exercises periodically so we can better understand where our motivation is coming from. When we take action from a values-based position, we are much more likely to succeed in whatever it is we are trying to do.

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-road-know-your-values/)

---

# Part 1: When Autovacuum Silently Fails Across Databases

> This blog series examines PostgreSQL autovacuum failures, focusing on temp tables and multi-database edge cases that cause bloat, slowdowns, or XID wraparound …

_Series Summary: This is Part 1 of a_ [_multi-part series_](<https://www.commandprompt.com/blog/tag/autovacuum-failure-blog-series/>) _on PostgreSQL autovacuum failures._  
  
PostgreSQL is known for its resilience and smart storage mechanisms, but even a mature system has edge cases. This post kicks off a multi-part series exploring a subtle but dangerous gotcha: under specific conditions, autovacuum can stop running entirely in a multi-database cluster, without any clear warning. Let’s look at how this happens and why it matters.

## Understanding PostgreSQL VACUUM Basics

If you’ve worked with PostgreSQL for any length of time, you’re familiar with the VACUUM process – what it does and how essential it is for database health. Let’s quickly review its core responsibilities to set the stage:

  *  **Reclaims storage:** Scans tables to mark obsolete tuple (row) versions created by UPDATE and DELETE commands as reusable space.
  *  **Maintains the Free Space map (FSM):** This map helps PostgreSQL quickly locate pages with enough space for INSERT and UPDATE operations.
    * Learn more in the [PostgreSQL FSM documentation](<https://www.postgresql.org/docs/16/storage-fsm.html>) or review the [backend FSM README](<https://github.com/postgres/postgres/blob/master/src/backend/storage/freespace/README>).
  *  **Prevents transaction ID (XID) wraparound:** Updates the XID in tuple headers to a lower value to ensure visibility rules remain accurate.
  *  **Trims bloated tables:** Whenever possible, VACUUM removes empty data pages at the end of the table heap.



## The Hidden Danger: Autovacuum Stops Working Across Databases

Let’s talk about the "gotcha."

PostgreSQL's autovacuum launcher operates at the cluster level, spawning autovacuum workers that target one database at a time. If a database has an open session with temporary tables that aren't cleaned up, especially if those tables live long enough to prevent XID advancement. It can block the entire autovacuum process for all other databases in the cluster.

Yes, really. PostgreSQL will stop processing autovacuum tasks for other databases—even when the emergency vacuum thresholds (e.g., for XID wraparound) are breached.

This behavior emerges under these specific conditions:

  * You’re running multiple databases in a single PostgreSQL cluster.
  * One or more of those databases use session-specific temporary tables.
  * A session creates a temp table and leaves it open and uncommitted for a long time (often due to application logic or connection pooling issues).



When that happens, the autovacuum launcher prioritizes the database with the open temp table, often getting stuck trying to vacuum that database repeatedly, while neglecting all others. This silent failure can allow bloat to accumulate or XID limits to creep dangerously close to shutdown thresholds.

In Part 2, we’ll walk through a test scenario that reproduces this failure mode step-by-step. You’ll see how PostgreSQL can quickly enter an unhealthy state, even when autovacuum should be working.

➡️ Next: [**Part 2: Reproducing and Diagnosing Autovacuum Failures**](<https://www.commandprompt.com/blog/part-2-reproducing-and-diagnosing-autovacuum-failures/>)

* * *

## Need Help?

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. [Contact us today](<https://www.commandprompt.com/contact-us/>).

 _Can't wait for the full series? Receive a link to download the full series as a white paper by submitting your contact information below._

---
[View this page online](https://www.commandprompt.com/blog/when-autovacuum-silently-fails-across-databases/)

---

# Lessons from the Road: What is Essential

> How often do you take a moment to ask yourself: what is essential in my life? Today? Now? What do I need?Knowing what is essential enables us to accurately pri…

How often do you take a moment to ask yourself: what is essential in my life? Today? Now? What do I need?

Knowing what is essential enables us to accurately prioritize. Whether from [Stephen Covey’s Time Management Matrix](<https://intranet-media.rca.ac.uk/documents/stephen-covey-the-time-management-matrix.pdf>) in the [Seven Habits of Highly Effective People](<https://www.amazon.com/Habits-Highly-Effective-People-Powerful/dp/0743269519>), or any part of the book [Essentialism](<https://gregmckeown.com/books/essentialism/>) by Greg McKeown, knowing how to prioritize is critical. When we do, we avoid burnout, unhealthy stress, overcommitting, overworking, and a plethora of other things. But when we live to work and we are constantly trying to fit more into our day, somehow the crucial piece of prioritization goes out the window. Our survival mind kicks in and instead of thinking rationally about the best tool for the job, we start running in a zigzag pattern trying to outrun an alligator. The problem is that it’s not an alligator: it’s a pissed off bison and our zigzags just give them the advantage.

Whether we are running a company or raising a child, coming back to what’s essential allows us to actually be who we are. We must ask ourselves: Is this essential to who I am and what I am trying to achieve? I was shocked when I started asking this question because I realized how often other people’s ideals and dreams were dictating my decisions. As [Mark Manson](<https://markmanson.net/>) and others emphasize in their work: If you do not choose your own priorities, **others will**.

So what is essential to _you_?

Questions for consideration:

  * What are the important things you have been avoiding because they are uncomfortable? Are they essential?
  * What have you been chasing that no longer serves who you are today?
  * Does this <whatever it is> contribute to the person you are trying to become?
  * If your living space was a quarter of the size it currently is, what would you keep? What is important about those things?
  * What does your body need nutritionally, physically, etc., that you have been ignoring?
  * What is essential for you to be healthy?
  * What is one action step you can take today to make progress in an essential area of your life?

---
[View this page online](https://www.commandprompt.com/blog/lessons-from-the-road-what-is-essential/)

---

# Alternative Work Style: Lessons From the Road

> For the last four months I have been working in the ‘cozy’ space of a 23’ school bus. Managing a business under the best of circumstances is stressful. Doing i…

For the last four months I have been working in the ‘cozy’ space of a 23’ school bus. Managing a business under the best of circumstances is stressful. Doing it on the road feels near impossible some days. The relocating, the dance of not being in the other’s way, and taking meetings without a proper setup can be frustrating. Not to mention the weather, which over the last four months has made me deeply appreciate the simplicity of the Pacific Northwest. ( _Tornadoes = do not recommend.)_

So why do this? **Why such an alternative work style?**

While we all have our unique traits, I believe the “why behind the why” is something much more fundamentally relatable than it appears. **Freedom.**

When I have “all the monitors” at home, a closed office, and a workout schedule that is adhered to like clockwork, my life exists to work. I’d like to think I’m working to live but the more I am doing the exact same thing every day, the more I use work as my escape from the melancholy of sameness.

When adaptation and flexibility is my normal, I am full of gratitude for the moments of calm and uneventfulness. My boundaries are better, my life balance is better, and somehow I am better at getting all of the essential work tasks done.

The reward for every day being like the last is comfort and convenience. I can order takeout, shop on Amazon, and be sitting in front of the TV minutes after work is done for the day. The reward for no day being like the last is: better prioritization, genuine appreciation, and having new experiences. While having a different work style than what the American Dream Expectation sets us up for isn’t feasible for some or even desired for others, I believe just the act of asking ourselves this question adds value and awareness to our lives:

 **If I was free from the fear of being uncomfortable, what would I be able to achieve?**

Over the next few weeks I will be diving into the most important things I carry with me from the road and posing questions on how others can explore the topics within their own lives. While these lessons aren’t specific to living in a school bus or being a nomad, my goal is to shed light on how alternatives to the status quo may be where our real passion and purpose lies.

Hope you’ll stick around and thanks for reading.

-Amanda

---
[View this page online](https://www.commandprompt.com/blog/alternative-work-style-lessons-from-the-road/)

---

# Of Unicorns and Donkeys

> Classic and untrue. It isn’t the DBAs that are the issue. It is the developers and their ego which is driven by the unrealistic expectations of the C-suite tha…

### **An umbrage of influencer titles**

This article is a, “get off my lawn, grumpy old man” article about PostgreSQL but more importantly it is a reminder to another generation to get some perspective. [**Derrick Wippler**](<https://www.linkedin.com/in/thrawn01/>) recently wrote an article that with a little more research and a little less whiz bang influencer titles would have been a great expose on limitations of a technology and how it makes sense to evaluate your solutions appropriately. Instead, our resident “Efficiency Czar, Evangelist of Cost-Effective Scaling, Professional Value Stream Detective, and Sustainability Champion” goes on a [**rant about how bad Postgresql**](<https://wippler.dev/posts/postgresql-is-terrible>) (the software) is. It is articles like this that limit the ability to take writers about PostgreSQL seriously. The article is the “vaccines don't work” and the “Chemtrail conspiracy” of database writing. Database people like correctness and we don’t actually buy into the idea that the world is flat so I am going to address the article directly. 

The issue with Derrick’s article is that it boils down to I don’t want to learn how to manage a database. I want it to be magic fairy dust from the sky daddy that hands me everything without having to work for it. For example:

>  ** _“that is designed for consistent 24 hour operation throughout write saturation events”_**

If you are having write saturation events with modern PostgreSQL, it is likely your configuration that is the problem. 

> **_“that has replication designed to be backward compatible with other versions in case of a node failure during upgrades”_**

While it is true that binary replication is not compatible with other versions, we also have Logical Replication (and have for almost a decade. Not only is that compatible with other versions, it is compatible with other platforms such as S3 or MySQL through logical decoding.

>  ** _“that doesn’t allow users to naively create schemas that will silently fail 4 years into operation because they used auto incrementing primary keys”_**

This one comment is the overexposure to the elements comment of the entire article. It says while jumping up and down on a couch Tom Cruise style that, “WHY CAN’T I JUST USE THIS WITHOUT KNOWING HOW”. Don’t get me wrong, I get it. It is an obnoxious thing to have happen and I often prototype without reading docs and understanding what I am actually doing. The difference is, I don’t blame the software when I realize it was my own ignorance that caused the problem in the first place.

>  ** _“doesn’t require a full time DBA on staff to ensure performant operation and uptime, and that allows me to use the resources at my disposal efficiently and keep my operating costs low.”_**

Classic and untrue. It isn’t the DBAs that are the issue. It is the developers and their ego which is driven by the unrealistic expectations of the C-suite that is driven by the ridiculous assertions of the investors that drives this problem. DBAs may be an acquired taste but we are the ones that are constantly cleaning up after the developers who could never learn more than the ORM and think it is better to abstract over a framework to the point of job security through obscurity.

>  ** _“Why is PostgreSQL Terrible?”_**

Derrick then goes on to list a series of public mishaps about PostgreSQL to attribute some level of legitimacy to his thoughts. Unfortunately, every case study he lists is literally, “I don’t know how to manage PostgreSQL” and “The developers actually broke it”.

There are other numerous errors in the article (no, PostgreSQL wasn’t released in 89) but I want to give credit where it is due. Derrick is absolutely correct on a few items:

  * There is literally zero technical reason to not have in place upgrades. (Obviously restart required)
  * Autovacuum deficiencies: There is absolutely a limitation to Autovacuum that has not yet been addressed and if you are running a system that hits this limit, it probably makes sense to migrate.



Does this mean that PostgreSQL solves every problem? Absolutely not. If it did, it wouldn’t be forked into 50 different products solving different problems. There is a reason that Aurora, AlloyDB and Yugabyte exist. They solve a problem PostgreSQL doesn’t while providing a PostgreSQL interface. PostgreSQL is a donkey: smart, stubborn, works hard and will be the last out of the field. It isn’t a Unicorn, let’s leave the fairy dust to Harry potter.

If it isn’t obvious, this article is meant to be enlightening and a fun answer to Derrick’s rant. I don’t know Derrick. I am sure he is a fantastic human being. Hey Derrick, [**why don’t you join me on my podcast?**](<https://open.spotify.com/show/5xKd2hhlJRLoWtDOR8pik0>) We could have a blast of an argument about, pick a topic.

---
[View this page online](https://www.commandprompt.com/blog/of-unicorns-and-donkeys/)

---

# pg_dump Gets a Speed Boost in PostgreSQL 18

> An interesting micro optimization for pg_dump is coming in PostgreSQL 18.

PostgreSQL 18, which is scheduled to be released in late 2025, brings several under-the-hood improvements. One particularly impactful change is a performance enhancement to pg_dump, the PostgreSQL utility used to back up the database. In version 18, pg_dump will now retrieve attributes in batches rather than one at a time.

This micro-optimization may not catch headlines, but for those managing complex databases with tens of thousands of objects, the difference is noticeable and measurable.

## Benchmarking the Improvement

To test this change, I ran a quick comparison on my local machine (i.e., my laptop) with a database containing **20,000 schema objects**. I used the -s flag to dump the schema only, avoiding data content for clarity. Here are the results:
    
    
    v17: pg_dump -s, 0.75 seconds
    
    
    v18: pg-dump -s, 0.54 seconds

That's a 28% reduction in time just from this internal optimization. This result was repeatable across multiple runs.

While a difference of 0.21 seconds might seem small in isolation, the real impact emerges at scale. In production environments, database schemas can include hundreds of thousands of tables, views, functions, and other objects. When multiple backups or schema comparisons are running in parallel under load, even marginal gains in pg_dump efficiency can contribute to better throughput and system responsiveness.

## Why This Matters

For DevOps teams, DBAs, and developers who rely on pg_dump for CI/CD pipelines, nightly backups, or version-controlled schema exports, faster execution means:

  * Shorter downtime or maintenance windows
  * Faster build/test cycles in automated environments
  * Improved responsiveness in administrative tools that depend on pg_dump internally



It’s also worth noting that this improvement enhances usability in multi-tenant systems or complex microservice architectures where database sprawl is common. The more objects you have, the greater the benefit.

## Conclusion

PostgreSQL’s development team of committers and contributors continues to make thoughtful, impactful changes — even to core utilities that many of us take for granted. This small change to how pg_dump collects metadata demonstrates that performance tuning doesn’t always require sweeping architectural shifts. Sometimes, just batching the right operations can make all the difference.

If you’re already testing PostgreSQL 18 in your environment, let us know what kind of performance improvements you’re seeing with this and other new features.

## Don't Sleep on Upgrades

This is just one example of why **staying current with PostgreSQL releases is critical** , even when it feels like a release only includes minor version bumps or under-the-hood changes. Performance gains like the pg_dump optimization in version 18 may seem small, but they add up, especially at scale.

More importantly, **upgrading ensures you benefit from critical security patches and stability fixes** that may not be as visible as new features but are essential for long-term resilience. As highlighted in this article regarding a critical minor release addressing a pg_dump issue, older PostgreSQL versions can leave your systems exposed to vulnerabilities. You also miss out on years of performance tuning and bug fixes.

Whether you're a small shop or managing enterprise-scale deployments, **routine version upgrades should be part of your PostgreSQL lifecycle strategy** — not just to chase new features, but to ensure stability, security, and efficiency over time.

Don't wait until it's too late— [contact us today](<https://www.commandprompt.com/contact-us/>) to discuss how we can help you upgrade your PostgreSQL version and secure your database infrastructure for the future.

---
[View this page online](https://www.commandprompt.com/blog/coming-in-18-pg_dump-micro-optimization/)

---

# Driving Excellence

> We have seen a shift from the pandemic era work from home mandates to a new back to normal mandate of return to the office. This has caused a lot of frustratio…

We have seen a shift from the pandemic era work from home mandates to a new back to normal mandate of return to the office. This has caused a lot of frustration from workers. Much of the frustration is valid. Workers feel as if they can do their job more effectively if they work from home and that it provides better flexibility for managing non-work related responsibilities. There have been studies that back this idea but they tend to have mixed results when comparing the overall data. 

## The corporate culture

Many of the companies mandating return to office cite productivity, lack of focus, a need for tighter collaboration and more creativity. These are valid reasons and through experience we know that it is much harder to encourage those things through remote teams. Anything from communication barriers that are created from text based collaboration, to time zone differences for meetings, to a lack of in person body language to make interpretation easier - they all provide unique challenges for fully remote teams. It is also difficult to build empathy, loyalty, and accountability.There is just something about not having to face a person in real life that allows us to hand off responsibility.

## There is a simpler reason for the mandate

It will encourage the pursuit of excellence and some will say, profit. It takes a special kind of person that can be truly productive working from home. I have worked at home for well over 20 years and even now I get distracted. Get up to get some coffee, notice I need to water a plant, my dog is looking at me like I haven’t played with him in a thousand years, oh I need to pull out meat or dinner, wait what was I supposed to be doing? That’s right, grab a coffee and finish writing this article. That is all time that is lost and time in this context is two things: the ability to produce profit and/or something of excellence. When you work from an office, there is less opportunity for distraction from work. 

## Do U.S. people pursue excellence?

Yes, but not all and not the majority. This was the cusp of Ramaswamy’s quote, “That “American culture has venerated mediocrity over excellence for way too long.” Excellence is something that is achieved over time. It is true that you can build or create something of excellence in 40 hours a week and it is also true that it takes 5x as long as someone who will push 60 or 80 hours a week. If you consider the most profound scientists and innovators, they are not working 32 or 40 hours a week. They are living the project that they are researching, creating, and building.

## Culture has a lot to do with it

Math is the cornerstone of every highly coveted job in the nation. You cannot have excellence in any of the top fields without an aptitude or hard earned skill in math. With this consideration, we would be negligent if we didn’t note that Asians on average score 11 percent higher than Whites in math. [1] Why? Simply put, Asians value academics more than Whites [2]. There is also evidence that the way the U.S. has changed education leads to underperforming results in math [3]. I also believe we have over the last 3-4 generations moved toward a soft lifestyle. People just don’t want to have to work hard and the lack of desire to work hard was further exacerbated by the government policies during the pandemic. 

## When I was a kid

I am going to be 52 this year. I am squarely in Gen X. The stereotypes of Gen X kids riding their bikes in the streets, never seen or heard from from sun up to the street lights came on, drinking from hoses and seeing who could hold on the longest on the merry-go-round are all true. We had firecrackers, were allowed to bring (unloaded) rifles to school (in California even), have a pocket knife, climb trees, walk home alone, take a bus downtown, explore abandoned buildings and play football on pavement. Now people are arrested for allowing their children to walk home from school.[4]

As a child if I wanted something, I had to work for it. Before I hit my teens, I started a lawn mowing business. I didn’t have a lawnmower. I had to borrow one and the first payments I received all went to buying my own law mower. When I returned the borrowed mower, I was required to return it in better condition than when I received it. That was the beginning of my long road to trying to achieve excellence. I am still trying today.

## Where is this all going

We need to require and support education. We need diversity of thought, and an understanding that while we all are all equal the moment of our first breath, equality of outcomes is a descent into mediocrity. We must celebrate and nurture the gifts we are given. We must appreciate and be grateful for the privileges we have. We must hone our skills and cultivate our talents. We must care for our people. Lastly, we must focus on the essentials.[5]

If we want America to continue to be a leader in the world beyond what we can consume, we have to have the culture to support it. We need to accept that a C is not good enough unless it is your best effort and that we should all be striving for the A. That doesn’t mean we all get there. It means we are all working for it. Otherwise, what is the point?

  1. <https://nces.ed.gov/programs/raceindicators/indicator_rcb.asp#:~:text=Asian%20students%20scored%2011%20points,the%20corresponding%20gap%20in%202005.>
  2. <https://www.pnas.org/doi/10.1073/pnas.1406402111>
  3. https://www.asianscientist.com/2016/05/academia/asian-students-good-maths-science/
  4. <https://abcnews.go.com/US/georgia-moms-arrest-puts-free-range-parenting-back/story?id=116004039>
  5. <https://en.wikipedia.org/wiki/Essentialism>
  6. https://youtu.be/ikN3hsWBAyc?si=RcGMWmYPVaQn2Ngz

---
[View this page online](https://www.commandprompt.com/blog/driving-excellence/)

---

# The Freedom to Choose: Why Vendor-Neutral Consulting Matters

> BackgroundOn a recent call, a potential client shared their frustrations with the high costs and limitations of their managed services cloud platform. While re…

## **Background**

On a recent call, a potential client shared their frustrations with the high costs and limitations of their managed services cloud platform. While reaching out to potential support providers, they often encountered companies that only supported PostgreSQL's community edition or pushed their closed-source editions. This experience highlighted the need for a consulting partner who takes a vendor-neutral approach.

 **Command Prompt prides itself on integrity, discipline, and excellence.** We’re straight shooters who weigh the pros and cons of every available solution, and we do so with the needs of your enterprise at the forefront of our minds. With almost three decades of real-world experience supporting clients across the cloud landscape, we understand the nuances and pitfalls that go far beyond what cloud providers’ marketing and technical documentation will tell you.

Organizations face an overwhelming array of choices regarding cloud providers, databases, platforms, and support providers. The wrong decision can result in unnecessary costs, technical roadblocks, inflexibility down the line, or direct negative business impact. A vendor-neutral consulting firm, such as Command Prompt, is committed to finding the best solution for your unique needs, not tied to specific vendors or platforms.

##  **Understanding Your Needs, Not Selling You a Product**

 **The key advantage of working with a vendor-neutral consulting firm is that we don’t aim to sell you any particular product or service.** We provide you with extensive experience and help you make the best decision for your enterprise. Unlike resellers, whose primary goal is to move units of a specific vendor’s offerings, our goal is to be a trusted partner in your success.

By remaining vendor-neutral, we are free to explore the full spectrum of options available to you. This means assessing the requirements, from security, performance, and scalability to budget constraints and compliance needs. We will provide a solution that aligns seamlessly. Whether you need an open-source database solution, a managed service, or a hybrid approach, we’re here to make it happen.

Our _only_ goal is to support your organization with the tools that best align with your infrastructure, not to sell a specific product dictated by an outside partner.

##  **Expertise Across Cloud Providers**

 **The cloud landscape is vast, and every cloud platform provider has its nuances and gotchas.** Navigating these complexities can be daunting without expert guidance. Our team has deep expertise across the leading cloud providers — AWS, Azure, Google Cloud Platform (GCP) – and beyond, including legacy providers such as Heroku.

Whether you’re considering open source PostgreSQL, hybrid, or on-prem, we understand the strengths and limitations of each platform and environment.

This approach allows us to guide you toward the best fit, whether it’s a managed service or a self-hosted solution. By understanding the intricacies of each provider, we identify and weigh the pros and cons to help you avoid pitfalls and optimize for long-term success.

##  **Flexible PostgreSQL Solutions**

 **PostgreSQL is the most powerful and versatile database available, with options ranging from the always-free-to-use community edition to closed-source and cloud-hosted variations.** As a vendor-neutral firm, we’re not here to push you toward a closed-source edition – especially if that’s not what you need.

PostgreSQL is a cornerstone for organizations of all sizes, including Cloud 100 and Fortune 500 companies. We firmly advocate for open source PostgreSQL, recognizing its immense popularity and robust feature set.

At the same time, we understand that certain business requirements or operational constraints may necessitate managed solutions like AWS RDS or Azure Database for PostgreSQL. Our goal is to support all PostgreSQL-related technologies while remaining flexible to meet your needs. Our approach is to ensure that your chosen database solution aligns seamlessly with your operational and business objectives.

##  **Tailored Solutions for Long-term Success**

 **When you work with Command Prompt, you gain a partner who is invested in your success, not in hitting a sales quota.** This means we’re focused on:

  *  **Integrity** : Providing honest recommendations without vendor bias or hidden agendas.
  *  **Discipline** : Knowing when to customize solutions, and balancing your current needs with scalability for future growth.
  *  **Excellence** : Delivering only the solutions that truly work for your company, rather than prioritizing sales margins.



Our goal is to empower your team with the best tools, practices, and strategies to succeed in the long run.

##  **Partnering for Success**

 **The technology decisions you make today will shape your organization’s success tomorrow.** By choosing Command Prompt, you gain a reliable partner who’s focused on aligning solutions with your goals. Whether it’s navigating cloud complexities, implementing PostgreSQL, or designing a resilient infrastructure, we’re here to ensure you succeed on your terms.

Let’s work together to build a solution that’s right for today, and ready for tomorrow. Contact us today.

---
[View this page online](https://www.commandprompt.com/blog/the-freedom-to-choose-why-vendor-neutral-consulting-matters/)

---

# Navigating Compliance in Regulated Industries

> Command Prompt: Your U.S.-Based Partner for Navigating Compliance in Regulated Industries

In highly regulated industries ("RIS") such as healthtech, fintech, and edtech, compliance isn’t just the law — it’s the foundation of trust, safety, and operational success. Organizations must navigate complex federal regulations to protect sensitive data, ensure consumer confidence, and avoid costly penalties. Meeting these challenges requires not only deep industry expertise but also a partner who understands the specific demands of compliance.

Businesses in RIS face numerous challenges – from ensuring compliance with federal regulations to adapting to rapidly changing market demands. That’s where Command Prompt excels, offering a unique advantage that sets us apart from competitors: a majority-U.S.-based team that deeply understands the nuanced requirements of these industries.

###  **Why U.S.-Based Technology Support Matters in Regulated Industries**

Compliance is the law. RIS requires stringent oversight of operations, especially around data security, and privacy. Many regulations, including the [Health Insurance Portability and Accountability Act of 1996 (HIPAA)](<https://aspe.hhs.gov/reports/health-insurance-portability-accountability-act-1996>) for healthtech, [U.S. Securities and Exchange Commission (SEC) compliance](<https://www.sec.gov/compliance>) for fintech, and [Family Educational Rights and Privacy Act (FERPA)](<https://www.ecfr.gov/current/title-34/subtitle-A/part-99?toc=1>) for edtech, mandate or strongly encourage U.S.-based support for certain processes.

By leveraging our U.S.-based expertise, Command Prompt ensures:

  1.  **Regulatory Compliance:** Our team’s familiarity with domestic regulations guarantees that our clients’ operations remain compliant, minimizing the risks of penalties or data breaches.
  2.  **Proximity and Accessibility:** Operating across the same time zones as our clients enables real-time communication and faster issue resolution, a critical factor in high-stakes environments.
  3.  **Cultural and Operational Alignment:** Our team understands the intricacies of U.S. market dynamics and workplace culture. We also recognize the thought processes that influence consumer attitudes, particularly their approach to convenience and handling personal information. We deliver solutions tailored to your specific needs.



###  **Our Expertise Across Healthtech, Fintech, and Edtech**

At Command Prompt, we specialize in tackling the challenges unique to regulated industries:

####  **Healthtech:**

Compliance with the [Health Information Technology for Economic and Clinical Health (HITECH) Act](<https://www.hhs.gov/hipaa/for-professionals/special-topics/hitech-act-enforcement-interim-final-rule/index.html>) as well as HIPAA and other federal guidelines is paramount. Our U.S.-based team works closely with our clients to develop and implement secure, compliant solutions for patient data management, telehealth platforms, medical coding, and more. With Command Prompt, you can trust that your sensitive information is in capable, regulation-conscious hands.

####  **Fintech:**

Innovation with rigorous adherence to SEC, [FINRA](<https://www.finra.org/>), and other regulatory frameworks is critical. Whether it’s ensuring secure payment processing, building compliant investment platforms, or navigating the complexities of financial regulations for securities, Command Prompt’s technical team brings unmatched expertise to help fintech clients thrive in a competitive and tightly controlled landscape.

####  **Edtech:**

As the demand for online education grows, so does the need for compliance with the [Children's Online Privacy Protection Rule (COPPA)](<https://www.ecfr.gov/current/title-16/chapter-I/subchapter-C/part-312>), FERPA, and other education-related regulations. Our U.S.-based team assists companies in creating secure learning management systems, safeguarding student data, and scaling their operations while adhering to federal standards.

###  **The Command Prompt Difference**

While many consulting firms outsource key operations to offshore teams, Command Prompt practices integrity, discipline, and excellence in maintaining a majority U.S.-based team. This commitment isn’t just about meeting regulatory requirements; it’s about delivering unparalleled quality and peace of mind to our clients.

  1.  **Tailored Solutions:** One size does not fit all. Our team invests the time to understand your organization’s unique challenges and delivers customized strategies that align with your goals and regulatory obligations.
  2.  **Proven Track Record:** With a history spanning almost three decades of successful partnerships across healthtech, fintech, and edtech, Command Prompt has earned a reputation for reliability, expertise, and innovation.
  3.  **Future-Focused:** In addition to addressing your current needs, our team stays ahead of regulatory and market trends, looking further down the road to equip your organization for long-term success.  




* * *

###  **Partner with Command Prompt Today**

Choosing a consulting partner is a critical decision, especially for organizations in regulated industries. By partnering with Command Prompt, you’re not only gaining access to top-tier expertise but also ensuring that your operations align with U.S. regulations and best practices. Let us help you navigate the complexities of your industry and achieve your business objectives with confidence.

Contact us today to learn how Command Prompt can help your organization excel in healthtech, fintech, edtech, and beyond.

---
[View this page online](https://www.commandprompt.com/blog/navigating-compliance-in-regulated-industries/)

---

# Support California Wildfire Relief Efforts

> Supporting Our Community: Help California Wildfire Relief Efforts

As we witness the destruction caused by the California wildfires, we’re reminded of the importance of coming together to support those in need. If you are looking for ways to help, here are a few trusted organizations assisting:

  1. [California Fire Foundation](<http://calfund.org/wildfire-relief-fund>) Wildfire & Disaster Relief Fund - This fund supports immediate relief efforts, as well as long-term recovery and rebuilding initiatives for wildfire-affected communities. Learn more and donate [here](<https://www.cafirefoundation.org/what-we-do/for-communities/disaster-relief>).
  2. [World Central Kitchen](<https://wck.org/>) \- This organization is providing meals to displaced families and emergency workers on the frontlines of the fires. You can support their efforts at <https://donate.wck.org/give/654000/>
  3. [Direct Relief](<http://directrelief.org/>) \- This organization is delivering medical supplies and providing health support to communities affected by the wildfires. Visit directrelief.org to contribute.
  4. [GoFundMe Wildfire Relief Fund 2025](<https://www.gofundme.com/f/wildfire-relief-fund-2025>) \- This platform has created a centralized hub of verified fundraising pages on its site. In addition, they have established a fundraiser to send critical cash grants directly to people who need help recovering from the impact of a wildfire.



 **Every donation, big or small, makes a difference in helping communities recover and rebuild.** If you’re unable to give financially, consider volunteering with local organizations or sharing these resources to spread awareness.

Disclaimer: In times of crisis, many people are eager to help, but unfortunately scams often arise that prey on our goodwill. Before donating to a wildfire relief effort, please take a moment to ensure the organization is legitimate, the payment process is secure, and that your contribution will have the intended impact.

Stay safe, and let’s continue to support one another.

Sincerely,

The Command Prompt Team

---
[View this page online](https://www.commandprompt.com/blog/support-california-wildfire-relief-efforts/)

---

# Part 2: The Essential Role of Rollback Plans

> In Part 1 of this series, we discussed the importance of robust change control policies in managing system modifications and minimizing disruptions. But even t…

In Part 1 of this series, we discussed the importance of robust change control policies in managing system modifications and minimizing disruptions. But even the best-planned changes can sometimes go awry. That’s where rollback plans come in as a vital safety net. In Part 2, we’ll focus on the essential role of rollback plans, examining how they minimize downtime, maintain data integrity, and build confidence in your team’s ability to recover quickly and effectively when unexpected challenges arise.

Even with the most meticulous planning and testing, not every change will go as expected. In these cases, a rollback plan becomes invaluable. A rollback plan is a predefined strategy for reverting a system to its previous state if a change does not produce the desired outcome or causes unforeseen issues.

###  **Part 2: The Essential Role of Rollback Plans**

####  **Why Rollback Plans Matter**

  1.  **Minimize Downtime:** Rollback plans allow for a quick return to a known state, minimizing downtime and its associated costs. For mission-critical systems, even short periods of unavailability can have severe repercussions.
  2.  **Maintain Data Integrity:** In environments where data integrity is paramount, a rollback plan ensures that changes do not compromise the accuracy or consistency of data. If a change introduces errors or data corruption, the rollback plan enables the restoration of the previous, stable state.
  3.  **Practice Risk Management:** A robust rollback plan mitigates the risk associated with changes. Knowing that a fallback option is available provides confidence to the team and reduces anxiety about making necessary updates or improvements.
  4.  **Maintain Customer Trust:** For businesses that rely on technology to deliver services to customers, maintaining uptime and data accuracy is crucial. A failed change that leads to prolonged downtime or data issues can erode customer trust. A rollback plan helps preserve that trust by ensuring quick recovery from any problems.



####  **Best Practices for Implementing Rollback Plans**

  1.  **Define Decision Criteria:** Specify who is authorized to make the rollback decision and under what circumstances it should be triggered.
  2.  **Create Playbooks:** Once you streamline your processes and automation, create a playbook for quick deployment. Python-based Ansible is highly recommended as it offers a repeatable, reusable, simple configuration management and multi-machine deployment system, and is well suited to deploying complex applications. Use the playbook to push out new configurations or confirm the configuration of remote systems.
  3.  **Version Control:** Utilize version control systems for configuration files and scripts. This practice allows for easy reversion to previous configurations if needed, and it provides a clear history of changes.
  4.  **Backup, Restore, and Test:** Regularly backup both system configurations and databases. Test backups frequently to ensure they can be restored quickly and accurately if needed. As Greg Dostatni notes “The only way to check is to restore it. Some places automatically rebuild test environment from a backup of production every week - using their backups as the source.”
  5.  **Post-Change Monitoring:** After applying a change, closely monitor system performance and logs for any signs of issues. Early detection allows for faster response if a rollback is needed.
  6.  **Continuous Improvement:** After every change, whether successful or not, conduct a post-implementation review. Analyze what went well, what didn’t, and how the process can be improved. This continuous feedback loop helps refine both change control and rollback processes.
  7.  **Automate With Caution:** Use automation tools to manage and apply changes consistently across environments. Automation reduces human error but can magnify problems if not carefully managed. As Greg Dostatni cautions:



> ... automation is a great way to automatically mess up a large portion of the environment. Where automation fails is that it is very hard to check every possible system state. If something unexpected happens the automation scripts will happily chug along and keep making the same changes everywhere. Automation could work if it is combined with staged release. Allow and enforce that only a small portion of the environment is allowed to change at any given time.

####  **Conclusion**

In technology projects involving critical infrastructure and applications, robust change control policies, and well-defined rollback plans are not just best practices — they are essential safeguards. These processes protect against risks associated with changes, ensure system stability, and maintain trust among internal stakeholders and external customers. By investing in these strategies, organizations can confidently manage their technology environments, knowing they are prepared for any eventuality.

---
[View this page online](https://www.commandprompt.com/blog/essential-role-of-rollback-plans-part-2/)

---

# The Critical Importance of Robust Change Control Policies and Rollback Plans in Technology Projects

> Learn the importance of robust change control policies in technology projects. Explore strategies to minimize risks, ensure smooth implementations, and maintain system stability through effective change management.

Robust systems are essential in the fast-paced and ever-evolving world of technology, where even minor disruptions can cascade into significant downtime or data loss. Yet even the most resilient infrastructure can falter without proper change management. This two-part series delves into the critical importance of two foundational practices: change control policies and rollback plans.

In Part 1, we’ll explore the value of establishing robust change control policies that minimize risks and ensure every modification to a system is deliberate, tested, and aligned with organizational goals.

###  **Part 1: The Value of Robust Change Control Policies**

Smart businesses and organizations must remain agile for both scalability and a constantly evolving technological landscape, to sustain a stable and secure infrastructure to support their operations. When dealing with complex systems, the margin for error is slim because even a minor misconfiguration or unexpected interaction can lead to significant disruptions. We spend a lot of effort to build robust, scalable, and resilient services, but humans still manage those services. Human error is attributed as one (if not the largest) source of unplanned downtime. Kevin Heslin, chief editor of the Uptime Institute Journal, stated in [this blog post](<https://journal.uptimeinstitute.com/how-to-avoid-outages-try-harder/>):

> Perhaps there is simply a limit to what can be achieved in an industry that still relies heavily on people to perform many of the most basic and critical tasks and thus is subject to human error, which can never be completely eliminated.

This is where the importance of robust change control policies and effective rollback plans comes into play.

####  **What is Change Control?**

Change control is the process of managing how changes are introduced into a system. A robust change control policy ensures that any modification — a patch, an upgrade, or a configuration change — is planned, tested, reviewed, and approved before implementation. This process minimizes the risk of unintentional disruptions and ensures that changes align with business objectives.

####  **Key Components of a Robust Change Control Policy**

  1.  **Communication:** All stakeholders, including IT teams, management, and end-users, should be informed of upcoming changes. This communication helps prepare the organization for any potential impact and reduces the risk of surprise disruptions.
  2.  **Approval Process:** Changes should be reviewed and approved by relevant stakeholders before they are applied. This ensures that all potential impacts are considered and that the change aligns with organizational goals.
  3.  **Detailed Documentation:** Every change should be thoroughly documented, including the reason for the change, the expected outcome, and potential risks. This documentation serves as a reference for both the implementation at hand as well as future changes and internal audits.
  4.  **Testing Environment:** Before applying changes to the production environment, they should be tested in a controlled environment that mirrors production as closely as possible. This step helps identify unforeseen issues and provides an opportunity to fine-tune the change.



Greg Dostatni, known for his expertise as a DBA for Command Prompt, shared a keen observation about a common challenge in change control:

> This is where I see most companies fail. Replicating the production load is hard. Would it make sense to say and acknowledge that fact and put it as justification for why you may want a rollback procedure?

This observation leads us to the next topic – the essential role of rollback plans as a safety net, ensuring that systems can recover quickly and effectively when unforeseen challenges arise in production environments. Stay tuned for "Part 2: The Essential Role of Rollback Plans".

 **Want to learn more now?** Dive deeper into preparing for changes in this informative blog post from James Campbell - "Pinpointing, Planning, and Roadmapping Future Software Updates: Why It Matters."

* * *

 **Need help?** Reach out and contact us today!

---
[View this page online](https://www.commandprompt.com/blog/critical-importance-of-change-control-policies-part-1/)

---

# The PostgreSQL Roadmap: Understanding Milestones in Versioning, Features, and Upgrades

> PostgreSQL is an open-source, feature-rich, and highly extensible relational database system used globally across countless sectors. Over the years, it has gro…

PostgreSQL is an open-source, feature-rich, and highly extensible relational database system used globally across countless sectors. Over the years, it has grown significantly with each release, becoming one of the most reliable databases for developers and enterprises. Let’s explore the PostgreSQL roadmap, focusing on its major version changes, key features introduced in newer releases, use cases, and why upgrading is essential for better stability and performance.

 **PostgreSQL 's Naming Convention Shift: From 9.6 to 10**

Before Version 10, PostgreSQL followed a three-digit versioning format: major.minor.patch. For instance, releases were named 9.0, 9.1, 9.2, and 9.6. Each of these versions signaled a specific series of updates that were improvements or bug fixes but were part of the same overarching major version.

However, starting with version 10, PostgreSQL shifted to a simpler versioning scheme: major.minor. After that, PostgreSQL 10 was followed by 11, 12, 13, and so forth. This change was driven by the need to communicate substantial updates more clearly. Instead of treating major updates like minor ones (as happened in the 9.x series), this new format allows for a better understanding of significant advancements in each version, highlighting that these were major shifts in the product.

 **Key takeaway:** This change in the naming convention was introduced to make the significance of major updates more transparent to users and administrators.

 **Critical Features Introduced in Recent Versions**

Let's walk through some of the major versions and the critical features introduced:

 **PostgreSQL 10 (Released in October 2017)**

  * Logical Replication: Introduced logical replication, allowing selective replication of tables and columns. It opened up use cases such as synchronizing different versions of an application or replicating to different schemas.
  * Declarative Table Partitioning: Enhanced partitioning capabilities with improved management make working with large datasets easier.
  * Parallel Query Enhancements: Continued efforts to improve parallel query execution, leading to significant performance gains.



 **PostgreSQL 11 (Released in October 2018)**

  * Improved Partitioning: Added features like hash partitioning and automatic index creation on partitions, simplifying database maintenance.
  * Just-in-Time (JIT) Compilation: A significant speed boost in query execution using Low-Level Virtual Machine (LLVM), which allows PostgreSQL to compile code on the fly, thereby optimizing performance.
  * Parallelism Improvements: Extended parallel capabilities to more types of queries, such as parallel hash joins and parallel bitmap heap scans.



 **PostgreSQL 12 (Released in October 2019)**

  * Partitioning Improvements: Continued focus on partitioning with features like better foreign key support and faster partition pruning.
  * B-tree Index Optimization: Made significant improvements in the management of B-tree indexes, which are the backbone of most database queries.
  * Enhanced Query Optimizer: Smarter optimization of certain query plans, leading to faster execution for complex queries.



 **PostgreSQL 13 (Released in September 2020)**

  * Incremental Sort: Reduced memory usage and improved performance for sorted queries.
  * Deduplication of B-Tree Indexes: Implemented more efficient use of indexes by avoiding duplicate entries.
  * Parallel Vacuum and Analyzes: Speeds up table maintenance, reducing downtime for critical tables.



 **PostgreSQL 14 (Released in September 2021)**

  * Performance Enhancements: Improvements in multicolumn and parallel queries, resulting in better use of system resources.
  * Enhanced JSON Capabilities: Introduced more efficient storage and handling of JSON data.
  * Connection Scalability: Improved connection management for high-traffic systems, making PostgreSQL a better fit for applications with numerous concurrent users.



 **PostgreSQL 15 (Released in October 2022)**

  * MERGE SQL Command: Long-awaited support for SQL's `MERGE` command, simplified data manipulation tasks.
  * Sort Performance Gains: Improved sort performance by leveraging optimizations at a lower level.
  * Advanced Index Management: New options to rebuild indexes concurrently, reducing downtime during large-scale maintenance.



 **PostgreSQL 16 (Released in October 2023)**

  * Improved Data Encryption: Enhanced data security capabilities to comply with stricter regulations and higher security standards.
  * Parallel Indexing and More Robust Partitioning: Made handling partitions and indexes faster and more reliable.Improved Monitoring and Observability: Built-in enhancements to monitor system performance better, leading to faster issue resolution.



 **PostgreSQL 17 (Released in October 2024)**

  * System-wide Performance Gains: A new internal memory structure for vacuum that improved performance speed and resource availability.
  * Development Expansion: More features to MERGE, including conditional updates such as a RETURNING clause and the ability to update views.



 **Why Upgrading Matters: Improved Stability and Performance**

  1. Security Enhancements: With each release, PostgreSQL incorporates security patches and improvements to core functionalities, reducing the risk of vulnerabilities. Upgrading ensures that your database adheres to the latest security standards and protocols.
  2. Performance Gains: PostgreSQL has invested heavily in parallelism, indexing optimizations, and JIT compilation. These advancements translate to tangible performance gains, especially for large-scale applications and analytics workloads. For example, PostgreSQL 12's improved partition pruning can drastically reduce query execution times for large tables.
  3. Better Resource Management: With improved memory and connection handling, newer versions help applications scale effectively. For businesses with growing workloads or increasing user demands, upgrading ensures the database can handle these new challenges efficiently.
  4. Feature Availability: Newer versions come with critical features such as logical replication, JSON support improvements, and the `MERGE` command. These updates streamline development, simplify data migrations, and make it easier to manage complex data scenarios.



 **Use Cases for Upgrading PostgreSQL**

  1. Large Enterprises Handling Big Data: Upgrading to newer versions after PostgreSQL 13 is crucial for organizations dealing with large datasets due to better partition management and index optimization.
  2. High-Traffic Websites and Applications: Websites and applications requiring numerous concurrent connections can benefit from the improved connection scalability in version 14+.
  3. Data Warehousing and Analytics: Organizations performing heavy analytical operations should consider upgrading to version 12+ for JIT compilation and enhanced parallelism capabilities.
  4. Financial Services and High Security: Businesses requiring stringent security controls can leverage PostgreSQL 16's enhanced data encryption capabilities to ensure data integrity.



 **Conclusion**

The PostgreSQL roadmap demonstrates a clear trajectory of innovation and improvement. From the versioning change in PostgreSQL 10 to the more recent releases, each version introduces meaningful features that enhance performance, scalability, and security. Upgrading to newer PostgreSQL versions is not just about accessing new features – it's about leveraging improvements that can translate to better stability, higher efficiency, and safer data handling.

For any PostgreSQL-based system, understanding the version milestones and the advancements in each release helps in planning the right upgrades to keep up with best practices in database management.

By consistently upgrading and staying up-to-date with the latest releases, developers, and DBAs can harness the power of PostgreSQL’s relentless evolution to achieve better results for their applications and businesses.

 **References and Resources:**

  * PostgreSQL Global Development Group. [PostgreSQL: Versioning Policy](<https://www.postgresql.org/support/versioning/>)
  * [PostgreSQL Release Notes](<https://www.postgresql.org/docs/release/>)



* * *

 **Need Help?**

As the oldest dedicated Postgres professional services and support company in the world, our Command Prompt team of experts can help you with your upgrade strategy. Contact us today for help with your next upgrade.

---
[View this page online](https://www.commandprompt.com/blog/the-postgresql-roadmap/)

---

# Out of Cycle PostgreSQL Release: November 21, 2024

> The latest PostgreSQL updates were released on November 21, 2024, which address critical issues affecting data integrity and system stability.PostgreSQL Versio…

The latest PostgreSQL updates were released on November 21, 2024, which address critical issues affecting data integrity and system stability.

 **PostgreSQL Versions Update**

The PostgreSQL Global Development Group has [released updates for all supported versions: 17.2, 16.6, 15.10, 14.15, and 13.18.](<https://www.postgresql.org/about/news/postgresql-172-166-1510-1415-1318-and-1222-released-2965/>) Additionally, due to the nature of one of the issues in the previous update release, they have also released version 12.22 for PostgreSQL 12, even though it has reached its end-of-life (EOL) and will not receive further fixes. citeturn0fetch0

 **Bug Fixes and Improvements**

The recent updates include several important fixes for PostgreSQL 17. (Some of these issues may affect other supported versions of PostgreSQL):

\- **ALTER ROLE and ALTER DATABASE Functionality** : Restored the functionality of ALTER ROLE .. SET ROLE and ALTER DATABASE .. SET ROLE. A previous fix for CVE-2024-10978 inadvertently caused settings for roles to not be applied if they came from non-interactive sources, including prior ALTER {ROLE|DATABASE} commands and the PGOPTIONS environment variable.

\- **Extension Compatibility** : Restored compatibility for the timescaledb and other PostgreSQL extensions built using versions prior to the November 14, 2024 release (17.0, 16.4, 15.8, 14.13, 13.16, 12.20, and earlier). This fix reverts struct ResultRelInfo to its previous size, eliminating the need to rebuild affected extensions.

\- **Logical Replication Slots** : Fixed cases where a logical replication slot's restart_lsn could regress to an earlier state.

\- **WAL File Management** : Prevented the deletion of necessary Write-Ahead Log (WAL) files during pg_rewind operations.

\- **Shared Statistics** : Addressed race conditions associated with dropping shared statistics entries, which could lead to the loss of statistical data.

\- **ALTER TABLE Stability** : Resolved a crash issue with ALTER TABLE when checking if an index's operator class options have changed, particularly if the table has an index with a non-default operator class.

For a comprehensive list of changes, please review the release notes at https://www.postgresql.org/docs/release/.

 **PostgreSQL 12 End-of-Life (EOL) Notice**

 **This release marks the final update for PostgreSQL 12, which has now reached its end-of-life and will no longer receive security or bug fixes.** If you are operating PostgreSQL 12 in a production environment, we strongly recommend planning an upgrade to a newer, supported version. For more information, please refer to the versioning policy at https://www.postgresql.org/support/versioning/.

 **Action Required**

If your systems are running versions earlier than those mentioned above, it is crucial to upgrade to the latest releases to maintain security and stability. If you require assistance with the upgrade process or have any concerns, our team is here to support you.

. [Contact Command Prompt today](<https://www.commandprompt.com/contact-us/>)!

---
[View this page online](https://www.commandprompt.com/blog/out-of-cycle-postgresql-release-november-21-2024/)

---

# PgManage 1.2 Released

> The latest version of PgManage has been released! PgManage 1.2 Release introduces new features and improvements, and addresses several bugs reported since the …

The latest version of PgManage has been released! PgManage 1.2 Release introduces new features and improvements, and addresses several bugs reported since the last release. Please update to the latest version at your earliest convenience.

New features:

  * Implemented support for adding/changing table indexes in Schema Editor
  * Implemented Postgres role editor
  * Added SQL error annotations in the query editor
  * Significant code completion improvements: added context-aware schema, table, view, column and function completions
  * Added support for Postgres byte array display query results data grid



Bugs fixed:

  * Connection manager where "Discard changes" confirmation was shown after clicking "Test Connection" button
  * Fixed where PgManage was trying to restore tabs for closed database workspaces
  * Fixed where "Discard changes" confirmation appeared after running "Explain/Analyze" and then closing the DB workspace
  * Fall back to unencrypted SSH key when no password is provided (thanks u/El-Virus)
  * Use a user-provided database password instead of a previously stored one when "Test connection" is clicked in the connection manager
  * Fixed a bug when backup/restore background job info was potentially accessible by other pgmanage user accounts
  * Fixed a bug when redundant database back-end was instantiated when requesting database auto-completion metadata
  * Fixed a rare race condition when opening a new database workspace
  * Rearranged parts of the DROP INDEX query template to make it runnable without needing extra modifications by the user
  * Fixed a bug in the Monitoring Dashboard when the "Refresh all widgets" button was doing nothing after deleting all and restoring some monitoring widgets
  * Fixed a bug in the connection manager where "Discard changes" confirmation was shown for connections with passwords auto-filled by the browser
  * Fixed a bug in the schema editor where the "DEFAULT" part of the column definition was rendered regardless of the presence of the column default value



UI/UX Improvements:

  * New application startup screen
  * Improved naming for exported CSV/XLS files



Other changes:

  * Django updated from 4.2.11 to 4.2.16
  * cryptography updated from 36.0.2 to 41.0.7
  * pymysql updated from 1.0.x to 1.1.1
  * psycopg2 updated from 2.9.5 to 2.9.9
  * oracledb updated from 1.3.1 to 2.2.1
  * Other occurrences of highlighted selection in the query editor are now case-insensitive
  * Implemented custom SESSION_SERIALIZER for improved session handling security
  * Eager-load QueryTab components when opening database workspace for improved app responsiveness
  * Added uniqueness validation to connection group names
  * Removed unnecessary files from the Windows build of PgManage
  * Changed default value for CSV separator setting
  * Improved database back-end cleanup when no keep-alive requests come from the front-end
  * don't show an error toast when running Explain/Analyze if PEV2 can display these errors by itself



Downloads & Sources are available here:

  * <https://commandprompt.com/products/pgmanage/>
  * <https://github.com/commandprompt/pgmanage>



Contributions and feedback are welcome!

* * *

Want to receive blog updates straight to your inbox? Subscribe to the [Command Prompt Substack here](<https://cmdpromptinc.substack.com/>).

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-12-released/)

---

# PgManage 1.1.1 released

> The latest version of PgManage has been released! PgManage 1.1.1 Release introduces new features and fixes 1 security vulnerability and several bugs reported s…

The latest version of PgManage has been released! PgManage 1.1.1 Release introduces new features and fixes 1 security vulnerability and several bugs reported since the last release. Please update to the latest version at your earliest convenience.

  * New features:
    * Added IPv6 support for database connections
    * Allow using UNIX domain socket paths in connection form -> server field ([#438](<https://link.sbstck.com/redirect/c559f823-f228-4551-94da-81173073a730?j=eyJ1IjoiMmFyZms2In0.R9Rsh5FQDMlCeVNNSFuVnUG3qEw2aw3-E94qWzz1XJw>))
    * Allow empty server values in the connection form for Postgres connections
    * Password prompt will now be shown when a user tries to establish a database connection with the wrong password
    * Queries in the console query history modal can now be copied to the query tab with a double-click
    * The console history buffer is now cleared from memory when the "clear console" button is clicked
  * Bugs fixed:
    * Fixed unrestricted code execution vulnerability in monitoring widget back-end. The PgManage project thanks Andrew Effenhauser, Ayman Hammad, and Daniel Crowley of [IBM X-Force Red](<https://www.ibm.com/services/offensive-security>) for reporting this issue.
    * Fixed Entity Relationship not rendering diagram for some database layouts
    * Fixes issue when expanded DB object tree node was not always scrolled to the top of the viewport
    * Fixed missing GRANT statements when roles are displayed in the DDL tab
    * Fixed a bug when application tabs may become unresponsive in some cases
    * Various minor layout fixes and tweaks



Downloads & Sources are available here:

  * <https://commandprompt.com/products/pgmanage/>
  * <https://github.com/commandprompt/pgmanage>



Contributions and feedback are welcome!

* * *

Want to receive blog updates straight to your inbox? Subscribe to the [Command Prompt Substack here](<https://cmdpromptinc.substack.com/>).

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-111-released/)

---

# Pinpointing, Planning, and Roadmapping Future Software Updates: Why It Matters

> Planning and road-mapping updates not only address immediate issues but also contribute to long-term stability and security, helping your organization avoid ma…

Pinpointing, planning, and road-mapping future software updates are essential for maintaining a secure, efficient, and functional database environment. While it may be tempting to delay updates in favor of other “more pressing” work, postponing these updates can lead to severe consequences down the line. By taking time to proactively plan updates, you can ensure smoother processes in the future.

## Assess and Plan

The key to effective update management starts with a comprehensive assessment of your current software. Begin by cataloging all software applications and their versions, and compare your audit to the latest available and supported versions. This process will highlight outdated or soon-to-be outdated systems. Prioritize updates based on their importance and impact on your organization: Failing to update an outdated public-facing application may have more dire consequences than failing to update a developer-only sandbox environment. But remember that those aging backend servers can still pose a security risk.

## Identify and Prepare for Risks

There are several risks associated with implementing updates:

  * Both the planning period and the implementation period could reveal new and unexpected issues
  * Unforeseen complications could occur if you do not have a robust test environment that mirrors your production environment – if your test environment is inadequate, now is the time to improve it
  * Updates could disrupt other parts of your system - preparation can help in identifying potential problems early



Uncomfortable talking to your manager about needing time and resources to plan future updates? Consider framing the conversation around risks and benefits:

  * For supportive managers, leverage upcoming audits or compliance requirements as justification for the updates - they’re going to want to be prepared ahead of time.*
  * For managers who would rather delay, emphasize the risks of neglecting updates, such as security vulnerabilities and operational disruptions. Frequent small upgrades are generally less disruptive and more manageable than gigantic, infrequent nightmare upgrades.
  * Present concrete examples of what has happened in similar situations to underscore the importance of staying current. Many people can probably point to a "Remember how that time went?" type of event.



> *In such cases, what could have been a manageable update becomes a frantic scramble.

Planning and road-mapping updates not only address immediate issues but also contribute to long-term stability and security, helping your organization avoid major headaches down the road.

## Additional Resources

Here are a few resources that can help you stay ahead and aware of any vital updates, especially related to security issues:

  * Subscribe and routinely review the [CISA's Catalog of known Vulnerabilities Catalog](<https://www.cisa.gov/known-exploited-vulnerabilities-catalog>). Special attention should be paid to updates that are often overlooked but essential for security and functionality.
  * [The Cyber Management Alliance](<https://www.cm-alliance.com/>) compiles listings of recent cyber attacks. Follow [their blog](<https://www.cm-alliance.com/cybersecurity-blog/>).
  * [Bleeping Computer](<https://www.bleepingcomputer.com/>) information security and technology news site covers the latest security threats and new ways to stay protected online. As the first news and support site to be added as a partner of the No More Ransom Project, they routinely share vital [security-related news](<https://www.bleepingcomputer.com/news/security/>).



 **Unsure about where to start?** Our team is here and ready to assist you in navigating the complexities of update management. We can provide expert guidance on creating a comprehensive roadmap tailored to your specific needs, ensuring your systems remain secure and functional. Contact Command Prompt today!

---
[View this page online](https://www.commandprompt.com/blog/pinpointing-planning-and-roadmapping-future-software-updates-why-it-matters/)

---

# Upgrade Your PostgreSQL Version to Ensure Stability and Security

> The PostgreSQL Global Development Group recently released important updates for several supported PostgreSQL versions, including 16.4, 15.8, 14.13, 13.16, 12.2…

The PostgreSQL Global Development Group [recently released important updates](<https://www.postgresql.org/about/news/postgresql-164-158-1413-1316-1220-and-17-beta-3-released-2910/>) for several supported PostgreSQL versions, including 16.4, 15.8, 14.13, 13.16, 12.20, as well as the 17 Beta 3. One security vulnerability and over 55 bugs were addressed, many of which affect PostgreSQL 16 and other supported versions.

## Security Issue: pg_dump

The August 8th release addresses security vulnerability [CVE-2024-7348](<https://www.postgresql.org/support/security/CVE-2024-7348/>): PostgreSQL relation replacement during pg_dump executes arbitrary SQL. From the CVE page:

> Time-of-check Time-of-use (TOCTOU) race condition in pg_dump in PostgreSQL allows an object creator to execute arbitrary SQL functions as the user running pg_dump, which is often a superuser. The attack involves replacing another relation type with a view or foreign table. The attack requires waiting for pg_dump to start, but winning the race condition is trivial if the attacker retains an open transaction. Versions before PostgreSQL 16.4, 15.8, 14.13, 13.16, and 12.20 are affected.

This vulnerability impacts all supported versions of 12 - 16 prior to this release.

## PostgreSQL 12 EOL: November 14, 2024

Also of note, PostgreSQL 12.20 marks the final update before this version reaches its End-of-Life (EOL). If your systems are still running PostgreSQL 12, it's crucial to act now.

As PostgreSQL 12 enters its EOL phase, it will no longer receive updates or security patches, leaving your databases vulnerable. Upgrading to a newer version ensures that you continue to receive essential security updates. It also allows you to take advantage of the latest features and performance improvements.

###  **Not ready to upgrade yet?**

Command Prompt offers comprehensive EOL support to help you transition smoothly. Whether you need guidance on the upgrade process or long-term support for your legacy systems, we're here to assist you.

Don't wait until it's too late— contact us today to discuss how we can help you upgrade your PostgreSQL version and secure your database infrastructure for the future.

---
[View this page online](https://www.commandprompt.com/blog/upgrade-your-postgresql-version-to-ensure-stability-and-security/)

---

# 11 Essential Tips to Maximize The Summer Slowdown for a Productive Fall

> As the summer winds down, many of us have experienced a professional lull with school breaks and summer vacations.This transition offers a golden opportunity t…

As the summer winds down, many of us have experienced a professional lull with school breaks and summer vacations.

This transition offers a golden opportunity to prepare for a successful fall. Our team of System Admins and DBAs has compiled top strategies to make the most of this period:

  1.  **Plan and roadmap future updates.**
  2.  **Determine which OS updates you’ve been putting off and do them**
    1. Execute pending OS and database updates including applicable utilities and extensions
    2. Test, test, test - Testing in production is not testing! (example: CrowdStrike incident)
  3. Ensure you have and implement a change control policy
  4.  **Evaluate and improve current infrastructure**
    1. Review your infrastructure as code to see if you have drift going on that you aren't aware of
    2. Pinpoint where your data is and isn’t
  5. Audit your systems and streamline integrations including monitoring
  6.  **Conduct Disaster recovery testing**
  7. Perform server maintenance
  8. Update and backfill documentation
  9. Focus on professional development
  10. Reassess success metrics and goals
  11. Prioritize and communicate your project goal, requirements, and timeline to internal and external support teams



Use the next few months to enhance your operation and database environment and applications, catch up on professional growth, and set clear goals for your organization. Follow along for detailed insights each week!

Ready to optimize seasonal downtime and ensure a smooth transition into fall? Reach out to Command Prompt for professional services and support!

---
[View this page online](https://www.commandprompt.com/blog/11-essential-tips-to-maximize-the-summer-slowdown-for-a-productive-fall/)

---

# Global IT Outage & The Impact on Windows Systems: Consider An Open Source Alternative

> Global IT Outage: The Impact on Windows Systems and the Case for Open Source Alternatives

On July 19, 2024, a significant IT outage impacted Windows systems globally, [disrupting operations across various sectors](<https://www.theverge.com/2024/7/19/24201717/windows-bsod-crowdstrike-outage-issue>) including health care and emergency services, medical providers, airlines, banks, and media. Aviation industry leader [Delta Air Lines is making progress](<https://news.delta.com/update/july-2024-operation/delta-teams-make-progress-restore-operation>) but has yet to fully recover from the outage, [continuing to cancel hundreds of flights for the last few days](<https://www.npr.org/2024/07/22/nx-s1-5048858/delta-canceles-hundreds-of-flights-recovering-after-crowdstrike-failures>).

The CEO of CrowdStrike [has been called upon by members of Congress to testify about the incident](<https://apnews.com/article/crowdstrike-tech-outage-microsoft-windows-falcon-8fe725037ab975e011b2cfad67b17c0f>), including members of the House Homeland Security committee.

The issue originated from a faulty update in the Falcon Sensor software by CrowdStrike, leading to widespread system crashes and the infamous "blue screen of death" (BSOD). Both [CrowdStrike](<https://www.crowdstrike.com/blog/statement-on-falcon-content-update-for-windows-hosts/>) and Microsoft acknowledged the problem and have been working on resolutions.

According to [Windows Central](<https://www.windowscentral.com/microsoft/mitigation-actions-microsoft-cloudstrike-outages>):

> July 19, 9:38 AM ET: CrowdStrike's engineers claim to have fixed a faulty kernel driver responsible for the outages but say it will be "some time" before worldwide services return to normal. While some infrastructures recovered, thousands of flights were still canceled, and public transport remains disrupted in some areas.

Windows Central also offered a [how-to article on fixing BOSD errors on Windows 11](<https://www.windowscentral.com/software-apps/windows-11/how-to-resolve-crowdstrike-blue-screen-error-on-windows-11>) due to the CrowdStrike issue.

Microsoft stated in a [post on X](<https://x.com/MSFT365Status/status/1814251159537729592>) that “the update to CrowdStrike’s Falcon software led to “an issue with Windows 365 Cloud PCs.” The post includes a guide on how to fix the issue.

In the meantime, Microsoft has taken action to repair its Azure servers, and also addressed a separate issue for global Windows users. It is unknown at this time whether the Azure problems are related to the faulty CrowdStrike update.

 _Update 7/25/2024_ \- CrowdStrike has created a [Remediation and Guidance Hub:](<https://www.crowdstrike.com/falcon-content-update-remediation-and-guidance-hub/>)

[ Falcon Content Update for Windows Hosts](<https://www.crowdstrike.com/falcon-content-update-remediation-and-guidance-hub/>) dedicated webpage that is updated daily.

 **Major Issues with Windows**

While the global IT outage was due to a bad update published by CrowdStrike, it does draw attention to issues with Windows OS in general. Major issues with Windows operating systems revolve around high costs, frequent updates that can disrupt workflows, and privacy concerns according to this [Windows Central article](<https://www.windowscentral.com/one-thing-microsoft-didnt-discuss-windows-11-privacy>) . Many users face substantial expenses when purchasing Windows licenses, which can financially burden individuals and organizations.

Windows updates are often mandatory and can occur at inconvenient times, causing interruptions in work and potentially leading to data and financial losses.

Windows 10 and Windows 11 employs extensive data collection practices, where telemetry data is continuously sent back to Microsoft. This data can include browsing history, app usage, and event location information, often without users being fully aware of the extent of the data collection ([MDPI](<https://www.mdpi.com/2410-387X/8/1/5>)). According to an article titled [“Pervasive User Data Collection from Cyberspace: Privacy Concerns and Countermeasures”](<https://www.mdpi.com/2410-387X/8/1/5>) published January 31, 2024, by MDPI in the international, scientific, peer-reviewed open access journal, [_Cryptography_](<https://www.mdpi.com/journal/cryptography>):

> Microsoft has further expanded LDP’s scope to include telemetry collection, graph data analysis, language data analysis, iterative interactions, and incorporating prior knowledge. These developments illustrate the evolving landscape of LDP, addressing the intricacies of various data types and privacy concerns.

 **Consider an Open Source Alternative**

To avoid similar issues in the future caused by forced updates, consider switching to an open source operating Linux for your operating systems. Open source alternatives offer various benefits, including:

  1. Cost-effectiveness: These systems are free to use, reducing financial burdens.
  2. Control Over Updates: Users can manage updates according to their schedules, minimizing disruptions.
  3. Enhanced Privacy: Open source software is transparent, allowing users to manage their data privacy better.



Explore options like Ubuntu, Debian, and others to enhance your computing experience with more control, security, and cost-efficiency. Further, as these are Open Source platforms, many vendors such as Command Prompt can support you enterprise-wide.

Reach out to us with any questions or for further assistance in installing or implementing a Linux OS, including configuration and best practices for data performance and security.

---
[View this page online](https://www.commandprompt.com/blog/global-it-outage-the-impact-on-windows-systems-consider-an-open-source-alternative/)

---

# PgManage 1.1 Released

> PgManage 1.1, a usable Open Source Postgres manager, has been released

The latest version of PgManage has been released!

## New features:

  * pgmanage now uses database-specific syntax highlighting rules in SQL editors depending on the database type
  * Added support for displaying column data types in query results data grid
  * Columns in the query results data grid can now be minimized/maximized by double-clicking the column header
  * Switchable data grid layouts in query tabs: adaptive, compact, and fit-content can be selected by clicking the ellipsis icon on the top-left corner of the grid
  * Existing DB connection can now be cloned in the connection manager dialog
  * The size of the next loaded data chunk can now be selected when using "fetch-more" feature for large query results
  * Added multi-statement query support for SQlite3
  * Database connections can now have a color label to make it easier to differentiate between different environments
  * scram-sha256 password hashing is now used when changing Postgres role passwords



## UI/UX Improvements:

  * 'fetch all records' is now also supported DB console tabs
  * Removed unnecessary schema name prefixes from table partition names in DB object tree
  * Added warning about unsaved changes in the Postgres Server configuration tab before closing
  * Added confirmation when deleting configuration change history records in the Postgres Server configuration tab
  * Added support for showing newline characters in query results data grid cells
  * Added support for showing null and blank values in query results data grid cells
  * The data grid is no longer hidden for queries that return 0 rows
  * Added visual hints for column resize handles in data grid headers
  * Improved DB console and SSH terminal performance when displaying large amounts of text
  * Significantly improved performance of query result data grids when working with large amounts of data
  * It is now possible to reuse a query from the history dialog by double-clicking on the corresponding query cell



For additional fixes and minor improvements, see the full changelog on the [Github Release Page](<https://github.com/commandprompt/pgmanage/releases/tag/1.1>).

Packages are available for Linux, Windows and Mac. Learn more here.

* * *

Want to receive blog updates straight to your inbox? Subscribe to the [Command Prompt Substack here](<https://cmdpromptinc.substack.com/>).

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-11-released/)

---

# Privacy Concerns and Risks with Slack's AI and ML Training

> In today’s digital workplace, privacy concerns are paramount, especially when using communication tools like Slack for sharing sensitive information. Recently,…

In today’s digital workplace, privacy concerns are paramount, especially when using communication tools like Slack for sharing sensitive information. Recently, Slack has been integrating advanced Artificial Intelligence (AI) and Machine Learning (ML) technologies to boost user experience and functionality. While these advancements bring substantial benefits, they also introduce potential privacy risks that users need to be aware of.

 **Privacy Concerns:**

Slack’s AI and ML systems are trained using data from user interactions. This means that the messages, files, and other data shared within your Slack workspace could potentially be utilized to improve these AI and ML models. Although Slack has implemented stringent security measures, the following risks should be considered:

  * Data Exposure: Sensitive or confidential information shared on Slack could be accessed and used in ways not intended by your organization.
  * Data Retention: Slack may retain data for extended periods to train their models, leading to concerns about data lifecycle management.
  * Model Training: The global model training process may inadvertently expose your data to third-party entities or across different regions, which could be outside your data residency requirements.



 **Recommended Actions:**

To mitigate these risks and ensure the privacy and security of your data, we recommend the following actions:

  1. Review [Slack’s Privacy Principles](<https://slack.com/intl/en-gb/trust/data-management/privacy-principles>): Understand how your data is being used and what measures Slack has in place to protect your data.
  2. Opt-out: Contact Slack to exclude your Customer Data from Slack global models as described in their privacy principles.
  3. Adjust Data Sharing Practices: Be cautious about sharing sensitive or confidential information through Slack. Consider using more secure methods for transmitting such data.
  4. Use Slack’s Security Features: Utilize available security settings within Slack to enhance data protection, such as data encryption and access controls.
  5. Utilize Alternative Solutions: For highly sensitive communications, consider using secure communication tools that offer more stringent data privacy assurances. For our clients, we also encourage you to use the features (Secure Paste, Wiki, File Uploads, Documents) inside your secure Redmine environment to share sensitive information. **Note:** Google Chat is not e2e and Microsoft Teams **is** e2e (Premium).



We understand that this information might be concerning. We are here to support you in navigating these challenges. We can also help you deploy private solutions such as Discourse or Mattermost to provide collaborative environments that are more productive than Slack and protective of your privacy.

Please feel free to reach out to us with any questions or for further assistance in implementing best practices for data security.

---
[View this page online](https://www.commandprompt.com/blog/privacy-concerns-and-risks-with-slacks-ai-and-ml-training/)

---

# The Essential

> We like to say, “This season too will pass”, “Give it to God”, “My therapist and I are working on it”, and “I will be able to get to that if only…” The reality…

We like to say, “This season too will pass”, “Give it to God”, “My therapist and I are working on it”, and “I will be able to get to that if only…” The reality is many of us are focused on the wrong things. We are so focused on externalities in society that it never occurs to us that we are ignoring the very things that are important for success in life. I am not talking about artificial success of up-votes, being liked at church or your slack channel. I am talking about the deep connection that we are always seeking yet can never seem to find. It is this great information age that causes many of us to forget that humans do not have the armor or the emotional constitution to distance us from the great many rage machines that have been created in the name of profit.

## In the name of profit

I love profit. It is the great equalizer in this world. It is profit that allows us to take time for our families, our community and ourselves. Without profit we are struggling to survive and self-sufficiency is a myth without it. It is also a drug and with all drugs your tolerance can grow and you keep seeking more. What if our profit was twice as much? What could we do? It is a spiral into the blackhole that creates the great demons of our age: The Military Industrial Complex, Private Prisons, Social-Mass Media and Debt. Instead what if we were able to focus our energies on what matters in the long term?

## What is essential

If you ask most people around the world what is essential to their lives they would likely answer some form of: Food, Water, Shelter and someone to love. Healthy people are not considering the profit of others, social-mass media, or an end to whatever conflict the social-mass media is currently shoving down our throats. They are too busy living and working their lives. They are going to church, participating in community, building their garden, taking walks with loved ones and playing with their children. They avoid toxic culture because they are fulfilled and don’t need the dopamine hit or false validation.

## Rubbernecking

Our life experience today is of rubbernecking and the response to it. People will doom scroll about whatever the social-mass media is projecting. One day it is Ukraine, the next Israel, the next protests, the next violation of our rights, the low U.S. birth rate, and then it starts all over again. I will start, several countries in Europe are restarting or considering conscription! 😱 What is your rubbernecking current event?

Are those societal causes important? Yes, they are and there isn’t a single thing you can do about it. You are not a geopolitical player. You are not a Mayor, President, Dictator, Ambassador, or policy maker for the United Nations (if you are, reach out I would love to have you on my [podcast](<https://podcasts.apple.com/us/podcast/more-than-a-refresh-conversations-with-the/id1554903835>)). This isn’t about staying in your lane, it is about staying on your freeway. You know instinctively what neighborhood to not walk in, why are you wasting precious emotional positivity and human connection on things you literally can not affect?

## Solutions

It is important to be informed. We need to be aware of events. We should be educated in what is going on in the world. It is far more important to be self-aware of the destructive tendencies of society and accept that we can only control what we do. If you are finding yourself doom scrolling, participating in gossip, feeling negative toward people or generally not moving forward in a productive and positive way then something needs to change. There is something in your life that you are in control of that you are not changing. Ignore the non-reality. If you are not directly involved, then it is likely out of your control and it is time to move on. I guarantee you there is something that isn’t being done that you actually can impact the quality of.

## Focus on the Essential

Create a new mantra for yourself. Whatever you are doing throughout the day ask yourself, does this somehow positively impact my ability to have Food, Water, Shelter and someone to love? If not then it is likely that part of the world doesn’t actually exist for you. It has somehow once again grabbed a hold of you. It is distracting you from what is essential, it is taking your energy away from being positive and productive. It is destroying your mind, your soul and your relationships. It will eventually destroy you in entirety.

What about the war in … There are over 180 [armed conflicts globally](<https://ourworldindata.org/grapher/number-of-armed-conflicts>). Ask yourself how many of those you knew existed and then ask yourself how you know about the half dozen you do. Then ask yourself why it is only those half dozen (hint: Social-Mass Media). Then ask yourself, outside of meditating, praying or holding a moment of silence once a week for them, why you care. You aren’t changing anything except causing yourself stress and trauma.

The great recovering alcoholics of the world understand:

> God, grant me the serenity to accept the things I cannot change,the courage to change the things I can, and the wisdom to know the difference.

---
[View this page online](https://www.commandprompt.com/blog/the-essential/)

---

# PgManage 1.0 Released

> PgManage 1.0 released, grab it today!

* New features:  

    * added SQL file import into Query and Snippet tabs
    * added SQL file export from Query and Snippet tabs
    * query tab title now displays the name of the imported file
    * query history can now be filtered by database
    * added MySQL and MariaDB support in database Schema editor
    * new autocomplete in SQL code editor
    * added search and replace in SQL code editor
    * added live query execution timer for long-running queries
    * make "restore application tabs" behavior configurable in application settings
    * make DB object tree "scroll into view" behavior configurable in application settings
  * Major Bugs fixed:  

    * fixed database tab restore concurrency issues when restoring multiple workspaces
    * change selected database when database child nodes are clicked
    * update workspace tooltips when corresponding connection gets renamed
    * don't try to run explain/analyze visualizer for non-Postgres database connections
    * don't allow setting nullable and primary-key column properties on schema editor
    * fixed various layout isues in UI walkthrough component
    * fixed issue when new monitoring widget modal wasn't possible to open after widget save/update
    * fixed automatic selection of last used database when reconnecting
    * reset connection properties form when connection manager dialog is closed
  * UI/UX Improvements:  

    * improved application font size change handling various parts of the app
    * copy only selected text into clipboard if editor has a selection
    * application tabs now fit within a single row and can be scrolled if there are too many tabs
    * improved UI performance during application panel resize
    * improved UI responsiveness when application window is resized
    * application data grids layout improvements
    * data editor cell contents modal can now be shown by double-clicking the cell
    * database query tabs now show the associated database in tab title
    * added buttons for database tab scrolling
    * improved displaying of long error messages in application toast notifications
    * warn user about unsaved connection changes in connection manager dialog
  * Other changes  

    * code indent feature now has a maximum content length limited to 75mb
    * monitoring dashboard was rewritten in Vuejs
    * application tab management code was rewritten in Vuejs
    * password dialogs were rewritten in Vuejs
    * improved SSH tunnel error handling
    * improved error reporting when SSH tunnel issues occur
    * legacy code cleaned-up/removed
    * improved database back-end clean-up when query is cancelled by the user
    * updated django from 3.2.18 to 3.2.25
    * updated tabulator.js from 5.5.2 to 6.2
    * updated chart.js
    * significantly improved application error logging
  * Download  

    * [Linux AppImage](<https://github.com/commandprompt/pgmanage/releases/download/1.0/pgmanage-1.0.AppImage>)
    * [MacOS .dmg](<https://github.com/commandprompt/pgmanage/releases/download/1.0/pgmanage-1.0_mac_x64.dmg>)
    * [Windows Installer](<https://github.com/commandprompt/pgmanage/releases/download/1.0/pgmanage-1.0_setup_win64.exe>)
  * Contribute  

    * PgManage is Open Source and being developed on [Github](<https://github.com/commandprompt/pgmanage>)

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-10-released/)

---

# Less is More

> Sometimes, after using a tool for many years, you will discover a feature that totally changes how you do things. When it is a fundamental tool like “less”, it…

Sometimes, after using a tool for many years, you will discover a feature that totally changes how you do things. When it is a fundamental tool like “less”, it changes how you interact with many command line programs in Linux*.

Did you know that less can do far more than just press space to advance to the next page? I sure didn’t. Then one day I went down the rabbit hole that is less and now I use it everywhere.

Let me demonstrate using our favorite database and favorite access tool - psql.

Let’s say that we are querying a customer's table. A simple “select first_name, last_name, email, city, country from customers" is going to get us started.

That is a lot of customers. We could easily add a filter to our query above, but what if we do not want to? Maybe the subspace link is too expensive, or we just want to easily view some aspect of the data without rerunning the query over and over.

If the data loaded into the pager (or if you selected “\pset pager always”), you are seeing this table through less.

Press “/”, followed by CTRL+k, then “serenity” to highlight all of our loyal customers with serenity emails.

That’s useful information, but if the data spans multiple screens, we’d have to scroll to find all the highlighted values. That’s not ideal if, for example, we want to copy and paste all of the records that use “Earth” for a country. Earth is not a country, so those values need to be fixed. We could copy highlight all of those sections that say “Earth” and then remove extra lines, but there is a better way.

Type “&” followed by “Earth” and press Enter.

Our screen changes to just show all of the lines that contain the word “Earth” in them. Much easier to copy all of them into an email. If you want to go back to the original list just filter again with empty pattern “&” + Enter. Sometimes you may need to scroll up to bring the original data back onto the screen.

That is really it. There are a few options for searching, color highlighting, but just these two little features changed how I interact with many programs. For example, did you know that “\h” and “\?” pages output through less as well? Try doing “\?” and then filtering for just the psql commands that accept a “FILE” as an attribute. Or maybe ones that operate on a buffer?

Less comes with its own help. Try pressing “h” on any less screen to see the available options. We can perform case insensitive pattern matching, jump to specific line of output, control scrolling, save output to a file and lots more.

There is even a way to keep your final, filtered output on the screen after you are finished. Simply export LESS=’-X’, and the output will remain available for further reference.

The best part is that less is used in so many places. Manpages, git log, systemctl status, journalctl are just a few common commands that use less in the background. Now you can highlight, search and filter any of that output.

Happy paging.  
  
  
* Windows users are defaulted to using the “more”pager which does not have these capabilities. It is possible to install the GnuWin32 version of less. Once you do, make sure to edit your environment variables in ControlPanel. You want to add both the GnuWin32 and Postgresql bin directories to the PATH variable, as well as create the PAGER variable that points to the less program. At the time of writing this, the GnuWin32 less can perform searches and highlighting, but does not appear to have the filtering capabilities.

---
[View this page online](https://www.commandprompt.com/blog/less-is-more/)

---

# Getting Started with pgBackRest: Perform Your First Backup

> pgBackRest is a complete backup and continuous archiving solution for PostgreSQL offering support for point-in-time recovery (PITR), fast multi-threaded backup…

## **Intro**

pgBackRest is a comprehensive backup and continuous archiving solution for PostgreSQL, providing support for point-in-time recovery (PITR), fast multi-threaded backup and restore, as well as compression and encryption of backups, among other features. In this article, we will explore pgBackRest’s features and present how to set up a basic pgBackRest configuration.

pgBackRest supports three kinds of backups: full, incremental, and differential. The full backup copies the entire content of the database cluster, while the incremental/differential backup copies only the database cluster files that have changed since the last full backup. The incremental backup helps to reduce backup time and disk space usage. By default, pgBackRest will attempt to perform an incremental backup in order to copy the database cluster files that have changed since the last backup, but if there is no previous backup, it runs a full backup.

##  **Features:**

 **Parallel Backup & Restore**: To improve performance and transfer during backups, pgBackRest allows you to set up multiple processes using lz4 and zstd compression algorithms. This may be specified in the --process-max parameter.

 **Local or Remote Operation** : pgBackRest can restore and backup locally or remotely using TLS/SSH.

 **Full, Differential, & Incremental Backups (at File or Block Level)**: pgBackRest supports the following kinds of backups:

  * Full backup: All the data is sent to another location.
  * Differential backup: Only backs up the files that have changed since the last full backup.
  * Incremental backup: Only backs up the files that have changed since the last backup.



 **Backup Rotation & Archive Expiration**: Retention policies can be set to backup for any time frame. For example, the WAL archive may be maintained for all backups or recent ones.

 **Backup Integrity** : pgBackRest calculates checksums for every file in backups and checks during a restore or a verify.

 **Page Checksums** : PostgreSQL started to support Checksums in version 9.3. If checksums are enabled, pgBackrest will validate them according to the kind of backups. During full backups, pgBackrest will validate all of the checksums. During differential and incremental backups, only the files that have changed will be validated.

 **Backup Resume** : If a backup is interrupted, it may be restored. Files that were already copied are compared with the checksums. This saves time because recalculating the checksums is faster than retransmitting data.

 **Streaming Compression & Checksums**: Compression and checksum calculations are performed while the files are being copied to the repository.

 **Delta Restore** : PgBackRest saves the checksums for every backup file so as to speed up any restore. In the case of a Delta Restore, files not present in the backup are removed, and checksums are created for the rest of the files. The files that match the backup stay the same, while the rest are restored.

 **Parallel, Asynchronous WAL Push & Get**: The Push and Get commands are available to push and get the WAL to and from the archive.

 **Tablespace & Link Support**: Tablespaces and directory links are supported. Tablespaces can be remapped to any location. Additionally, links can be restored to their original locations, remapped, or restored as files or directories within the cluster.

 **S3, Azure, and GCS Compatible Object Store Support** : PgBackRest’s repository can be stored on Amazon S3, Azure, and GCS-compatible object stores.

 **Encryption** : PgBackrest can encrypt the repository to secure stored backups.

 **Compatibility with ten versions of PostgreSQL** : PgBackRest is committed to maintaining compatibility with the five supported versions of PostgreSQL and the five end-of-life versions.

##  **Installation Guide:**

To install pgBackRest on an Ubuntu operating system, you may run the following commands:
    
    
    sudo apt update
    sudo apt -y install pgbackrest

If pgBackRest is not provided in your distribution, you may find more information on <https://pgbackrest.org/user-guide.html#installation>

## **Demo: Performing Your First Backup**

For this demo, we will configure pgBackrest with Postgres and simulate a backup. This is a simple setup in which no replicas are used.

Open the Postgres config_file with your preferred text editor. To find where your config_file is located, you may enter the following on a terminal:
    
    
    sudo -iu postgres
    psql
    SHOW config_file;

This will display the following:

Once you find your file, edit the following parameters:
    
    
    listen_addresses = '[host IP address]'
    password_encryption=’scram-sha-256’
    archive_mode = on

Now, reset the service so that the changes take effect:
    
    
    sudo systemctl restart postgresql-[version].service

To check that the parameters have been updated, you may type the following commands and query:
    
    
    Sudo -iu postgres
    Psql
    SELECT name,setting,context,source FROM pg_settings WHERE NAME IN ('listen_addresses','archive_mode','password_encryption');

This will display a table with the updated values:

Create the pgBackRest backup repository:
    
    
    sudo mkdir -p /var/lib/pgbackrest
    sudo chmod 750 /var/lib/pgbackrest
    sudo chown postgres:postgres /var/lib/pgbackrest
    sudo chown -R postgres:postgres /var/log/pgbackrest

Create a backup for your pgBackRest configuration file:
    
    
    sudo cp /etc/pgbackrest.conf /etc/pgbackrest.conf.backup

Now we are going to generate a key to encrypt the repository:
    
    
    openssl rand -base64 48

Edit the pgbackrest.conf file using your preferred text editor. Paste the following in the file:
    
    
    [global]
    repo1-cipher-pass=[Copy your previously generated key]
    repo1-cipher-type=aes-256-cbc
    repo1-path=/var/lib/pgbackrest
    repo1-retention-full=2
    log-level-console=info
    log-level-file=debug
    [demo]
    pg1-path=/var/lib/postgresql/[version]/main

Now, we can create our stanza, which we’ll call demo, like the name of the repository:
    
    
    sudo -u postgres pgbackrest --stanza=demo stanza-create

Now that everything is set up, we can perform a backup. First, open your Postgres config file and edit the archive_command parameter as follows:
    
    
    archive_command = 'pgbackrest --stanza=demo archive-push %p'

For the changes to be applied, we need to reload the database:
    
    
    sudo systemctl reload postgresql-[version].service

Now, let’s check if our stanza is okay:
    
    
    sudo -iu postgres pgbackrest --stanza=demo check

Now we can finally perform the backup with the following command:
    
    
    sudo -u postgres pgbackrest --stanza=demo --type=full backup

This command could take five minutes by default because of the checkpoint_timeout parameter on PostgreSQL. A checkpoint is a point in the sequence of transactions in which changes to data files are guaranteed to be on disk. The server performs a checkpoint every scheckpoint_timeout seconds or if the max_wal_size parameter is about to be exceeded. Though reducing the scheckpoint_timeout results in more frequent checkpoints (thus speeding up after-crash recovery because there are fewer datafiles to recover), it is not recommended because constantly writing dirty pages to disk might overload the I/O system by increasing traffic to the WAL log.

Now we must confirm that our stanza exists and has a full backup:
    
    
    Sudo -u postgres pgbackrest info

Let’s simulate a system administration disaster by deleting the database data files.

First, stop the postgresql service:
    
    
    sudo systemctl stop postgresql-[version].service
    sudo find /var/lib/pgsql/12/data -mindepth 1 -delete

If we try to start the database, this will fail as follows:
    
    
    sudo systemctl start postgresql-[version].service

Now that we have deleted all these data files, let’s go ahead and restore them:
    
    
    sudo -iu postgres pgbackrest --stanza=demo --delta restore

We should be able to start postgresql again:
    
    
    Sudo systemctl start postgresql-[version].service

Check whether pgBackRest is working:
    
    
    sudo -u postgres pgbackrest --stanza=demo check

Finally, it is good practice to perform another backup after a disaster instance:
    
    
    sudo -u postgres pgbackrest --stanza=demo --type=full backup

##  **Conclusion**

In this article, we discussed pgBackrest’s features, as well as how to install and perform a backup on a sample database.

Recapping the steps we took in our backup:

  * Update the archive_mode and encryption parameters in your configuration file
  * Create the pgBackRest backup repository
  * Create a backup for your pgBackRest configuration file
  * Generate a key to encrypt the repository
  * Update the pgbackrest.conf file to add cypher and path information for the repository
  * Create a stanza
  * Update the archive_command parameter in the postgres configuration file as 'pgbackrest --stanza=[stanza_name] archive-push %p'
  * Stop the PostgreSQL service and delete its data files to simulate a disaster
  * Restore the database with “sudo -iu postgres pgbackrest --stanza=[stanza_name] --delta restore”



 **Referenced Works:**

[1] https://pgbackrest.org/

[2] https://www.crunchydata.com/blog/how-to-get-started-with-pgbackrest-and-postgresql-12

[3] <https://www.postgresql.org/docs/current/wal-configuration.html>

[4] <https://pgbackrest.org/configuration.html#section-general/option-process-max>

[5] <https://pgbackrest.org/user-guide.html#installation>

* * *

  
Stay connected with Command Prompt. Subscribe to our Substack Newsletter [here](<https://cmdpromptinc.substack.com/>).

##  **Need Help?**

Command Prompt is the world’s oldest dedicated Postgres services and consulting company, offering expert support for performance optimization and troubleshooting. [Contact us today.](<https://www.commandprompt.com/contact-us/>)

---
[View this page online](https://www.commandprompt.com/blog/getting-started-with-pgbackrest-perform-your-first-backup/)

---

# The Importance of Language

> After a short walk in the late afternoon sunshine, I found myself praising my noble steeds who come with me almost everywhere; aka my frenchtons. Moose, I’d ar…

After a short walk in the late afternoon sunshine, I found myself praising my noble steeds who come with me almost everywhere; aka my frenchtons. Moose, I’d argue the most sweet and stubborn frenchton, has Intervertebral Disk Disease (IVDD). This means most of what he does has to be monitored carefully as it takes more out of him and can lead to serious injury. It also means he and I connect on a deeper level as I too know what it’s like to have chronic pain and fatigue.

I try to make sure that I always give them praise when we’re active and out doing things, but especially on days when I notice that he is in pain. We exercise for our well being and as physical therapy for both him and I. As much as sometimes we’d prefer to couch [verb], we more often than not are walking somewhere.

Today out of my mouth came, “You have no idea what I’m saying, but I do, and that matters.” Meanwhile, my noble steeds wondered if another treat was on the horizon or if they’d have to “starve” until dinner.

As I said that, it really dawned on me how important language is in our everyday life. When I use positive words, even if they are clouded by the stress of the week/month/year, I unintentionally create a space of safety and calm. When I berate myself, I become reactionary, angry, and add to the wrinkles on my forehead. This may seem obvious but how often do we let our negative thoughts take over our mind? How often does one bad thing happen and we allow the rest of our time to be affected by it? When we intentionally choose encouraging words for ourselves and others, we create a culture of reciprocity. Those around us are less likely to be negative if we are being positive.

The sad fact is that almost everyone I’ve met has a prominent demon on their shoulder. The demon whispers self sabotaging, rude, judgmental, demeaning things into our ears and we wonder why we’re not happy. While everyone’s antidote for this is different, we can all relate by taking a step back when we’re interacting with someone and consider their demon. We don’t know what its particular problem is, but imagine what yours puts you through.

 _You’ll never be good enough._

 _You’ll never provide enough to make them happy._

 _You’re too fat for love._

 _You’re stupid._

 _You made yet another mistake._

 _No one will love you._

Now imagine if we said those things to those we love the most. In this case, my noble steeds who walk with me anywhere. You’d think I was a monster, and so would I. There’s absolutely no reason for it.

Yet we’re willing to do it to someone vastly more important than my dogs: ourselves. We walk around with these thoughts, using this judgmental language that emotionally beats ourselves into the ground. No wonder we constantly need distraction and a dopamine hit via instant gratification. We’re doing everything we can to not hear our demons at full volume. When we have no distractions, we are alone with our thoughts. That can be a terrifying experience, especially after years of letting _busyness_ run our life.

Unfortunately and fortunately, we’ve got to face the music and sit in our thoughts. It can be unpleasant, and stink of unresolved stress, but through the murky waters is a light that brings true peace and freedom.

Self compassion.

According to [Kristin Neff](<https://self-compassion.org/>), the Self Compassion Goddess, self compassion looks like this:

> “We are kind and understanding rather than harshly self-critical when we fail, make mistakes or feel inadequate. We give ourselves support and encouragement rather than being cold and judgmental when challenges and difficulty arise in our lives. Research indicates that self-compassion is one of the most powerful sources of coping and resilience we have available to us, radically improving our mental and physical wellbeing. It motivates us to make changes and reach our goals not because we’re inadequate, but because we care and want to be happy.”

Who doesn’t want to experience that?!

Noticing the language we use is the first step. How do we speak to our loved ones, our colleagues, and ourselves? Are we kind and considerate or judgmental and damaging? Do we give the benefit of the doubt or react based on impulse? Do we allow for rest or do we pass judgment when not constantly productive?

The language we use today impacts our future. It affects our life, our children’s lives, and those we meet on the road. It determines how we handle stress and trauma. It contributes to our decision making and what we do at a crossroads. Very simply put: change your language, change your life. It really is that impactful.

Sincerely,

A Disabler of Demons

—

An amazing read: [Self Compassion](<https://self-compassion.org/self-compassion-kristin-neff/>) by Kristin Neff.

---
[View this page online](https://www.commandprompt.com/blog/the-importance-of-language/)

---

# PgManage 1.0rc1 released

> PgManage 1.0rc1 released - an inch closer to being a mile ahead

Release Candidate 1 of PgManage is now available!

##  **Release Notes**

  * New features:
    * New welcome screen which displays app shortcuts and recent connections list
    * Added "run selection" feature in the query editor
    * The autocomplete setting is now stored separately for each DB connection
    * Added SQLite3 support in the table editor
  * Major Bugs fixed:
    * Various layout fixes on the snippets panel
    * Fixed memory leak in snippets panel tree view
    * Fixed PostgreSQL binary path corruption when pigz binary path is changed in the settings dialog
    * Added snippet and snippet folder name validation
    * Added CSV delimiter validation in app settings
    * Multiple fixes in the Getting Started wizard
    * Fixed query editor re-focusing when autocomplete widget closes
    * Added connection group name validation
    * Fixed disabled DB connection string input when creating a new connection
  * UI/UX Improvements:
    * Slightly improved app startup speed
  * Other changes
    * Improved error handling when app back-end is down or unavailable due to network issues
    * Application data grids migrated from Handsontable to Tabulator.js
    * Updated Vuejs and Bootstrap libraries



Binaries

  * [Linux](<https://link.sbstck.com/redirect/9ee3383e-cf18-4e6c-bda4-b6b034b40bbf?j=eyJ1IjoibmdzZjcifQ.l9TdRumhYeoXZIOuPk3sqXHPiZoDDAJof5YzLMxgT9g>)
  * [Mac](<https://link.sbstck.com/redirect/bc42836e-ed2f-4181-8a7a-c6238f731c98?j=eyJ1IjoibmdzZjcifQ.l9TdRumhYeoXZIOuPk3sqXHPiZoDDAJof5YzLMxgT9g>)
  * [Windows](<https://link.sbstck.com/redirect/db6bc9e9-7d6c-4461-9727-77c97b991242?j=eyJ1IjoibmdzZjcifQ.l9TdRumhYeoXZIOuPk3sqXHPiZoDDAJof5YzLMxgT9g>)



Source:

[https://github.com/commandprompt/pgmanage](<https://link.sbstck.com/redirect/82ee4d42-b2ef-4d78-832e-dc528d356b4a?j=eyJ1IjoibmdzZjcifQ.l9TdRumhYeoXZIOuPk3sqXHPiZoDDAJof5YzLMxgT9g>)

Bookmark our PgManage page for updates and new release information.

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-10rc1-released/)

---

# Embrace Creative Living

> “The universe buries strange jewels deep within us all, and then stands back to see if we can find them. The hunt to discover those jewels––that&#x27;s creative liv…

> “The universe buries strange jewels deep within us all, and then stands back to see if we can find them. The hunt to discover those jewels––that's creative living.”

> ― **_Elizabeth Gilbert, Big Magic: Creative Living Beyond Fear_**

A couple of years ago I was at Huntington Beach State Park in South Carolina pacing up and down the path to the beach. I was talking to my therapist and out came the revelation that I wanted to be a coach. I had previously been hesitant to bring it up to anyone because when I discussed it with my other half, he responded with the stark reality that I had no time for it - being a CEO and all. I was crushed. My therapist said I should go for it. I was elated. Following that call, I got my headphones, turned on some music, and literally danced in the ocean. 

Yes, everyone on the beach thought I was crazy.

For the first time in my life, _I didn’t care_.

It took two years and the onboarding of my other half before I put myself out there and applied to Duke Medical School. They have one of the most respected Health & Wellbeing Coach trainings. By some miracle I was admitted and it has changed my life. 

Lately I’ve found myself thinking about the fact that prior to enrolling (and even afterward) I was terrified. While college had its moments of intimidation, most of it was academic - not real world application. With Duke, not only did we have to apply what we learned immediately, in front of established coaches; we also had to continue to prove ourselves to mentors. I didn’t know if I could do it - it was very much a “take it day by day and pray” situation. In less than a year I went from not knowing how I would coach for five minutes to coaching for hours at a time. 

There are moments in life we are called to something - a job, a location, a new beginning, a creative pursuit. Often we turn it down because it doesn’t fit into the comfortable box we’ve built for ourselves. Recently I picked up the book _Big Magic: Creative Living Beyond Fear_ by Elizabeth Gilbert. She says that we all need something that isn’t work to fuel our creative side. And for the human givers of the world, she also states that it shouldn’t be for the benefit of someone else - it should be 100% because it makes us happy. She wrote _Eat Pray Love_ for herself, not anyone else. 

So I went from a woman dancing on a beach thinking that one day I’d live that creative passion, to a Duke trained health and wellbeing coach - and what’s more: a much better human. Duke taught me more than how to be a good coach - they also taught me the beauty behind non-judgement, how to genuinely listen, how to acknowledge others, and how to create space for others to be their authentic selves. It didn’t fit in my box and it took away from everything I thought was higher priority, yet it made me the best version of myself I have ever been. 

> “Be the weirdo who dares to enjoy.”

>  _―_ ** _Elizabeth Gilbert_**

## Our callings should not be ignored.

We have passion for a reason. It may not be convenient and certainly push us out of our comfort zones, but the end result is often so much more rewarding than the daily grind. That isn’t to say, “go quit your job and become a painter.” Even Elizabeth Gilbert kept her day job after being published numerous times. She’s taught me that our creative endeavors shouldn’t pay for our living - instead, they should bring us joy and willingness to live intentionally. 

What is your passion? What is the creative thing you love to do that you lose a sense of time while doing? What recharges you? 

> “You can measure your worth by your dedication to your path, not by your successes or failures.”

> ― **_Elizabeth Gilbert_**

I encourage you to take one step toward that today. Or go pick up [_Big Magic_](<https://www.elizabethgilbert.com/books/big-magic/>). 

Sincerely,

A dancer on beaches

---
[View this page online](https://www.commandprompt.com/blog/embrace-creative-living/)

---

# How to Set Yourself Up for a Successful Meeting

>  There are a lot of mugs out there that say “I survived another meeting that should have been an email.” We’ve all been there, and more likely than not we have…

There are a lot of mugs out there that say “I survived another meeting that should have been an email.” We’ve all been there, and more likely than not we have also facilitated meetings that others may throw in the “should have been an email” bucket. We’re busy and it happens. Meetings are constant, burdensome, and necessary. As a fellow survivor and bucket avoider, I’ve put together a few simple tips to ensure your meetings have more ROI. 

### Define What Success Looks Like

Prior to the meeting, and preferably before scheduling the meeting, take a few minutes to really assess what you need to get out of the meeting. Is it a decision to be made? Is it feedback from the team? Is it simply for others to hear you? Is it an agreement from the other party? Is it to resolve a conflict? It is most productive for a group to know what the goal is. Then everyone is able to work toward completion, even if it may not be an easy topic. The most effective way to ensure everyone is on the same page is sending out an agenda beforehand.

### Have a Plan B

While we’d all like to believe that a meeting will give us what we need, we need to be prepared that it may not. Attendees may be distracted, tired, or not in the right mindset for the discussion. Pivoting and adapting may be required. In productive environments, this can be done gracefully and honestly. A statement as simple as, “Considering where our team is coming from today, we’d like to pivot a little bit,” can let team members know they are being listened to and the decision or discussion can be had at a time that better suits everyone. Previously defining what topic is a successful plan B enables you to come prepared for success even in the event that plan A isn’t achievable. 

### Take a Minute

A few minutes before the meeting, shut down everything else. That includes the phone, all the open tabs, and any paperwork. Close your eyes if you need to. The goal here is to be mindful and present. Check in with yourself. Are you nervous? Stressed? Frustrated? Name what you are feeling and try to tune into your breathing. Breathe in, and as you breathe out, let go of the stressors you are bringing into this meeting. They’ll be there when you get back, believe me. Taking this moment to let the weight you’ve been carrying around all day slip from your mind enables you to go into the meeting focused and intentional. Reactivity reduces and projecting can be limited. 

### Pause

In our striving for efficiency and not wasting anyone’s time, we have lost the art of listening. We listen with the intent to respond, not to genuinely hear what the other person is saying. Pausing may seem like a dumb simple concept but think back on the last half dozen meetings you’ve been in. How often was there appropriate silence? How many times have you jumped in impulsively because the silence that was there made you feel uncomfortable? Despite our habitual quick response time, pausing is the best way to take a moment to think about what was said and how we want to respond. This isn’t necessarily about being politically correct as much as it is about checking in with ourselves. Is what you are responding with what you actually want to say or is it to keep things going? On the flip side, allowing people the opportunity to pause before they speak reinforces having value in what they have to say. 

### Summarize & Show Gratitude 

When closing the meeting, take a moment to summarize what was decided and discussed. If there are action items, make sure those are repeated and written down so there is no confusion on who is doing what. Afterward, genuinely thank the attendees of the meeting for their input and/or time. It may be a mandatory meeting, but everyone’s presence deserves to be appreciated. Gratitude instills value and lets the group know that it may have been easier to just send out an email, but instead we wanted to hear the person or even possibly see them. We wanted to be human together in a time of more and more screens. 

### Evaluate the Outcome

After the meeting, assess what the real outcomes of the meeting were. Did you meet your previously defined success metric or not? What contributed to that result? Was there another beneficial outcome you didn’t consider? Also include the outcome for others. Was their time used appropriately? Were their opinions solicited and given due consideration (if applicable)? This is a great opportunity to learn from the experience and make any changes for future meetings to ensure your teammates don’t give each other mugs or memes saying they survived.

### Bonus Tips

For a lot of us, meetings are the most stressful thing we do. Thinking on our feet in such a fast paced world while trying to be prepared for a variety of reactions can send us into fight or flight. If meetings cause you stress, here are a few tips to try:

  * Work out beforehand. Twenty minutes of lifting weights, going for a run, or yoga fills your body with endorphins, which is helpful for completing the stress cycle and brings you into an equilibrium, reducing the associated reactivity. For more information about completing the stress cycle, I highly recommend the book[ _Burnout_](<https://www.burnoutbook.net/>) by Emily & Amelia Nagoski. 
  * If you aren’t required to be in the office or in front of a screen, take a walk during the meeting. Like working out beforehand, moving your body during a call can allow for less “what ifs” and instead focusing on the question or discussion as directly as possible. It also reduces the likelihood to tune out, as odd as that sounds, because we are more inclined to care about the meeting when we are able to do something beneficial for us at the same time.
  * Meditate. If you are able to take more than a moment to get into the right mindset, listen to a meditation or calming music for half an hour. The key here is to not obsess about the meeting - instead, let your thoughts and stresses go. You’re already prepared - take the time to rest and recharge.



Taken individually or collectively, these tips should help you facilitate more productive meetings for all. 

Thanks for reading and happy meetings!

~Amanda

---
[View this page online](https://www.commandprompt.com/blog/how-to-set-yourself-up-for-a-successful-meeting/)

---

# Get back on that horse

> A few years ago I was diagnosed with a variety of conditions that came with the term “chronic.” Throughout the grief process, my partner encouraged me to write…

A few years ago I was diagnosed with a variety of conditions that came with the term “chronic.” Throughout the grief process, my partner encouraged me to write about it. It was uncomfortable to be publicly vulnerable in a professional world where “weakness = bad.” I sat there knowing logically that vulnerability was a sign of strength, but the risk adverse [read: scared] side of me still wasn’t convinced. How could a young professional, a woman in tech more specifically, be seen as strong and reliable when openly talking about her “limitations?” What future opportunities was I cutting myself out of before even having a chance to see them?

In spite of the doubt and fear, there was a deep sense of obligation. Millions of people have rare diseases, invisible diseases, are neurodivergent, or have disabilities and are discriminated against for being different. So I put together content, I talked to my team openly, and I became fond of wearing a [zebra](<https://www.ehlers-danlos.com/why-the-zebra/>) onesie (despite never being a onesie-wearing person). I started down the advocate path.

And then I received an email from a coworker that attributed the lack of clients or new job applicants to the fact that we were putting out content about wearing aforementioned onesies as a professional company. After all, what in the world does rare disease awareness have to do with building a Postgres and Open Source services firm? Was I reducing the perceived value of the company?

The support I received in response from my partner and other team members was significant. We have always been a people first organization. They said that what I was doing was being brave and demonstrating a need for meeting people where they are instead of treating everyone like robots. I bought into this on the surface level. Then I stopped publishing.

I continued to write, but the passion was gone. The obligation was replaced by the strong belief that no one would get anything out of what I wrote, that I was doing the company a disservice, and I should instead rededicate myself to being a workaholic. Drafts were left in my review pile; lists of article topics to research and work on were ignored.

Two years have gone by since I last published an article. Laughably, it was titled, “[We’re All in This Together.](<https://commandprompt.com/blog/were-all-in-this-together/>)” Within that article, I opened up in a way that makes the risk-adverse side of me cringe. On the flip side, I am encouraged by my past self. She faced her fear, gave it the finger, and hit publish.

Fast forward to today.

I am a Duke Medical School trained Health & Wellbeing Coach, and the most fulfilling moments of my days are when my clients face what they thought was impossible and see that they have strengths they have never acknowledged. The deep mental transformation that happens when you go from fearing something to accepting it as it is and working with it instead of against it is profound. When we tiptoe around our limitations, that in itself becomes a chronic debilitation.

I’m realizing that avoiding being vulnerable in a professional setting is right up there too. The last line of “We’re All in This Together,” is _Don’t forget that we’re all going through something - some are just more visible than others._ I am proud to be the CEO of a company that encourages individuals to be themselves and share their vulnerabilities. I am disappointed that I let fear discourage my willingness to open up further. I find myself spending more time bringing my coaching skills into my CEO role, and with it comes great discomfort. The discomfort is due to uncomfortable conversations, hard decisions, and great responsibilities. The beauty in all of those things is that growth and healing is found within the discomfort. We are most effective as a team and as a people when we are open, transparent, and work together toward the same goal of providing a good living for everyone involved. That comes with understanding people’s unique circumstances. Brene Brown writes:

> “We desperately need more leaders who are committed to courageous, wholehearted leadership and who are self-aware enough to lead from their hearts, rather than unevolved leaders who lead from hurt and fear.”

And because there’s no way I can leave this one out:

> “Write a new ending for yourself, for the people you’re meant to serve and support, and for your culture.”

Guess I need to get back on that horse.

Thanks for reading my rambles.

Sincerely,

Amanda

CEO, Coach, and Spoonie

---
[View this page online](https://www.commandprompt.com/blog/get-back-on-that-horse/)

---

# Embracing Wellness: Our Journey Begins

> Embracing wellness our journey begins

At Command Prompt, our commitment to creating a thriving open-source technology ecosystem extends beyond code and software. We recognize that true success and innovation come from fostering the well-being of our team members and the communities we serve. That's why we are thrilled to announce the launch of our comprehensive Health and Mental Wellness campaign.

##   
Why Wellness Matters

In the world of technology, it's easy to become engrossed in the intricacies of coding, troubleshooting, and rapid development. This is why a holistic approach to wellness is essential for driving both personal and professional growth. Our mission is not just to excel in our field but to lead fulfilling lives, nurture strong minds, and support diverse voices in an inclusive environment.  


## What to Expect

Our Health and Wellness Series is a platform that encompasses four crucial dimensions of well-being:

  1.  **Health & Mental Wellness:  
** In a world where stress and burnout are common in the tech industry, we are committed to helping our team members achieve balance and inner peace. Our content will cover physical health, mental well-being, self-care, stress management, and mindfulness practices. You can look forward to expert insights, practical tips, and personal stories to guide you on your journey to better health and mental clarity.
  2.  **Professional Development:  
** At Command Prompt, we believe that the growth of individuals drives the growth of our organization. We'll offer tips, suggested reading, and podcasts that focus on leadership skills, effective communication, career advancement, and personal development. It's our way of empowering you to become the best version of yourself, both personally and professionally. It's also why we host an Education blog dedicated to Postgres with several hundred articles and guides.
  3.  **Neurodiversity:  
** We embrace the unique talents and perspectives of every individual in our diverse team. Our neurodiversity content aims to promote understanding, appreciation, and support for individuals with varying neurological traits. We'll share the ways that we make our workplace more inclusive, fostering an environment where everyone can thrive.
  4.  **Community Involvement:  
** We are not just a company; we are an integral part of a broader community. Our commitment to social responsibility extends to our community involvement projects including the nonprofit [Postgres Conference](<https://postgresconf.org/>) series. We will discuss ways to give back, support local initiatives, make a positive impact, and create meaningful connections. Join us in creating a brighter future for our communities, alongside your open-source contributions.  
  




## Join Us in This Wellness Journey

Keep an eye on our blog, follow us on social media, and engage with our internal resources such as our On the Flip Side podcast as we unveil our Health & Mental Wellness campaign. We are excited to bring you valuable insights, stimulating discussions, and practical advice. Let's embark on this journey together, as we strive for personal and collective growth in the realms of health, professional development, neurodiversity, and community involvement. Stay tuned for our upcoming wellness content!

---
[View this page online](https://www.commandprompt.com/blog/embracing-wellness-our-journey-begins/)

---

# An act of kindness for the PostgreSQL community

> Since at least 2021 there has been a disagreement between Postgres related non-profit organizations. On one side are two affiliate non-profits for Postgresql.o…

Since at least 2021 there has been a disagreement between Postgres related non-profit organizations. On one side are two affiliate non-profits for Postgresql.org; on the other is a relatively unknown non-profit out of Spain. Lines have been drawn, feet have dug in, and a lot of unproductive discourse has occurred. This has culminated in legal action, bad blood, and some poor decisions. 

As one of the Founders of United States PostgreSQL, a former Director of Software in the Public Interest (one of the NPOs behind Postgresql.org), a former committer (web), former major contributor, President of the [oldest PostgreSQL company](<https://commandprompt.com/>) still independent in North America, and the Founder of [Postgres Conference](<https://postgresconf.org/>) (in the U.S.), I thought I would offer a knowledgeable perspective. 

I have had long discussions with one of the primary people within the Fundacion PostgreSQL (Alvaro) and his heart is in the best interest of the community, even if Postgresql.org, PGEU and PGCAC do not agree. You can see this demonstrated within Fundacion’s [trademark policy](<https://postgresql.fund/trademarks/>). That said, Fundacion PostgreSQL did go about their actions in an incorrect way. There should have been an open discussion and they should have provided PGCAC the opportunity to resolve the trademark issues on their own. It is also true that while I believe PGEU and PGCAC believe they are protecting the community, if they were interested in positive community growth and collaboration, they would not be taking the approach they currently are. The current path has far reaching implications that PGEU and PGCAC do not see.

Further, the PostgreSQL Community Association of Canada and Fundacion PostgreSQL have resorted to terrible language in representing what is actually going on within the disagreement. Using language such as, “An attack on our community” or “PostgreSQL attacks the community” is immature at best and at worst an intentional decision to use good faith and mindshare against what is largely just a disagreement that could be solved with an active mediator and a few phone calls. If this disagreement is about the best interest of the PostgreSQL community, shouldn’t that involve discourse, honesty, transparency, and kind communication?

## Some facts:

  1. The first appearance of a PostgreSQL trademark outside of Canada wasn’t until 2018.
  2. The trademark PostgreSQL in the European Union was [not registered until 2018](<https://euipo.europa.eu/eSearch/#details/trademarks/017894441>).
  3. The trademark in Canada was registered in 2003 (filed in 1999).
  4. The trademark in Canada [does not accurately represent PostgreSQL](<https://ised-isde.canada.ca/cipo/trademark-search/1017132>) as the services it was registered under are:



(1) Internet consulting.

(2) Internet presence provider- DNS hosting.

(3) Commercial internet support for database applications development and implementation including the ability to host internet domains (as an internet service provider) and provide a wide range of web site development, programming and information technology services, namely computer software architecture, design and/or development services.

(4) Computer hardware sales and service.

## The solution

The solution to the whole problem is simple; a single contract that states:

  1. That the term PostgreSQL is trademarked by the PostgreSQL Community Association of Canada
  2. That the Fundacion PostgreSQL relinquishes all property and rights to the mark PostgreSQL held in Spain and assigns them to the PostgreSQL Community Association of Canada
  3. The PostgreSQL Community Association of Canada forgoes any punitive damages or secondary costs
  4. That the Fundacion PostgreSQL forgoes any punitive damages or secondary costs



The contract should not contain language in regards to future potential filings that involve but are not exclusive to the word _Postgres_ or _PostgreSQL_. There are already a number of filings worldwide that use Postgres or PostgreSQL as part of an overall mark inclusively such as _Postgres Pro_ , _Postgres Plus_ , _Postgres Always On_ and _Postgres Enterprise Manager,_ all of which are not owned but PGCAC or PGEU.

## Why forgo punitive damages or secondary costs

Because it is the right thing to do. Otherwise this whole affair is going to end up costing one entity or another way too much money for no purpose. There is no clear distinction on who would legally win, and in either situation the main sufferers are the PostgreSQL community. Let’s have the parties show an act of kindness for the betterment of everyone involved.

---
[View this page online](https://www.commandprompt.com/blog/an-act-of-kindness-for-the-postgresql-community/)

---

# Courtesy Notification: CVE-2020-21469 PostgreSQL 12.2 Security Vulnerability

> This is a courtesy notification to our clients and community regarding an alleged security issue for PostgreSQL 12.2.The following issue was reported as CVE-20…

This is a courtesy notification to our clients and community regarding an alleged security issue for PostgreSQL 12.2.

The following issue was reported as [CVE-2020-21469](<https://www.cve.org/CVERecord?id=CVE-2020-21469>):

> An issue discovered in PostgreSQL 12.2 allows attackers to cause a denial of service via repeatedly sending SIGHUP signals.

 **This is not a security vulnerability** , and was filed without prior knowledge of or consultation with the PostgreSQL Security Team as reported in [this news release](<https://www.postgresql.org/about/news/cve-2020-21469-is-not-a-security-vulnerability-2701/>).

To cause a denial-of-service issue in an PostgreSQL 12.2 instance, an account would require explicitly granted elevated privileges, including:

  * A PostgreSQL superuser (postgres)
  * A user that was granted permission to execute pg_reload_conf by a PostgreSQL superuser
  * Access to a privileged operating system user



Following best practices for user privileges and information security will prevent this occurrence. To learn more about known PostgreSQL security vulnerabilities and the related patches for all versions, [visit this page](<https://www.postgresql.org/support/security/>).

As always, we recommend that you upgrade to the most recent supported minor release because of other security and bug fixes.

If you are running version 10 or less of PostgreSQL, note that it is End-of-Life (EOL) and we recommend that you upgrade to a supported version. If you need help maintaining an EOL version, reach out to us for extended support. Find out more here or contact us today!

---
[View this page online](https://www.commandprompt.com/blog/courtesy-notification-cve-2020-21469-postgresql-security-vulnerability/)

---

# An update on the hunt for 195

> On July 6th, I published, “A Transparency Moment”. There are a lot of us who would never publish such an article. ‘Your health is private,’ ‘won’t you be embar…

On July 6th, I published, “[A Transparency Moment](<https://www.linkedin.com/pulse/transparency-moment-joshua-drake>)”. There are a lot of us who would never publish such an article. ‘Your health is private,’ ‘won’t you be embarrassed,’ and ‘what if you fail?’ These are nagging thoughts and they are constant. ‘Should I publish another update?’ ‘What if I don’t make progress?’

## Your health is private

While I accept the premise that sharing your ‘weakness’ with family and especially the general public is difficult, I reject the assumption that it is a bad idea. The harsh reality of being fat is that it is a weakness. You are showing weakness in self-control and an inability to manage yourself. That isn’t to say that the weakness isn’t without reason: depression, socioeconomic conditions, genetics and any number of other challenges can affect your success in losing weight.

It is to say, being public with your troubles, your weaknesses, and successes is an opportunity to show strength, inspire others, receive accountability and maybe even pay it forward.

## What if you fail?

The only result of the pursuit of perfection is failure. You are going to fail every day at something. Why not document and publish your trials, your failures, and your successes? Why not provide an opportunity for someone to say to themselves, “I identify with this person's struggle, I am going to try too.” One should never fear failure; we should fear not trying.

## August 6th

My weight on August 6th was 225 lbs. That is not quite as low as I was hoping (220) but the whole of July was up and down with the ability to exercise between weather, physical limitations (ankle), and just in general life getting in the way. That said, it is yet another 5lbs down from the weigh in on July 6th, and 15lbs down from June 6th. That’s progress. I will assess my current progress and call it a win. Maybe it is a silver medal and not a gold but damn,[ I am in the competition](<https://www.theodorerooseveltcenter.org/Learn-About-TR/TR-Encyclopedia/Culture-and-Society/Man-in-the-Arena.aspx>).

## What’s the data?

I continue to eat less meat, more vegetables, and less carbs. I eat out a lot less, drink less alcohol and exercise more. Since June 6th I have averaged 6950 steps a day. I am still working on getting that above 10,000. My less than stellar ankle makes that difficult. That being said, averages don’t tell the whole story. I have averaged 3.5 miles per day (since June 6th). The goal is more toward 5 miles per day. I would challenge every reader of this post to consider setting a goal of 5 miles per day.

## What’s next?

Winter is coming.

That means rain, sleet, snow, cold weather, angry arthritis, seasonal affectiveness disorder and a lack of vitamin D. It also means I am going to move back into our school bus and snow bird. Utah, the South, and the Southwest. The hope is to take advantage of the great weather to be able to hike year around, at least twice a week and of course, walk every single day. Success requires discipline. I am working on it.

Tl;dr;

  1. <https://youtu.be/trz7g-wilxs?si=lJVNLlyN_U3f9FXT>
  2. <https://youtu.be/tbnzAVRZ9Xc?si=FcW7BuWHB5buZ9YU>

---
[View this page online](https://www.commandprompt.com/blog/an-update-on-the-hunt-for-195/)

---

# PgManage 1.0b2 released

> PgManage 1.0b2 released.

## New features:

  * ability to disable CSV header when exporting data grid contents
  * added UI for Postgres extension management
  * new hierarchical connections menu
  * use random TCP port number for the application back-end process so Pgmanage does not occupy ports commonly used by other applications
  * ability to select SSL connection options in Connection Management dialog
  * remember and restore application window position and size when the app starts
  * added configurable date/time display format in the application settings dialog
  * restore the last used database and query tabs when pgmanage starts



## Major Bugs fixed:

If the query entered by the user contains explain keyword, clicking on explain/analyze button will no longer prepend the query with an extra explain keyword (previously this bug resulted in syntactically incorrect query)

## UI/UX Improvements:

  * ability to work with multiple databases within a DB session without needing to select the "active" database
  * if query entered by the user contains explain keyword, the explain tab will be opened automatically when user clicks the "Run query" button
  * explain and analyze buttons are now grouped together and separated from other query buttons
  * pre-set database connection TCP port in the Connection Management dialog based on selected database type
  * add visually matching themes for query editor



## Other changes:

  * django has been updated from 2.2 to 3.2
  * bundled python version changed from 3.8 to 3.9
  * code clean-up and refactoring
  * moved application shared data into globally accessible Pinia store
  * replace cx_Oracle library with oracledb



### Get Pgmanage:

  * [Downloads](<https://commandprompt.com/products/pgmanage/>)
  * [Source](<https://github.com/commandprompt/pgmanage>)

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-10b2-released/)

---

# PgManage 1.0b released

> Command Prompt is pleased to announce PgManage version 1.0b. This release adds two major features, 3 major bug fixes and over a dozen changes and improvements.…

Command Prompt is pleased to announce PgManage version 1.0b. This release adds two major features, 3 major bug fixes and over a dozen changes and improvements. PgManage is a Postgres centered multi-database management Open Source project.

## New features:

  * Added backup/restore support for PostgreSQL
  * First version of PgManage Handbook was published to https://pgmanage.readthedocs.io/en/latest  




## Major Bugs fixed:  


  * Fixed .AppImage compatibility issues for newer Linux distributions which do not have libcrypt installed
  * Added logic to terminate stale back-end process if the front-end process crashes
  * Fixed application UI process memory leaks  




## UI/UX Improvements:  


  * Improved support for configuration options search in Postgres Server Configuration Management
  * Automatically readjust query editor font size when the application font size changes
  * Various application layout and UI improvements
  * Limited minimum application window size to 1024x766
  * Fixed splash screen flickering/position issues during the application startup
  * Added PgManage Handbook links to application error modal dialogs
  * Improved handling of drag-and-drop reordering for database operations tabs  




## Other changes:  


  * Added support for configurable PostgreSQL Client binary path in application settings
  * Excluded SASS libraries and .sass files from the release builds
  * Included EGL/GLES libraries into app release builds
  * pev2 upgraded to v1.7.0
  * Removed "plugins" and other obsolete menu items from the application UI
  * Removed unused files and dead code from the project
  * Shred SSH keys stored in the app during the Master Password Reset  




## Getting PgManage:  


  * [Source](<https://github.com/commandprompt/pgmanage>)
  * [Binaries](<https://commandprompt.com/products/pgmanage/>)



##

---
[View this page online](https://www.commandprompt.com/blog/pgmanage-10b-released/)

---

# Your work-life balance is killing you

> Your Work Life balance is killing you

By Joshua D. Drake and Amanda Nystrom

This is not yet another article where someone informs you that you need better balance in your life or you’re going to burnout and fall apart. We all know we have to have balance. We all know that the personal side of the stick tends to end up with more mud/shit on it than the work side because the work side allows us to do all the personal things and keep roofs over our heads. So instead of telling you what you already know, we wanted to propose a new way of thinking about the whole thing (Because quite frankly - if someone says work-life balance to me one more time, someone is going to become the meme where the computer gets thrown out the window.)  
  


The definition of Work-Life balance from Wikipedia is:

>  _Work-life interface is the intersection of work and personal life. There are many aspects of one 's personal life that can intersect with work including family, leisure, and health. Work–life interface is bidirectional; for instance, work can interfere with private life, and private life can interfere with work._

 _  
  
_

Let’s consider the language we are using. When we use the phrase “work-life balance,” we are inevitably giving precedence to work over life. When we put work first, it creates an implicit battle between what we usually feel is more important (life) and what societal pressure says should be our primary focus (work).

The conflict that is created from putting the word “work” first presents a cognitive dissonance between the opportunity of work and life. It creates frustration with family needs, work requirements that affect home life, personal needs, vacations, friends and everything in between. Instead of celebrating and creating a positive inclusivity of the differences, the language of “work-life balance” fights to keep these important facets of your life separate.  
  


> When was the last time you took a day to not do anything and didn’t feel guilty about it? The need to be constantly productive is not a natural thing - it is a toxic demand that stems from consumerism and [the “laziness” lie](<https://offtheclockpsych.com/230-the-laziness-lie/>).  
>   
> 

## A change in perspective

To be truly successful in life, we must have an equilibrium. We must balance desire, learning from success and failure, fear, exhaustion, passion, employer satisfaction, relationships, children, personal ambition and growth, tee-ball games, disappointment, ballet classes, illness, client management, and unexpected events. How can we manage all of these tasks when we try to put everything into two separate boxes? We can’t and that is why people get burned out.  
  


## Life Balance

A life balance exists when we embrace everything in our life, for good or bad, hard or extra hard. A balanced life includes work; it is part of everything we do. It is work to have a good relationship with a friend, partner, or family member. It is work to schedule time for the kids' sports games or keep the house clean. It is work to make sure we perform in our career. It is work to become a better person. If all of these things are work, then how can we have a work-life balance? How can work be separated from our life as a whole?  
  


## Moving forward

While it is true that sometimes our work that comes with a paycheck takes more from our family than it should, our family is capable of doing the same. The key is this: We are the ultimate project manager when it comes to our life. It is up to us to be able to say no, to communicate our needs, and to set boundaries. It is up to us to be leaders of our life and make sure we’re in the right jungle instead of letting others make that decision for us. We must demonstrate our values and show authenticity in order to find a path that is truly rewarding. It may seem crazy or completely against the mold, but that’s why it’s a mold and not a supply chain. Be present in every part of your life now before your work-life balance kills you.  
  


## PS

It is not the purpose of this article to discount the difficulties that can arise when trying to manage a life. There are bad employers, unfortunate circumstances, and days when we feel terrible. Life can often not live up to our expectations and that is why _life is work_. It is impossible to separate the two. It is, however, possible to start making changes now that support the life you want. Take a moment to listen to “[On the Flip Side](<https://commandprompt.com/about/on-the-flip-side/>)” which discusses the importance of the [7 Habits of Highly Effective People](<https://www.amazon.com/Habits-Highly-Effective-People-Powerful/dp/1982137274/ref=sr_1_1?keywords=7+habits+of+highly+effective+people+paperback&s=books&sr=1-1>).

---
[View this page online](https://www.commandprompt.com/blog/your-work-life-balance-is-killing-you/)

---

# Announcing PgManage 1.0a

> PgManage is a Postgres centered multi-database management Open Source project. It is a fork of the previously well received project OmniDB that had been abando…

PgManage is a Postgres centered multi-database management Open Source project. It is a fork of the previously well received project OmniDB that had been abandoned. Command Prompt has taken the helm of this project to ensure a quality project focused on the Management of PostgreSQL and related technologies.  


  * Source: <https://github.com/commandprompt/pgmanage>
  * Website and Binaries: <https://commandprompt.com/products/pgmanage/>
  * Full Documentation: <https://pgmanage.readthedocs.io/en/latest/>
  * Community: <https://discord.gg/FvweAhhUeu>  
  




## Major Changes from OmniDB  


### New features:  


  * new connection management UI
  * added support for postgres server configuration management
  * new explain/analyze UI powered by pev2, including pev2 dark theme support
  * connection credential encryption
  * backported support for monitoring data-grid-based monitoring widgets
  * backported pie charts widgets for numbackends and database sizes
  * added password strength validation for user and master passwords
  * PostgreSQL 9.6, 10, 11, 12, 13, 14 and 15 support  




### Major Bugs fixed:  


  * fixed data export to csv/xls format in the desktop version of the app
  * added superuser permission check on all user management APIs
  * extra validations added to prevent creation of unnamed connection groups
  * fixed external links not working in the desktop variant of the app
  * fixed postgres special commands on postgresql versions 12 and higher
  * fixed broken postgres documentation links available in database tree view menus
  * made all web/cdn app dependencies local so pgmanage can work properly without an internet connection  




### UI/UX Improvements:  


  * reorganized connection management menus in the left menu bar
  * fixed DDL tab auto resizing
  * the top-right utilities menu now expands on click instead of mouse-hover
  * added ddl/properties tab resize limits to prevent it from becoming impossible to grab/resize back
  * unified tooltip appearance throughout the whole app
  * unified pictogram look and feel throughout the whole app
  * improved database tree view navigation by adding smooth scroll to the newly expanded tree node. previously when some tree view node was expanded it jumped out of sight
  * improved data grid/table readability
  * improved database entity tree view readability
  * fixed date formatting in sql command history grid
  * fixed date formatting in db console command history grid
  * proper styling for dialog primary and secondary buttons. the secondary buttons in forms and dialogs were previously looked disabled/grayed-out which was confusing.
  * the autocommit checkbox on query tab now stays visible despite of application window size removed the option to make connections public in desktop variant of the app (which has only one user so shared/public connections make no sense)  




#### Other changes

  * application data directory and db/log file naming was changed from omnidb* to pgmanage*.

---
[View this page online](https://www.commandprompt.com/blog/announcing-pgmanage-10a/)

---

# The issue of convenience

> Life is about people

Humans by their nature will seek things that make life easier and often do not consider the consequences. What is worse is that a lot of the convenience we seek is anything but and it guides the true cost to our health. Some of this cost is short term, others longer term and more difficult to ascertain ([think forever chemicals](<https://www.ewg.org/what-are-pfas-chemicals#:~:text=The%20'forever%20chemicals'%20in%2099,system%20harm%2C%20and%20other%20diseases.>)).

One of my favorite examples of this is coffee. People are in the constant search for the perfect, fast and easy cup of coffee. I have in fact found the perfect cup of coffee. I was in Austria presenting on PostgreSQL at the time. We were at the hotel and the complimentary breakfast had a coffee maker. This wasn’t just some Mr. Coffee. This was an Italian job that had a touch screen and I was able to select anything from Espresso to Cappuccino to Americano. Let me just say, I never knew a machine to make such a perfect Cappuccino, let alone a Barista. Nowadays, you can find these machines at any quality truck stop (Pilot, Loves, Sheetz).

## What is the cost of the perfect cup of coffee

There is definitely a material waste. These coffee makers are created from plastic, silicon and rare earth metals. They are computers with touch screens. They have the ability to heat and sense the perfect temperature and brew the perfect cup of joe. Then they break and if it can’t be fixed, it is just thrown away. They aren’t recycled, many of the parts aren’t recyclable. The company will just buy another one because: Humans seek the perfect cup of coffee. It is the very reason even many of my environmentalist (green) friends will say, “You can take my [Keurig](<https://www.usatoday.com/story/tech/2019/03/13/heres-why-your-used-k-cups-coffee-pods-arent-usually-recycled/3067283002/>) from my cold dead hands!”

## The cost to society

These conveniences, while a simple luxury, create a vacuum within our communities. While I touch a few buttons to have a machine brew the perfect cup to satiate my need for caffeine, I am missing out on something far more important:. The Barista and human interaction.

The Barista is the individual taking my order, creating through art and skill my coffee and having small talk. It might be just a hello, or through time it may be a conversation about how school, work or the kids are. We might form a bond and find out that they are a cabinet maker on the side, perhaps they are retired and who knows, they may become friends. A person you look forward to seeing each morning, or Saturday or whatever your routine may be.

This is why I love it when the [KOA](<https://koa.com/>) has free coffee. It is terrible coffee and I can make better coffee using my pour over. However, it isn't a better morning. I wouldn't make the connection with the people that made the coffee. We meet many interesting people on the road, all of whom have a story to be heard or told. We listen to them and they listen to us. We learn about each other and a social bond forms. This bond causes us to return to the same KOA more than once and the people remember us. To be fair it is usually because of [Intrepidus](<https://commandprompt.com/about/intrepidusvita/>) but that does not reduce the quality of the connection and the community being built.

## Where to now

Next time you are staring at a screen, consider the implications. What is it that you are missing out on? When was the last time you reached out to someone, said thank you to a complete stranger, or paid it forward? There are so many of us that are missing connection.. Connection is where we find community, identity, and happiness. It is how we are able to become the best versions of ourselves and deal with the hardships that life throws at us. Convenience can be great - but it can also remove something we as humans deeply need. Choose your conveniences wisely.

 **Tl;dr;** Life is about people.

---
[View this page online](https://www.commandprompt.com/blog/the-issue-of-convenience/)

---

# Top 3 Reasons to Upgrade PostgreSQL End-of-Life

> Top 3 Reasons to Upgrade PostgreSQL End-of-Life

Databases are a vital component of any application or website, especially with the reliance on data to meet our end users’ needs. PostgreSQL databases are robust and limitless in their capabilities but not when they’re operating like it’s 1999.

 **Do you have any outdated end-of-life (EOL) PostgreSQL instances?**

EOL software is especially prone to bugs and security issues, but scheduling and performing critical updates and upgrades can be challenging. The less complex factors are time and resources – not only whether you can schedule a maintenance window and staff, but whether you can have an outage or have staff experienced in making a major upgrade. More complex issues include how your database integrates into your infrastructure. Is it the core of your business functions, and there’s a fear that an upgrade to the foundation will bring the architecture crashing down?

Addressing end of life for databases can be challenging, especially as significant changes were made between 9.6 and higher versions of PostgreSQL. Successful upgrades involve dedicated time and resources for planning and testing.

We empathize with all of these concerns. However, if the primary reason is the old adage “if it ain’t broke, don’t fix it” - let’s outline the top reasons why you _should_ upgrade your PostgreSQL EOL instances.

## Lack of Features

Newer versions offer more features. The upgrade from 9.6 was so massive that the community decided to go to the next whole version of 10. Features included logical replication using publish/subscribe, declarative table partitioning and improved query parallelism.

PostgreSQL 12 contained major innovations, including JSON path queries per the SQL/JSON specifications and pluggable table storage interface. PostgreSQL 13 introduced parallel processing of indexes with the VACUUM command and improved duplicate data handling by B-tree indexes. Both versions contain numerous fixes to various software bugs in earlier versions of the database.

PostgreSQL 14 brought major advancements with connection concurrency, high-write workloads, query parallelism, and logical replication. PostgreSQL 15 is due to be released soon, featuring improved performance for sorts exceeding working memory and window function as well as new replication and backup features. Features for all PostgreSQL versions can be viewed at the [full feature matrix page](<https://www.postgresql.org/about/featurematrix/>).

## Performance and Stability Issues

Performance improvements are made with each new version of PostgreSQL, including minor releases. For example, PostgreSQL 14.4 fixed an issue that could cause silent data corruption when using the CREATE INDEX CONCURRENTLY or REINDEX CONCURRENTLY commands. This emphasizes the importance of updating to the most recent minor release as soon as possible not only to minimize impact to performance and stability, but also security. If you don’t upgrade to the latest versions, your company could be vulnerable to security breaches and non-compliant with information security best practices.

## Lack of Support

While Command Prompt provides legacy long term support for EOL releases of PostgreSQL, PostgreSQL 9.6 (and 10.x in November 2022) will no longer be supported by PostgreSQL.Org and other vendors.. This means that the community will no longer produce bug fixes or security patches for these versions.

As a result, many PostgreSQL users have been left without EOL support for their 9.6 databases. Others will need to prepare for the upcoming PostgreSQL 10 EOL.

## How to Address EOL

We strongly encourage clients to upgrade their PostgreSQL 9.6 and 10.x database instances to version 14.x as soon as possible. If you are in PostgreSQL 10, it’s not too early to start planning your upgrade strategy before support ends in November.

If you are in 9.6, you can upgrade directly to PostgreSQL 14 to skip intermediate major versions. PostgreSQL has good client compatibility over all the versions.

### A Side Note: What It Means for AWS Customers

PostgreSQL 9.6 database instances can no longer be created in Amazon Web Services (AWS) from the AWS Console or CLI as of March 31, 2022. Amazon RDS began automatically upgrading PostgreSQL 9.6 database instances to version 12 at the end of April 2022. If a client restores PostgreSQL 9.6 database snapshots, Amazon RDS will automatically upgrade the restored database to PostgreSQL 12 or a more current supported version. It can therefore be assumed that PostgreSQL 10 will be unsupported by AWS by spring of 2023.

* * *

## Next Step

As the oldest dedicated Postgres professional services and support company in the world, our Command Prompt team of experts can help you with your upgrade strategy. Contact us today for help with your next upgrade.

---
[View this page online](https://www.commandprompt.com/blog/top-3-reasons-to-upgrade-postgresql-end-of-life/)

---

# Performance Analysis of PostgreSQL Data Checksums

> Recently I have been working on PostgreSQL benchmarks for its data checksums feature. This incredibly valuable option to initdb -- introduced in version 9.3 in…

Recently I have been working on PostgreSQL benchmarks for its data checksums feature. This incredibly valuable option to initdb -- introduced in version 9.3 in 2013 -- allows quick detection of corrupted disk data pages. It provides the glorious opportunity to simply failover to a standby before your data becomes corrupted, rather than endure the horror of discovering the corruption afterward and attempting to recover.

But people care as much about speed as safety, and the feature comes with a performance cost since that data is checksummed every time it's read from or written to disk. Clients are interested in the feature but they want to know the performance cost. Our answer so far has been "we don't really know," and if an internet search is any indicator, no one really knows.

There is another challenge with this feature: for PostgreSQL versions lower than 12, it can only be enabled when the cluster is first created. And if you create a cluster with this option enabled, there is no way to disable it. PostgreSQL version 12 introduces a utility program [_pg_checksums_](<https://www.postgresql.org/docs/12/app-pgchecksums.html>), which enables or disables data checksums in a PostgreSQL cluster, but the cluster must still be offline while the utility runs. Clients want to understand the performance implications of this feature before committing a new cluster to it, or before undertaking a migration to a new cluster with the feature enabled.

Take note: Amazon enables data checksums on _all_ RDS PostgreSQL clusters, and on their platform it is _not_ a configurable option. I intend to leave you with their same clarity and confidence about this feature.

To find the answer about performance, my first instinct was to run benchmarks and get the answer empirically. I did run benchmarks and I did get an answer. However, this was a really tricky benchmark to set up in a meaningful way, and there are several different benchmarks needed to understand this issue, because there are many factors at play:  


  * CPU time to calculate checksums
  * Obscure differences in write ahead logging having dramatic effects on disk writes.
  * Caching
  * Workload dependence of effects



In the CommandPrompt whitepaper [_Performance Analysis of PostgreSQL Data Checksums_](<../../../../uploads/images/CommandPrompt_Performance_Analysis_of_PostgreSQL_Data_Checksums_2019-09-02.pdf>), I provide the results of several carefully designed benchmarks that illustrate the common workload types that bear significant additional CPU and disk IO load because of the feature, and other workload types that do not bear an additional load. From the Technical Summary of the whitepaper, here are some conclusions about performance impacts of data checksums on different workload types:  


  * Any application with a high shared buffers hit ratio: little impact.
  * Any application with a high ratio of reads/writes: little impact.
  * Data logging application with a low ratio of reads/inserts, and few updates and deletes: little impact.
  * Application with an equal ratio of reads/inserts, or many updates or deletes, and a low shared buffers hit ratio (for example, an ETL workload), especially where the rows are scattered among disk pages: expect double or greater CPU and disk I/O use.



Because hardware failure and low-level data corruption are an all-too-common occurrence in database operations, and the data-checksums feature provides strong protection against such occurrences, Command Prompt recommends that administrators plan for implementation of clusters utilizing the feature, with foreknowledge of its performance impacts. For a full analysis, please download our whitepaper by entering your email below.

---
[View this page online](https://www.commandprompt.com/blog/performance-postgresql-data-checksums/)

---

# PostgreSQL and Financial Calculations - Part Five

> The fifth and last in a series of blogs covering common mistakes in Database and Application designs for financial calculations.Method of Rounding:There are ma…

The fifth and last in a series of blogs covering common mistakes in Database and Application designs for financial calculations.

## Method of Rounding:

There are many methods of rounding

  1. Half Round Up
  2. Half Round Down
  3. Round Towards Zero
  4. Round Away from Zero
  5. Round Half To Even
  6. Round Half To Odd
  7. Random Round



The built-in method of rounding in PostgreSQL is Half Round Up. Unfortunately, it is not the best approach, as it is biased to a higher value. Being biased to a higher value is a well understood problem and why there are so many rounding methods to choose from. To avoid the biased results, the oldest and most common rounding method used is Round Half to Even (commonly referred to as convergent rounding, statistician's rounding, Dutch rounding, Gaussian rounding, or banker’s rounding).

## Consider 5:
    
    
    CREATE SCHEMA ol_code;
    
    
    CREATE OR REPLACE FUNCTION ol_code.round(val numeric, prec integer default 0)
    
    
       RETURNS numeric
    
    
    LANGUAGE 'plpgsql'
    
    
    COST 1
    
    
    STRICT PARALLEL SAFE
    
    
    as $$
    
    
    DECLARE
    
    
    _last_digit numeric = TRUNC(ABS((val * (10::numeric^prec) %1::numeric )),1);
    
    
    BEGIN
    
    
    IF _last_digit = 0.5 THEN  --the digit being rounded is 5
    
    
    -- lets find out if the leading digit is even or odd
    
    
    IF TRUNC(ABS(val * (10::numeric^prec))) %2::numeric = 0 THEN
    
    
    RETURN trunc(val::numeric,prec);
    
    
    END IF ;
    
    
    END IF ;
    
    
    IF val > 0.0 AND _last_digit >= 0.5 THEN
    
    
    RETURN  trunc(val::numeric + (1/ (10::numeric^prec)), prec) ;
    
    
    ELSEIF  val > 0.0 AND _last_digit < 0.5 THEN
    
    
    RETURN trunc(val::numeric, prec);
    
    
    ELSEIF val < 0.0 AND _last_digit >= 0.5 THEN
    
    
    RETURN  trunc(val::numeric - (1/ (10::numeric^prec)), prec) ;
    
    
    ELSE
    
    
    RETURN  trunc(val::numeric, prec);
    
    
    END IF;
    
    
    END ;
    
    
    $$;
    
    
    WITH cc as (select random()::numeric as random  from generate_series(0,100000) )
    
    
    select  sum(pg_catalog.round(random,2)) round_half_up,
    
    
    sum(ol_code.round(random,2)) as round_to_even,
    
    
    sum(trunc(random,3)) correct_value ,
    
    
    sum(ol_code.round(random,2)) - sum(trunc(random,3)) round_even_error,
    
    
    sum(pg_catalog.round(random,2)) - sum(trunc(random,3)) round_up_error
    
    
    from cc

0.1% error Round Half Up vs 0.0025% error Round To Even

As we can see above, the rounding method we are all taught in school creates error biasing the value to the high side compared to banker’s rounding, which we should all be using.

## The solution:

To fix the rounding in PostgreSQL, we need to implement a custom rounding function and overload the default round function by setting the search path like so:

SET search_path to ol_code, pg_catalog, public

This assumes the custom round function is named round(numeric,integer) and placed in the schema ol_code (ol_code is short for overloaded code). This schema is where I place any function overloading the default behavior of PostgreSQL.

There are two well known standards for rounding: ASTM E29 and IEEE 754. Both specify the Round Half to Even method. To maintain the highest level of accuracy, Round Half Up should be replaced with Round to Even, as it is the preferred method.

## Closing Thoughts:

If all the issues discussed in this series were trivial problems we would not have numeric types, independent Math libraries, international standard documents or math papers to address the problems.

Rounding and precision math errors can not be stopped, only contained and limited. It is up to us to use the appropriate tools and techniques to contain the error, limiting the havoc it will create.

These are solved problems, we just need to use the solution.

---
[View this page online](https://www.commandprompt.com/blog/postgresql-and-financial-calculations-part-five/)

---

# PostgreSQL and Financial Calculations - Part Four

> The fourth in a series of blogs covering common mistakes in Database and Application designs for financial calculations.Database Driver, or Application Framewo…

The fourth in a series of blogs covering common mistakes in Database and Application designs for financial calculations.

## Database Driver, or Application Framework Created Error:

The database driver or application framework created errors are probably the hardest to find, as we are the consumer not the writer of the tool, with many assuming the casting is correct. However, we must review the documentation or the library’s code to know how the data type is mapped in the framework. Keep in mind, PostgreSQL numeric type does not always have a comparable data type in many frameworks.

 **Frameworks and languages casting numeric to less accurate type:**

Java Script

  * Numeric => 64 bit float
  * Probably the weakest framework to use for accurate math calculations.
  * In its defense, it was never designed to do things it is asked to do today. (cough NodeJS cough )



PHP

  * Numeric => 64 bit float
  * Independent Math libraries must be used to accurately calculate results. Creates problems sending data back to PostgreSQL, as conversion to string or float must be used in the database driver.



Ruby

  * Numeric => String
  * Numeric => BigDecimal
  * Ruby has a full featured Math library to accurately calculate results. Same problem that PHP has sending data back to PostgreSQL.



GO

  * Numeric => unknown
  * The drivers have no clear documentation on how numeric is being cast. Most likely it is being cast to a 64 bit float.
  * There are libraries available to accurately represent PostgreSQL numeric types and do math operations on them, but they have the same problem PHP, and Ruby have.



 **Frameworks and languages with accurate types for numeric:**

Python

  * Numeric => Decimal
  * Decimal is equivalent to Numeric and has appropriate Math library
  * Pyscopg is a PostgreSQL community created driver



.Net

  * Numeric => Decimal
  * Decimal is equivalent to Numeric and has appropriate Math library
  * Npgsql is a PostgreSQL community created driver



Java

  * Numeric => BigDecimal
  * BigDecimal is equivalent to Numeric and has appropriate Math library
  * The database driver is supported by the PostgreSQL community



C/C++

  * Direct access to the libpq library and PostgreSQL numeric type
  * Direct access to Math libraries to be used with the numeric type



As these two lists show, the application framework can add errors to the calculations just through type casting, which later affects calculations.

## The solution:

The application framework needs to be reviewed to make sure calculations are not using floating point types when it’s a critical calculation. Review the database driver layer to ensure incorrect type casting is not being performed. Use available Math libraries to do all critical calculations.

 **Personal Comment** : It is kind of amazing to me with so many new frameworks and programming languages being developed over the last decade, how all the new toys lack accurate math libraries. It seems they all choose to go for speed over accuracy first, then go _“Whoops! We need to be accurate too!”_ This is probably one of the reasons I see this mistake repeated so many times in application design, as no one realizes how these tiny errors stack up and bite.

## Closing Thought:

Use the appropriate data types in the database and throughout the application stack. Python, C, C++ Java, .Net, all have libraries and functions that make doing these calculations easy.

---
[View this page online](https://www.commandprompt.com/blog/postgresql-and-financial-calculations-part-four/)

---

# PostgreSQL and Financial Calculations - Part Three

> The third in a series of blogs covering common mistakes in Database and Application designs for financial calculations.Order of Operations and Storing Aggregat…

The third in a series of blogs covering common mistakes in Database and Application designs for financial calculations.

## Order of Operations and Storing Aggregate Results:

When working with float data types, order of operations will affect the ending value.

### Consider 3:
    
    
    Python3:
    
    
     **justin@Debian10** : **~** $ python3
    
    
    Python 3.7.3 (default, Jul 25 2020, 13:03:44)
    
    
    >>> (1234.567 * 3.333333) + (1.234567 * 3.333333)
    
    
    4119.338,144,732,812
    
    
    >>> (1234.567 + 1.234567 ) * 3.333333
    
    
    4119.338,144,732,811

As can be seen with the example, order of operations affects the result even though associative and communicative rules state it should not. The degree to which it affects the result depends on if it is a 32 or 64 bit floating type.

Many are going to state that it's only 1 digit of error, however this is happening in one operation and should not happen. This error is amplified when stacking results on results.

A real world example of this problem is with cost-based accounting, recalculating the cost of items using a Weighted Average formula to calculate the average cost.

Formula:

Where:

  * W = weighted average
  * n = number of terms to be averaged
  * wi = weights applied to x values
  * Xi = data values to be averaged



Or more simply expressed below to calculate system/application wide unit cost:

SystemItem UnitCost = ((QtyOnhand/(QtyOnHand + NewQty)) * CurrentCost) + ((NewQty/(QtyOnHand + NewQty)) * NewCost)

The above formula will return the new cost of an item on a _per unit of measure basis_. The application must independently track the cost and the quantity on hand for each item. To calculate the total value of inventory is done like so:

QtyOnHand * SystemItemUnitCost = SystemItemTotalCost

However, many implementations calculate the _Weighted Cost_ using an aggregate value of the Total Cost. This makes calculating the new weighted average easier:

SystemItemTotalCost = CurrentItemTotalCost + (NewItemTotalCost)

This approach is simpler and appears to work, but errors start creeping in as the “per unit of measure cost” is calculated at every transaction, which updates the system total cost and quantity on hand.

PerUnitCost = CurrentItemTotalCost/QtyOnHand

SystemItemTotalCost = CurrentItemTotalCost +/- (QtyOfTransaction*PerUnitCost)

QtyOnHand = QtyOnHand +/- QtyOfTransaction

The bulk of the error comes from recalculating the PerUnitCost at every transaction, adding rounding and floating point errors to the new results.

### Consider 4:
    
    
    SELECT '1: Calculate new cost', round(((139.00/(139.00+75.00) * 1.25)) + ((75.00/(139.00+75.00))*1.35),4), round((((139.00 *1.25) +(75.00*1.35))), 4)
    
    
    UNION
    
    
    SELECT '2: do a transactions subtract 5.333, value moved', round( 1.2850 * 5.333, 4), round(275.00/(75.00+139.00) * 5.333, 4)
    
    
    UNION
    
    
    SELECT '3: do a transactions subtract 37.482', value moved, round( 1.2850 * 37.482, 4), round((268.1468/208.667) * 37.482, 4)
    
    
    UNION
    
    
    SELECT '4: do a transactions subtract 68.57, value moved', round( 1.2850 * 68.57, 4), round((219.9807/171.185) *68.57, 4)
    
    
    UNION
    
    
    SELECT '5: Total inventory value',  round(1.2850 * 102.615,4),  130.8247
    
    
    UNION
    
    
    SELECT '6: Current per unit value',  1.2850 ,  round(130.8247/102.615,4)
    
    
    ORDER BY 1

We see here how the order of operations and storing of an aggregate value distorts calculations rather quickly. With only 3 transactions, the total inventory value was distorted by 0.04 units.

The above calculations were done with PostgreSQL numeric type, not a floating point type. Using float type would make the deviation worse. If we threw in units of measurement conversions, the deviation would grow. See Consider 2 for effects of unit of measure conversion.

## The solution:

If the application uses aggregates in critical calculations, the quickest solution is to increase precision of the stored values and in all calculations. This delays the stack up error from wreaking havoc. The error can not be completely removed by only increasing the precision. The best approach is to keep the stored values in the lowest common value, and avoid storing or using aggregated, sum, or grand totals that are used in later calculations. For example do not store the total inventory value (Qty * UnitCost); store the quantity on hand and the unit cost in separate columns. Best to avoid using mix precision, rounding, or simplifying formulas with calculated aggregated values. Don’t cheat or shortcut the math formulas to save processing time. CPU time is cheap today; this is not the 1970’s.

## Closing thoughts:

Watch the structure of formulas and order of operations. It's easy to add errors to a result that will go unnoticed for thousands of operations. Always investigate what will happen if a formula is called thousands or millions of times.

Is the result correct?

How much error can be tolerated?

---
[View this page online](https://www.commandprompt.com/blog/postgresql-and-financial-calculations-part-three/)

---

# PostgreSQL and Financial Calculations - Part Two

> The second in a series of blogs covering common mistakes in Database and Application designs for financial calculations.Inconsistent precision scaling:This is …

The second in a series of blogs covering common mistakes in Database and Application designs for financial calculations.

## Inconsistent precision scaling:

This is probably the most common mistake in database design that I observe. It is understood to use exact data types (such as numeric) and the precision must be fixed, but for whatever reason the decision is made that it’s OK for one table to use numeric(12,4),a second table to use numeric(12,2), and then a third to use numeric(12,6). It’s common to see mixed precision even within the same table. On the surface this does not sound bad, as numeric types are storing the results and math being used is exact. However, this ignores the basic math rule that the least precise number sets the accuracy limit and stack up error.

### Consider 2:
    
    
    CREATE TABLE uom_convert(
    part_number text,
    uom_from text,
    uom_to text,
    uom_ratio numeric(14,6)
    );
    
    CREATE TABLE inventory_on_hand(
    part_number text,
    uom text,
    qty_on_hand numeric(12,4),
    cost_per_uom numeric(12,2)
    );
    
    CREATE TABLE inventory_transactions(
    part_number text,
    qty_moved numeric(12,4),
    total_moved numeric(12,2)
    );
    
    INSERT INTO uom_convert VALUES
        ('gold', 'grams', 'troyoz', 0.0321507);
    
    INSERT INTO inventory_on_hand VALUES
        ('gold', 'troyoz', 0, 1735.25 );
    
    truncate inventory_transactions;
    
    INSERT INTO inventory_transactions
        (SELECT 'gold', rqty * uom_ratio, --cost_per_uom,
            (rqty * uom_ratio) * cost_per_uom
        FROM uom_convert
            CROSS JOIN (SELECT round((random()*100)::numeric,0)::numeric rqty --using only
    integer no fractions values. Fractions values make this look even worse.
        FROM generate_series(0,99)) dd
        LEFT JOIN inventory_on_hand ON
            inventory_on_hand.part_number = uom_convert.part_number
        WHERE uom_convert.part_number = 'gold'
            AND uom_from = 'grams'
            AND uom_to = 'troyoz' );
    
    UPDATE inventory_on_hand SET
        qty_on_hand = (SELECT SUM(qty_moved)
            FROM inventory_transactions
            WHERE part_number = 'gold')
         WHERE part_number = 'gold' ;
    
    SELECT 'inventory_on_hand', qty_on_hand, round(qty_on_hand * cost_per_uom,2)
        FROM inventory_on_hand where part_number = 'gold'
    UNION
    SELECT 'inventory_transactions', sum(qty_moved), SUM(total_moved)
        FROM inventory_transactions where part_number = 'gold';

Comparing the inventory transaction table value to the actual value, the inventory transactions are over stated by $0.26 in just 100 transactions. When you run this example you will get different values due to the random() function being used to set the quantity being moved. The returned value will be either higher or lower, however, the inventory_transactions value will always be overstated.

## The solution:

Increasing the precision of the tables. I have come to like numeric(20,8). This gives us a big number: 999 trillion and 8 digits of precision. If the local currency is something akin to Zimbabwe dollars, we will need a larger numeric value. Taking the above example, edit the tables to use numeric(20,8) the result will look something like this.

Errors do not start to appear in the calculations until the 6th decimal position. Many consider this level of error contained, as it will take tens of thousands of transactions for this to cause stack up error. In testing, it took a million transactions to create a 0.003 discrepancy between the two tables. This method is sometimes called a **_Check Digit_** , where math operations keep an extra digit of precision to avoid truncation or rounding errors.

## Closing Thoughts:

Changing the rounding method not just in PostgreSQL, but throughout the entire application stack wherever calculations are done.

---
[View this page online](https://www.commandprompt.com/blog/postgresql-and-financial-calculations-part-two/)

---

# PostgreSQL and Financial Calculations - Part One

> A series on the use of data types to insure accurate financial calculations with your application.Over my multi-decade career, I have often noticed the problem…

A series on the use of data types to insure accurate financial calculations with your application.

Over my multi-decade career, I have often noticed the problematic use of real, floating, double, and fixed precision types to store and calculate financials. Most believe the application only needs two digits to the right of the decimal point for financial data. The use of only two digits assumes that many financial calculations do not need more than two decimal points; for example, the units of measure conversion or currency exchange. These transactions represent a significant monetary value that cannot be represented with only two digits of precision.

In this series we will go over common mistakes, what happens when you choose an incorrect data type, inconsistent precision scaling, conversion errors caused by frameworks and common calculation mistakes within PostgreSQL.

## Choosing the wrong data type:

One of the most common mistakes may be the most destructive. It is the use of the variable-precision data type (such as real, float and double precision) for financial calculations. Many view this as a non-issue because PostgreSQL stores and returns the value as it is received from the application. However, floating point types being 32 or 64 bit suffer from inexact math in an attempt to balance the precision of the values with the speed to calculate those values. This balance will introduce what appears to be a minor error, however, it will stack up to significant error. Below is an example showing what happens with different data types and variable precision when compared to the default use of numeric type.

### Consider 1:

PostgreSQL SQL
    
    
    SELECT
    (1234.567 * 3.333333) + (1.234567 * 3.333333) as Correct_Value_Numeric,
    (1234.567 * 3.333333)::float(25) + (1.234567 * 3.333333)::float(25) as High,
    (1234.567 + 1.234567 )::float(24) * 3.333333::float(25) as Low_Mixed_Float_Size,
    (1234.567 * 3.333333)::real + (1.234567 * 3.333333)::real as Rounded_High,
    (1234.567 + 1.234567 )::real * 3.333333 as Low

With the above SQL query using casting, PostgreSQL uses floating type math operators demonstrating the errors that occur. Take note of the Low_Mixed_Float_Size column and odd math results when 32 and 64 bit floating point types. This kind of mixing of datatypes happens all the time in applications, which increases the value of the error.

Many will say this error is acceptable as it never impacts the 100th position and the rounded value is unchanged. This line of thinking is erroneous and ignores stackup. Consider what happens when buying a million widgets using the rounded price, or selling at the low price. Another counter argument is that only a few applications need this level of precision in financial calculations.

Let's look at a real world example of how precision and stackup are exploited. Gasoline pumps measure hydrocarbons to the 1,000th, but are priced in two digits of precision. Measuring the fuel to the 1,000th position to avoid rounding benefits the seller. Consider the following scenario where we compare the transaction using 3 digits of precision vs 2 digits:

By keeping the fuel measurement at a higher precision and leaving the price at two digits, the seller is exploiting the stack up of selling a 1,000th of gallon instead of rounding it to the same precision as the price. This allows the seller to extract a tiny fraction of money over billions of measurements and transactions.

## The solution:

Be consistent with the data types. Don't mix real, double precision and numeric types (or the equivalent) in your favorite framework. Tiny errors will appear in casting of data type, either by truncation or rounding artifacts.

## Closing Thoughts:

The single biggest improvement in accuracy for calculations is increasing the level of precision of the numeric type, as this delays error creeping into the calculations.

---
[View this page online](https://www.commandprompt.com/blog/postgresql-and-financial-calculations-part-one/)

---

# Recent blog updates

> When you have been around as long as Command Prompt, you are bound to forget blogs you wrote as well as the fact that those blogs are likely exceedingly outdat…

When you have been around as long as Command Prompt, you are bound to forget blogs you wrote as well as the fact that those blogs are likely exceedingly outdated. I was recently doing a review of the Command Prompt Dead Sea Scrolls and have come across two that we have updated to be accurate for the modern times of PostgreSQL.

### The blogs

  * The Write Ahead Log: Essentials
  * PostgreSQL Minimum Requirements



### Why update?

It is important to update your blogs including marking that they are updated or referencing former authors. It allows the content to maintain its relevancy and usefulness to readers. Remember, when dealing with technology things change often. If you don't update your content, you are doing a disservice to your readers as they may end up with old, bad or just wrong information about what you are trying to teach them.

---
[View this page online](https://www.commandprompt.com/blog/recent-blog-updates/)

---

# Postgres, where art thou?

> In the 2017 article we referenced to /r/postgresql which at the time had 5,100 members. It now has 25.5k. In the same time period as pgsql-general, it generate…

In 2017 I wrote an article titled, “[Where is the Postgres community?](<https://www.commandprompt.com/blog/where_is_the_postgres_community/>)” The article was a summary of many of the external communities where Postgres people interact. I wrote it for two reasons:

  1. To show that the Postgres community is far broader than Postgresql.org mailing lists
  2. To bring visibility to the external communities in hopes that people will join them



Now that we are post-pandemic and it is five years later, I am curious as to where the communities are now. I ask because I recently started paying attention to pgsql-general@postgresql.org again. The pgsql-general mailing list used to be a vibrant collaboration and support channel. I am sad to report that the mailing list is all but a ghost town with only 15 messages sent in 4 days. In its hay day the list would easily pull thousands of messages a month. The sparse nature of collaboration on this list isn’t surprising and has been the topic of many in the community. People just don’t use email as a canonical source for collaboration anymore.

## Where are we now? 

In the 2017 article we referenced to /r/postgresql which at the time had 5,100 members. It now has 25.5k. In the same time period as pgsql-general, it generated 175 messages among community members (20 posts, 155 responses). Similarly, we mentioned the Slack channel which at the time had 1100+ members. It now hosts 18.3k subscribers with similar activity of the subreddit. The [People, Postgres, Data Discord](<https://discord.gg/bW2hsax8We>), which did not exist in 2017, has 3,579 members and is quite active over its 28 channels. The listed collaboration venues don’t take into account the thousands of members among the international or associated (Brazil, Russia, TimescaleDB, Yugabyte, NeonDB, etc…) Postgres communities.

## Postgres community, where art thou?

Despite these numbers, the size of the communities and the activity mentioned above is barren in comparison to the mailing list’s hay day. I have to wonder: where did everyone go? Is this caused by consolidation of many of the Postgres companies? Is it because companies have their own venues? Even the AWS (arguably the largest single distributor of Postgres related technologies) support forums for Postgres related technologies are not very active. Perhaps it is due to the commercialization of the software. PostgreSQL was once a fledgling database that only those in-the-know used. Now it is the kernel for some of the most interesting database technologies such as Yugabyte, Aurora, Hyperscale, Timescale, and NeonDB. Is it then because Postgres is now more “work” and less of a hobby? 

## PostgreSQL is dying

Far from it. The technology is highly respected for its performance, quality of code and permissive licensing. The commercial side of PostgreSQL is beyond successful, causing even [Oracle to start supporting it](<https://docs.oracle.com/en/solutions/deploy-postgresql-db/index.html>) in their cloud. The mailing list pgsql-hackers, which is where development collaboration occurs, is quite active. What is dying is that feeling of community; that old feeling of a rebel Open Source, instead leaving behind only a job servicing, using or developing with PostgreSQL. Maybe we are just getting old.

---
[View this page online](https://www.commandprompt.com/blog/postgres-where-art-thou/)

---

# PostgresConf Silicon Valley 2022, anticipated talks

> On Thursday and Friday of this week we will be enjoying 90 degree weather and sunshine in San Jose, California. It will be quite the change from the dark and d…

On Thursday and Friday of this week we will be enjoying 90 degree weather and sunshine in San Jose, California. It will be quite the change from the dark and damp of NW Washington. This is also the first time I will have been on an airplane in almost 3 years. Yes, it really has been that long since the world decided to begin a pandemic. That said, I am excited for Postgres Conference Silicon Valley 2022 and in particular the following sessions:

  * [Digital Rights and Privacy: Concerns for the 21st century](<https://postgresconf.org/conferences/SV2022/program/proposals/digital-rights-and-privacy-concerns-for-the-21st-century>)
  * [Scaling Beyond PgBouncer & Pgpool-II: Advanced Traffic Management](<https://postgresconf.org/conferences/SV2022/program/proposals/scaling-beyond-pgbouncer-pgpool-ii-advanced-traffic-management>)
  * [Non-Relational Postgres](<https://postgresconf.org/conferences/SV2022/program/proposals/non-relational-postgres-321d2a8c-906e-4a4c-a1b0-770343e5d1a4>)



I also very much look forward to seeing long away friends, Bruce Momjian, Michael Meskes, Jim Mlodgenski and Alvaro Hernandez. See everyone there!

---
[View this page online](https://www.commandprompt.com/blog/postgresconf-silicon-valley-2022-anticipated-talks/)

---

# When is it time to fire a client?

> Over the last 25 years we have interviewed hundreds of people to be a part of our team. As with any good interview, you allow candidates to ask questions about…

Over the last 25 years we have interviewed hundreds of people to be a part of our team. As with any good interview, you allow candidates to ask questions about the business, how you operate, what your philosophy looks like, and hopefully what your plan for the future is. My favorite is, “What is something you tell every employee?” Our answer is always the same, “We are never afraid to fire a client” and the response is almost universally “that’s refreshing.”

While it is true that clients are the lifeblood of a business, there are times when the relationship between the parties becomes toxic and is no longer providing a productive and positive outcome. How do we know when the relationship is toxic? How do we know that it won’t produce a positive outcome? What are the metrics (the red flags) that help you determine such an important question and take decisive action? These are all excellent questions and there are only a few situations where it is black and white.

Through the 90s and early 2000s the chase for revenue outgrew the need to reduce the level of toxicity within a Vendor->Client relationship. The concern was, “How much money are we making from the client?” Thankfully, for many that time is long gone and there are more than enough businesses that understand that a relationship with a vendor is a partnership. That partnership should work toward the mutual success of both parties. The following is a list of red flags that could mean it is time to part ways with a client. It is by no means meant as a single incident qualifier, but as markers to pay attention to.

## The client wants a deal without mutual benefit

I often run into this with clients during the negotiation process. It is most often worded as, “So what kind of deal can you make me?” This is a red flag for a number of reasons:

  * It isn’t reciprocal. The client wants something for nothing.
  * They may not value your offering.
  * They may be having difficulty paying invoices.



Any “deal” should always be reciprocal. In Command Prompt’s industry an example would be, “If I can guarantee you X amount of revenue per month, can you give me a discount on your hourly rate?” This is a reasonable question and a positive sign of a new relationship. The client understands that you are valuable and is willing to commit to make the relationship stronger. On our end, the consistent nature of the work and revenue allows us to plan better and we are therefore in a better position to be able to be flexible to the client’s request.

## The client consistently refuses to heed your advice

There are perfectly valid reasons why a client may not be able to heed your advice/recommendations. It could be budget constraints, uptime requirements, external business factors or a host of others. However, there are times that a client will refuse your advice to the detriment of your business and theirs. When this happens, it is a marker of the stability of the client’s business as well as the maturity of their leadership.

## Your leadership is constantly on-call

There can be tense times in any relationship and sometimes leadership needs to calm the waters, help the client (or vendor) understand requirements, or just generally ease tensions between multiple teams. This is normal. However, if you find yourself in constant conversations where your engineers are requesting leadership present to redirect projects back into scope, push back against micro-managers, or generally be present to keep people on their best behavior, it is a sign of a dysfunctional relationship.

## An inability to be nice or respectful

It is no secret that many technical teams are lacking in certain human skills. A lot of times it is a holdover from the days when technical people were left to their own devices to deliver solutions that nobody could understand. This is no longer an acceptable behavior. Every person on a team deserves to be treated nicely and with respect, even if you disagree with them. Communications should always be professional and with purpose. If a mistake is made, the focus should be on reconciliation and solving the problem, not blame or counter attacks.

## They question every invoice

Invoices should be reviewed by clients. It keeps everyone honest and provides transparency into the project. However, if you find yourself constantly defending a certain type of billable (for example: Project Management), the client is showing that they do not value that particular part of your service. There are times when this can be resolved through client education, but often it is a client that will always nitpick your invoices. This further reduces your productivity for the client by focusing your time on items that are not actually within the scope of the project.

There are of course other behaviors to be considered and none of these should be an instant Stop Work order. It is critical in all situations with a client when any form of rupture occurs that repair happens as soon as possible. If you’re consistently phasing the above or related issues though, it may be time to go your separate ways for the mutual benefit of everyone involved.

---
[View this page online](https://www.commandprompt.com/blog/when-is-it-time-to-fire-a-client/)

---

# We're All In This Together

> Recently I received a kind email from a client and friend in the Postgres Community. It struck a chord because she had listened to my podcast, hosted by Beauti…

Recently I received a kind email from a client and friend in the Postgres Community. It struck a chord because she had listened to my [podcast](<https://open.spotify.com/episode/506mrV7YDWi8v9GIngx1QS>), hosted by [Beautiful Strength](<https://www.beautifulstrength.org/>), which was about having chronic illnesses while traveling in a bus and working full time.

Within the podcast, I reveal parts of myself that I don’t normally share with my team members, let alone with my clients. Until recently, I have kept my personal struggles pretty close to the chest. There was a point when going through the stages of grief about my new diagnoses that awareness became a passion. (I think it was my heart’s way of dipping into acceptance). During that stage, I spoke openly. Not long after, I felt myself shutting down - not in terms of ability, but rather vulnerability. I crawled back into my shell, trying to hide my suffering and struggles. I went back to expecting myself to perform like I did before I dipped my toe in sharing.

I got so wrapped up in hiding it that I started to believe in the back of my mind that maybe it won’t be as bad as they say. Maybe God will smile on me and a miracle will take the pain, the fatigue, and the shame away. Maybe I don’t have to let go of my dreams and aspirations. Maybe I can be there for my team all of the time without fail.

Today I feel like I have nothing left. Everything from my neck to my ankles ache. Two days ago my right leg throbbed so badly I had to have my partner lay on it to provide a miniscule amount of relief. All my bendy parts ached, but I didn’t notice them as much. Two weeks ago I collapsed on the bathroom floor and went into survival mode, using everything I had left to crawl into bed. By the time I got there, I was covered in sweat and couldn’t talk.

How does one go through that and feel like they can contribute? Watching my body deteriorate has been so hard for my mental health that I ask myself questions like that all of the time. I second guess myself more than ever and I fear that what I’m becoming won’t be enough to take care of my team and family. What then?

 _We’re all in this together_ , my client said in the email.

If someone else had said that to me, I likely would have done the standard nod. But it wasn’t. It was someone I know, someone who I’ve shared stories and struggles with. Someone who I know would pick me up when I fell and not pass judgement.

That made me hopeful again. Not “Miracles are Everywhere” hopeful, but hopeful enough to remember that everyone has struggles and we **all** have the ability to be there for someone who needs it.

The problem for me then shifts to a question for humanity: why have we become so distracted that we’ve forgotten to show common kindness and servitude? Why must we put up walls to shut ourselves off and desensitize our hearts just to function? Why do people, in general but especially with chronic illnesses, feel that their worth is tied to their productivity?

As I struggle to answer these questions, I remember that through the pain and shame, I am growing. In a way, I am learning to know and be myself more than ever before. I am learning to take down the walls that so easily get thrown up and believe that we’re actually all in this together.

It’s the small things in life that keep us going; such as an email from a client. Don’t forget that we’re all going through something - some are just more visible than others.

---
[View this page online](https://www.commandprompt.com/blog/were-all-in-this-together/)

---

# Top 5 Reasons to Move to a Peer Review Focused Business

> At Command Prompt, we rely heavily on peer review for the success of our clients. We believe that the best quality work is provided when there is no silo and w…

At Command Prompt, we rely heavily on peer review for the success of our clients. We believe that the best quality work is provided when there is no silo and when team work, no matter how much or how little, is a part of the day-to-day. When a group of individuals is encouraged to work together in an effort to provide high quality work and learn from each other, you’re able to find a highly productive environment. Team members are more likely to ask questions, more motivated to provide increased collaboration and will jump into an otherwise assigned urgent situation to offer whatever help they can. It is the ideal work environment, and we believe it all starts with Peer Review.

### Peer Review:

## Creates higher quality of work

No one can deny that two sets of eyes on an upgrade plan, a batch of code, or a recommended slow query fix will lead to a better result. Oversights are less common, errors are caught before being finalized, and peer discussion leads to reducing the potential risk. Problems are solved before the client is involved. Now imagine having several sets of eyes and a team with various skill sets reviewing, learning, and providing feedback as the plan evolves. The final quality is as close to perfect as possible given the requirements set by the client, simply by having peer review.

## Requires ego to be left at the door

When people know that their work will be reviewed by other members of their team, they have a choice: they can participate and learn from the experience, or they can hold their ego close to their chest. Due to the nature of the Open Source industry, there are a lot of people who are more focused on learning than being in a silo. The best way to do that is by working together, reviewing each other’s work, and providing constructive feedback in a respectful manner. It benefits everyone and encourages team members to focus on improvement instead of being egotistical about their work product.

## Encourages better work ethic

Requiring work to be reviewed by team members before it goes to a client reinforces accountability and a team focused mindset, which in turn can lead to improved work ethic. It’s not just about doing your 40 and enjoying your weekend. It’s about solving problems and learning together. When peer review is done right, without attitude or defensiveness, team members are enabled to know without a doubt that they provided the best quality work possible, encouraging satisfaction with work and reducing the time it takes to recharge. When work is a place people look forward to going to, work ethic improves.

## Instills camaraderie

The more time we spend together, whether editing each others’ work or solving problems, the more camaraderie we will end up with. People naturally seek positive relationships with the people they work with, and when you’re working together consistently, focusing on the quality of what is delivered becomes the main goal. Disagreements and differing opinions can help reveal various sides of the problem, which builds camaraderie and encourages the team to navigate challenging situations with the main goal in mind.

## Helps turn engineers into consultants

One of the most impactful things we have done at Command Prompt is bring on Project Managers. This is not only for the benefit of our clients, but for our team. Before work is provided to a client, it must be approved by a Project Manager to ensure effective work product by:

  * Ensuring proper grammar
  * Ensuring all updates are understandable by the tech team as well as other stakeholders within the company
  * Editing for clarity, delivery, and message
  * Always having a call to action
  * Making sure it is clear where the task is at, what is next, and who is doing what



These simple yet incredibly valuable modifications will help turn engineers into consultants over time. They reinforce an attitude of understanding, consideration, and emphasizes the importance of delivery to the client.

\--

While shifting to a Peer Review focused business is not without its challenges and overhead, it will provide a better work product and an improved learning environment for your team. It can be a simple or complex process based on the project requirements.

If you have any questions about how to get started, [contact us](<https://commandprompt.com/contact-us/>) and mention Intrepidus Vita!

---
[View this page online](https://www.commandprompt.com/blog/top-5-reasons-to-move-to-a-peer-review-focused-business/)

---

# Professional Development: How Our Team Sees It

> Command Prompt has been providing infrastructure support to enterprises for over 20 years. As we are the only Postgres company still operating since the 90s, h…

Command Prompt has been providing infrastructure support to enterprises for over 20 years. As we are the only Postgres company still operating since the 90s, how is it that we’ve stayed standing? The answer is simple; we as a company and as a community firmly believe in the power of professional development. We frequently encourage everyone in our team, from interns to owners, to continue to learn and grow, both professionally and in their personal lives. With this in mind, we interviewed our team about professional development, and we found there were far more commonalities than differences in what they had to say:

### There’s no reason not to

 _“The bottom line is: you have nothing to lose. Best case, you pick up a skill and you 're great at it; worst case, you learned something from trying to learn something. No one’s going to make fun of you for it.” - Lindsay Hooper, Director of Marketing & Events_

You have every reason to focus on professional development. It increases job opportunities, makes you better at handling challenges and everyday responsibilities, and helps you get to know yourself. And at the end of the day, the only person who can judge you is yourself.

### It keeps you at the top of your game

 _“The open source world changes all the time and moves very fast, so you have to get signed in to newsletters and news sites just to see what’s happening. Otherwise, it moves on without you and you get left behind.” - Eric Worden, Senior DBA_

If you don’t put effort into professional development, there’s a good chance that your skill set will soon be out of date. Especially in a fast-moving, ever-evolving world such as tech, not practicing professional development could spell disaster for your career. As everyone around you learns and adapts, if you stay in the same place, you’ll begin to lose opportunities and your expertise will become irrelevant. On the other hand, keeping up with the way the world is changing will keep you at the top of your game and give you all the same benefits mentioned in the above paragraph.

### It takes perseverance

 _“You 're learning a new skill and it's just like exercise, there's no shortcut; go in and spend time and carve out time doing it.” - Justin Graf, DBA_

There’s no way around it; professional development takes time, hard work, and perseverance. It won’t be easy - in fact, it may never be, but that’s how progress is made. It can be frustrating and start to feel pointless, but it isn’t. You have to push through those feelings and the difficult times in order to improve.

### Resources are all around you

 _“What 's most important is that you don't just have to read a dry technical course manual for professional development. A great resource can be more diverse and encompassing, such as the American Genius Network.” -_ _Debra Cerda, Director of Business Development & Compliance_

If you’re stuck on a certain topic, confused on where to start, or even just looking for enrichment for your development, the great news is that there are resources available everywhere you look. The device you’re using to read this, the library downtown, and the people around you are wealths of knowledge. If you know what you’re looking for, you’ll always be able to find it.

On the other hand, if you don’t know what you’re looking for, start with things you love to do and let yourself fall down the rabbit hole, discovering new areas that might suit your goals. And if that doesn’t work, we’d love to help; give us a call and mention [Intrepidus Vita](<https://www.commandprompt.com/about/intrepidusvita/>), and we’ll put you in touch with some fantastic brainstormers.

---
[View this page online](https://www.commandprompt.com/blog/professional-development-how-our-team-sees-it/)

---

# How to Achieve Success When Working From Home, Updated

> Now that it’s been over a year, we thought it would be good to revisit the How to Achieve Success When Working From Home blog from March 2020. The idea of the …

Now that it’s been over a year, we thought it would be good to revisit the [How to Achieve Success When Working From Home blog](<https://www.commandprompt.com/blog/how_to_achieve_success_when_working_from_home/>) from March 2020. The idea of the original post was to help those who were challenged by the new work-from-home environment by sharing the knowledge that we’ve gathered over 15 years of working from home ourselves. Much has changed since that post was published, and it’s time we updated it with the things we’ve learned.

## What worked

### Self care

Self-care is essential for any kind of success in life. You can work yourself to the bone and reach your goal, but if your health suffers for it, it isn’t a success. This holds true whether you’re facing the struggles of a pandemic or not. Take a breath, slow down, and take care of yourself.

### Boundaries

Setting boundaries is a big aspect of success when working from home. You need to be able to communicate with your family, friends, and whomever else may be in your home or online about what you need when you’re working. Requesting that they give you your space, stay relatively quiet, and respect your working hours is not only reasonable, but necessary for you to work efficiently. And while they may respect your needs, you need to keep yourself in check as well, by limiting phone usage, TV breaks, and whatever else may distract you from your tasks.

### Appropriate breaks

It can be hard to settle into a rhythm when working from home. Your entire schedule is disrupted, and while the flexibility can be great for some people, others work better with a routine. Balance is key. Set a time for when you work, but don’t overdo it; if yours is a career where breaks are possible, then remember that it’s okay to move about when you need to. At the same time, this kind of environment can encourage procrastination and enable distraction. Appropriate breaks will look different for everyone, so test out your routine, and see what works best for you.

### Dedicated workspace

Although working on the couch can be nice, if you’re used to working at a desk, that kind of environmental shift can end up sending the wrong message to your brain. If you end up in “relax” mode instead of “work” mode, it will be that much harder to focus on your tasks. If you create a dedicated workspace, whether it’s a corner of the dining room table or a desk in your office, you can teach your mind that when you’re there, work is done.

## New revelations

### External and internal noise

There are a million things trying to grab our attention outside of our homes. Inside used to be our safe place away from all of the noise of the outside world. However, the lines between work and play have blurred to the point where the inside of our homes can be just as loud as the outside world. Now, we are faced with the need to redefine those boundaries in a way that allows us to still be productive without overlooking our need for space. Those boundaries will have to be drawn differently for everyone, but what matters is that they are drawn effectively.

### Appreciating the opportunity

Many of us probably won't be able to work from home for the rest of our lives. In no way is this transition easy, but even so, working from home provides an unprecedented amount of freedom. Take advantage of that opportunity while you can; create a flex schedule, stop to make lunch in your kitchen, or take an afternoon walk. Chances are, this level of flexibility won’t roll around again.

### Continued evaluation

As we transition into hybrid work environments, what we found to work in a pandemic lockdown may not work anymore. Regularly checking up on what’s effective and what isn’t is key to continued success in our changing world.

Different tactics work for different people, and while we have tested these tips and can vouch for them, your experience may be different. Maybe your mind functions best when you’re in the clothes you’d wear in the office, but someone else might work best in their pajamas. At the end of the day, you know yourself better than we do, but what’s universal is the need to make an impact in our prospective roles - how you choose to get that done is up to you..

---
[View this page online](https://www.commandprompt.com/blog/how-to-achieve-success-when-working-from-home-updated/)

---

# Mark Porter: CTO MongoDB on PostgreSQL and MongoDB

> I had an opportunity to sit down with Mark Porter, the CTO of MongoDB to discuss PostgreSQL, Aurora PostgreSQL and MongoDB. Mark is one of the creators of Auro…

I had an opportunity to sit down with Mark Porter, the CTO of MongoDB to discuss PostgreSQL, Aurora PostgreSQL and MongoDB. Mark is one of the creators of Aurora PostgreSQL and now enjoys a leadership role at MongoDB. There are two episodes:

  * [Engineering Culture](<https://anchor.fm/more-than-a-refresh/episodes/Bonus-Episode-Mark-Porter--CTO-at-MongoDB-e167454/a-a1ptlh>)
  * [The aha moment](<https://anchor.fm/more-than-a-refresh/episodes/Episode-Nine-Mark-Porter--CTO-at-MongoDB-e15dqr5/a-a1ptlh>)



It is important to reach out to leaders in communities to understand how they succeed. Mark has over 30 years of experience in the Data world, including heavy hitters such as Oracle and AWS.

---
[View this page online](https://www.commandprompt.com/blog/mark-porter-cto-mongodb-on-postgresql-and-mongodb/)

---

# Professional Development: No Box Required

> The purpose of professional development is to strive to be better, to perform more effectively, to reach a higher professional level, and to know more in a wor…

The purpose of professional development is to strive to be better, to perform more effectively, to reach a higher professional level, and to know more in a world full of knowledge. While there are many continuing education classes, training, research, and reading opportunities, often these don’t fit our specific needs. Understanding how one learns may also impact how they should go about professional development. Sometimes thinking outside of the box is the most effective way to achieve growth on a consistent basis.

Earlier this year I took a Harvard class on leadership.. It energized me by taking the class andI wanted to take another one right away. Instead, my chronic illness flared up, and I decided that the way forward was to focus on self-paced professional development. A few months later I took part in an Ehlers-Danlos Syndrome (EDS) Awareness Challenge, and started a [pro](<https://unlimitedwithexceptions.org/>)ject to provide encouragement and education to others with this syndrome. I also took the personal challenge of informing my team and professional network of my battle with EDS.

I didn’t consider talking to my team about my chronic illness as professional development until I evaluated what professional development means. I started asking, “Am I in a different/better position than I was before opening up to my team? Did it benefit my career? Did it improve my workflow?” The answer is: Yes. Instead of pressuring myself to perform flawlessly, my vulnerability enabled me to refocus on what really matters. That has also helped me be more compassionate, more understanding, and more focused on my team’s and client’s needs.

Do these things technically qualify as professional development? If the goal of professional development is to grow and become a better professional, then it absolutely qualifies. Growth in a positive, professional manner is exactly what we should be striving for. Learning something to pass an exam or achieve a piece of paper does not compare to broadening everyday life skills. Ticking a checkbox, for example, isn’t about learning or growth; it’s adhering to someone else’s definition of what you need to know. That is often not enough and sometimes the only way to achieve genuine professional development is to get creative, and stretch your definitions.

Ways to think outside the box with your professional development:

 **Be a leader.**

Being a leader enables you to take what you learn and put it into practice. It reinforces all of the work/dedication you are already putting in, and at the same time it helps others. While leadership may be more time consuming than independently working on your own core skill set, the ultimate proof of understanding is being able to educate others by putting concepts into practice.

 **Take risks.**

Taking considered risks and managing them is how we push our ability to handle increasingly difficult situations. Sometimes you have to take the initiative. Don’t be afraid to put your hand up first when someone is asking for a volunteer, or offer suggestions no matter how good you think they are. And most importantly - never let failure discourage you from reaching your goals.

 **Know that when you’re uncomfortable, it’s a good thing.**

Just like taking risks, you only grow when you’re uncomfortable. Saying “no” is easy.Saying “yes” is a commitment that leads to change. It’s easy to say “I’m too tired to exercise” and then tell yourself “someday I’ll be fit.” It’s harder to get off the couch than it is to do the workout itself. It’s uncomfortable, and it hurts, but once you make that commitment to yourself and learn to embrace the uncomfortable, your mindset will change.

Sometimes the opposite is necessary, such as when you’re trying to build better habits and not eat that piece of cheesecake or binge watch that TV show when you should be reading [_The 7 Habits of Highly Effective People_](<https://www.indiebound.org/book/9781451639612>) by Stephen R. Covey. Focus on building yourself and your future; be intentional with your words and don’t avoid discomfort.

 **Don’t talk - DO.**

Planning is not action. Telling people about your plans is not action. Writing about your plans is not action. Opportunities fall in your lap when you start doing instead of planning. Often when you start with one thing, you’ll find a whole new area to discover, both about your trade and about yourself.

 **Take every opportunity.**

While this piece is geared around professional development, growth can be achieved in every aspect of life. The challenge is in recognizing opportunities and acting on them. When evaluating an opportunity or challenge, ask yourself the following: Will the skill benefit your professional life, even in indirect ways? Will it improve your mindset so you can perform better or be happier? Why are you stopping yourself? Call yourself out; we need accountability and to be reminded that we have the last say when it comes to our own successes.

---
[View this page online](https://www.commandprompt.com/blog/professional-development-no-box-required/)

---

# Educating the Educators: The Role Professional Development Plays for Today's Teachers

> In many industries, professional development has grown from a nice to have on the side of the employer to a must have for workers. In this blog, we’ll use teac…

In many industries, professional development has grown from a _nice to have_ on the side of the employer to a _must have_ for workers. In this blog, we’ll use teachers as a case study to explore how mandated professional development isn’t the answer, and how individuals need to be investing in themselves and the skill of adaptation, written from the perspective of a student in a remote learning setting.

In 2020 the world of education shifted. The ability to teach and learn in person was no longer an option. Students and teachers were faced with the challenge of remote learning. This presented a learning curve for most. It also revealed an unpopular opinion: There is a lack of depth and adaptation in [specifically high school] teachers today that can lead to a students’ failure.

For over a year I struggled with remote learning. Not because of the content or the structure; in fact, I received better grades and learned more during the first semester of my sophomore year because of the lack of distractions in-person school requires. As the year progressed, it became abundantly clear to all of my fellow students that some teachers adapted well and made classes feel comforting and appropriately challenging. On the flip side, many other teachers did not adapt well and their priorities shifted from the student to filling the space with content that didn’t require students’ participation. Technology-focused learning proved to be more of a barrier to learning than an asset for these teachers. This is not because it is less efficient, more complicated, or too distracting. It is because teachers aren’t able to balance technology and teaching. Prior to remote learning, I witnessed teachers being outright confused by the new applications students and schools use, choosing to work around the technology and instead using paper and pens. Now that so much is online, including the students themselves, there is no way around it anymore; teachers must increase their technological skills in order to effectively teach their students.

As a student who has had many teachers blatantly refuse to adapt, I suggest that school districts, instead of just trying to “get by” in the technological age, should develop programs to teach their staff what they need in order to educate their students effectively. This could be done through a summer class, a series of meetings, or a set of videos. It should cover the basics of navigating the nitty gritty, such as the platform, discuss alternative teaching methods that are applicable to remote learning, and address the crucial yet simple requirements such as appropriate response time and how to have a professional attitude.

Often schools require career professional development; it is required as continuing education. Recent events make me wonder what our teachers are learning given the significant challenges and limitations that were revealed by COVID-19. One part of the puzzle is the employer. Employers will require development but won’t provide time and opportunity for it, instead relying on their employees to figure it out. Expecting employees to spend their personal time on professional development with little to no guidance is often unrealistic, and results in very little progress. Instead of working teachers from sunrise to sunset, we need to reorganize the education and teaching process to be more holistic, taking into account the time teachers need to educate themselves in an ever changing, fast paced environment.

At the same time, however, teachers cannot rely on only what the schools offer. Teachers need to put in the time and effort on their own, or else they will not be able to teach sufficiently. They need to actively try to learn how the applications work, how best to communicate with their students, etc.. Figuring out how to start a meeting and send out assignments _is not enough._ Anyone in a position of leadership where students are affected have to adapt and that’s where professional development comes in.

There is a lot to be said on this topic, and frankly, I’m not qualified to cover it all. But as a student, I can say that I have watched some teachers take the challenge of digital learning head-on and succeed in doing the best they can for their students. Learning new things in such a short amount of time is difficult, and I commend those who are trying. I also want to thank the teachers who did not make me feel like a burden because they were seeing me through a screen.

---
[View this page online](https://www.commandprompt.com/blog/educating-the-educators-the-role-professional-development-plays-for-todays-teachers/)

---

# August PostgresWorld Webinars

> As North America starts to reopen, the PostgresWorld webinar series continues to provide exceptional free content to the community. See below for the August we…

As North America starts to reopen, the PostgresWorld webinar series continues to provide exceptional free content to the community. See below for the August webinars.

  * August 4, 1pm ET: [PostgreSQL HA with Patroni, etcd and HAProxy](<https://postgresconf.org/conferences/2021_Postgres_Conference_Webinars/tickets#>)
  * August 10, 1pm ET: [The NoSQL Store Everyone Ignored](<https://postgresconf.org/conferences/2021_Postgres_Conference_Webinars/tickets#>)
  * August 17, 1pm ET: [Beyond Off-the-Shelf Consensus](<https://postgresconf.org/conferences/2021_Postgres_Conference_Webinars/tickets#>)
  * August 31, 1pm ET: [Will Postgres Live Forever?](<https://postgresconf.org/conferences/2021_Postgres_Conference_Webinars/tickets#>)



People, Postgres, Data Community chat: <https://discord.gg/ghJ6vBKTrd>

[In-Person event Silicon Valley PostgresConf 2022 CFP open!](<https://postgresconf.org/conferences/SV2022>):

---
[View this page online](https://www.commandprompt.com/blog/august-postgresworld-webinars/)

---

# What makes a Postgres contributor?

> In many Open Source communities it is difficult to consider who a contributor is. Some projects take an exclusive view, requiring a direct contribution to be m…

In many Open Source communities it is difficult to consider who a contributor is. Some projects take an exclusive view, requiring a direct contribution to be made to be considered a contributor. Looking at this holistically, we find that the success of a project is found only when there is a mutual connection between the hands-on team and those who support it.Without that connection, PostgreSQL would just be a fever dream of academic pursuit.

Where would Postgres be without the tireless contributions made by volunteers, meetup organizers, the diligent chat and email forum support, the attendance taker at a conference, or free technical blog writers? Every one of these people are important and deserve to be acknowledged. While they may not be on the front lines so to speak, they are building the community in the most critical way: by using and being excited about Postgres. With this in mind I am recognizing the following individuals as Postgres Contributors:

Grant Zhou

A Director of the Chinese PostgreSQL Association

Lloyd Albin

One of the kindest men I have ever met, he organizes Seattle Postgres and has for over a decade. He has also assisted in bug reporting to Postgresql.org, assists in organizing PostgresConf.org, and has been a great resource for users.

Taha Kadado

The founder and organizer of Dallas - Fort Worth Postgres.

Viral Shah

An Organizer of PostgresConf.org and consummate professional behind the scenes.

Debra Cerda

Goat wrangler and Austin Postgres organizer. Debra has been a behind the scenes Postgres advocate and resource for the user community for years.

Amanda M. Nystrom

A PostgresWarrior that only other conference organizers will understand. She is a co-chair of PostgresConference and manages the relationships with PostgresConf.org sponsors.

Mason Sharp

A long time community member and founder of NYC Postgres.

Ryan Lambert

One of the most energetic members of the community I have met and an expert with PostGIS. He has provided many hours of technical support to the community via free webinars and participation in the People, Postgres, Data Discord server.

Who would you recognize as a contributor to the wider Postgres community?

---
[View this page online](https://www.commandprompt.com/blog/what-makes-a-postgres-contributor/)

---

# Maintaining Professionalism While Living With Long-Term Illness

> According to the National Institute of Mental Health (NIMH), nearly 1 in 5 American adults live with some form of mental illness. Per the Center for Disease Co…

According to the National Institute of Mental Health (NIMH), nearly 1 in 5 American adults live with some form of mental illness. Per the Center for Disease Control and Prevention (CDC), 6 in 10 adults in the USA have a chronic disease. Combined, that’s more than 120 _million_ Americans living with chronic health issues today. And yet, despite the sheer number and severity of the issue, mental illness and chronic pain are still taboo, leading many people to fight their fights on their own. Many don’t understand what it’s really like to face chronic illness on a daily basis, and the struggles these illnesses present. Therefore, in honor of Mental Health Awareness Month, Command Prompt has decided to shed light on long-term illnesses, mental _and_ physical.

We are reaching out a helping hand to those who are in need or struggling, especially in these trying times. In light of the COVID-19 Pandemic, many people have experienced isolation and depression, whether it’s been circumstantial or chemical. Given the many barriers to mental and physical health care, we want to help in any way we can, even if it’s just by enabling the conversation. We’ve also added some resources at the bottom of this page, in case anyone reading this is in need of more immediate support.  


As a professional and a student living with mental illness, I know how hard it can be to stay professional and productive when you’re struggling. Chronic illnesses present unique struggles and so I’m here to share some of the things I’ve learned that have helped me. Hopefully, this can help some of you, too.

### It starts with you

Self care starts at home. You can’t neglect your physical and emotional needs at home and expect to be healthy and do great work at the office. Like with many things, it starts with you.

  1.  **Self care.** Take care of yourself - whether it means eating when you’re hungry but don’t want to, resting when you’re in pain but have chores to do, or taking a bubble bath, just ‘cause. Keep in mind, though, that people love to talk about self care as this _magical_ cure-all, where you take a spa day and forget about your worries for a while. However, self care isn’t all rose petals and bath bombs. Sometimes, it means making yourself go to work even when you hate the thought of it, cleaning the house when you just want to let the dust bunnies take over the world, taking your medicine despite the crappy side effects, or brushing your teeth when you just couldn’t care less. Self care is doing things that are good for you, first and foremost, and I cannot stress enough how important that is. You cannot take care of your other responsibilities unless you take care of yourself first. So evict those dust bunnies and get to work - you can take that bubble bath later, I promise.
  2.  **Healthy coping mechanisms.** It can be easy to let your emotions build up. Sometimes it’s stress around work, or struggles with mental health, or interpersonal issues. Whatever it is, effective coping mechanisms will make your emotions that much easier to deal with. Instead of your feelings building up into a giant pile, you start putting them into boxes and neatly stacking them. They’re still there, but now they’re at least manageable. Life can be a never-ending cycle of roles/responsibilities, and we all have our own ways of dealing with it all. But not every coping mechanism is a good one. Many common coping mechanisms are self-destructive and do more harm than good. That can be big things, like, drinking, drugs, and self-harm, but it can also be smaller things, like ignoring your friends or losing your appetite. For me, coping looks like writing songs, listening to music, and cuddling with my dog. While effective coping mechanisms look different for everyone, ensure that it’s effective (meaning, it’s actively decreasing stress levels) and isn’t hurting more than helping.
  3.  **Support system.** You are not alone. Let me repeat; _you are not alone._ No matter how lonely you might feel, no matter how busy people in your life are, no matter how hard it might be to talk about it, _you are not alone_. There is someone in your life that will always be there for you, no matter what, and will gladly help support you in whatever you’re going through. It might be a parent, a sibling, a friend, a partner, or a therapist… whoever it is, don’t keep this from them. Reach out, talk to them, be honest with them, and tell them what you need. Even if all you need is to get it off your chest, there is someone who is more than happy to listen. Talking about it can lighten the load, so to speak, and allowing others to carry some of that burden can give you the space to begin to work through your “boxes”. And if you’re not comfortable talking to them about it, that’s okay, too; just remember that there are resources available to you when it’s time.



### In the workplace

  1.  **Communicate with your coworkers and boss.** You can’t expect anyone to understand or be able to provide support if you don’t tell them what’s going on. While it can be really intimidating to talk to your superiors about this, transparency will go a long way professionally. You may worry that you'll be perceived as less capable, but if they don’t know you’re having a hard time and your performance suffers, that’s when they’ll start to think those things. If you communicate to them what’s going on, what they might see, how they can help, etc., then there might be understanding and flexibility. While not everyone will empathize, it’s better at least to try. And your coworkers will be able to offer support as well, so don’t leave them out of it either, especially those who you consider to be friends or allies. And, as a bonus, your openness may even encourage others to reach out and ask for help when _they_ need it, too.
  2.  **Don’t make excuses or cultivate self pity.** You still have responsibilities even when you’re struggling. You can’t just ignore a deadline and procrastinate because you’re in a bad place. Yes, you can (and should) communicate with your superior if you’re finding it difficult to get the job done, and hopefully this will breed some level of understanding in the appropriate situations. However, that doesn’t mean you can start slacking off or feeling bad for yourself. If you start victimizing yourself or using your struggles as an excuse, you’ll never get anything done. You can work through your struggles on your own time; for right now, put on your big-kid panties and get to work.
  3.  **Set reasonable expectations.** You have to prioritize in order to avoid overworking yourself. If you’re in an especially dark place, and you know that even your best effort won’t result in the usual outcomes, then don’t try to do everything you’re usually capable of doing. It’s okay to put less on your plate if you know you can’t handle it. That doesn’t mean you should sit back and do the bare minimum; you just have to keep in touch with yourself - and your colleagues - to not bite off more than you can chew. If you overwork yourself, you risk going into burnout, and the last thing you need is to burn the candle at both ends. Take a breath, do what you can, and don’t stress about what you can’t.
  4.  **It’s okay to forgive yourself.** You’re doing your best right? Then don’t beat yourself up for your shortcomings. If you mess up, miss a due date, or even straight-up forget a task, it’s okay. Take a breath, own your hiccup, do what you can to fix it, and keep moving forward. Kicking yourself when you’re down isn’t conducive to healing or to productivity. Keep working hard, keep doing your best, and remember: you’re still human, and you can’t expect to be any less flawed than those around you, especially if you’re coping with long-term illness.



### Conclusion

In the end, it is possible to be productive, and successful, and happy, all while struggling with chronic, mental, and invisible illness. It can so easily feel like it’s impossible, like you have no hope and an empty future. But the ball is in your court. The process starts with the choices that you make today. Your first step is working to succeed in wherever you are in life at the moment.

As a final message, I just want to say that you’ve got millions of people who know what it’s like, who are on your side. It’s so easy to feel alone, especially nowadays, but you’re not. And if you feel like you are, here some resources and helplines for people who need help, no matter what it is:

  * National Suicide Prevention Lifeline: (800) 273-8255
  * Crisis Text Line: Text HOME to 741741
  * National Domestic Violence Hotline: (800) 799-7233
  * National Graduate Student Crisis Hotline: (877) 472-3457
  * National Sexual Assault Hotline: (800) 656-4673
  * Child Abuse Hotline: (800) 422-4453
  * CDC National HIV & AIDS Hotline: (800) 342-2437



For even more, go here: <https://helplinedelmor.org/24-hour-crisis-hotline/>  
Or here: https://mindfulstate.com/get-help-now

---
[View this page online](https://www.commandprompt.com/blog/maintaining-professionalism-while-living-with-long-term-illness/)

---

# Redefining Badassery

> Whether it be movies, books, or social media, we are inundated with the attraction of being a badass. It might be the quiet, humble hero or the “genius, billio…

Whether it be movies, books, or social media, we are inundated with the attraction of being a badass. It might be the quiet, humble hero or the “genius, billionaire, playboy, philanthropist.” We look to these people because they are confident in who they are and they make a difference. My stepdaughter’s first swear word was “B.A.” (short for badass because she was terrified of how we’d react if she went around swearing) and whenever she felt great about something she accomplished she’d call herself “B.A.”

For most of my life I chased after the badass title. Think Pepper Potts, not the A-Team. I wanted to contribute to the success of companies and people, have high standards, and make good money while doing it. It came through by becoming an overachieving workaholic, and happily dedicating seven years to the success of Command Prompt’s team and clients. I also wanted to be an adventurer, wildlife photographer, homemaker, and all around cheerful person because life is too short not to be. To me, this was being a badass.

Then in 2020 amongst the COVID panic, I was diagnosed with Hypermobile Ehlers-Danlos Syndrome (hEDS), Fibromyalgia, and MCAS.

Per the [Ehlers-Danlos Society](<https://www.ehlers-danlos.com/what-is-eds/>), “ _Ehlers-Danlos syndromes (EDS) are a group of hereditary disorders of connective tissue that are varied in the ways they affect the body and in their genetic causes. The underlying concern is the abnormal structure or function of collagen and certain allied connective tissue proteins._ ” Check out the [symptoms list](<https://www.nhs.uk/conditions/ehlers-danlos-syndromes/>) and welcome to my chronic pain-filled present and future.

It took months to process the diagnosis, and even then it didn’t seem real because there is no cure. Treatment varies based on the person, and most doctors haven’t heard of the condition. The average time to be diagnosed is over a decade.

Thinking back to everything I’d experienced, it started to make sense. My symptoms weren’t yet debilitating, but they weren’t normal either. I used to kickbox, belly dance, rock climb, backpack, and in the last couple of years I became unable to do those things. I started to hurt every day. My balance got worse, I bruised easier, and I was tired. I became more introverted and preferred books over social outings. I assumed it was the normal process of getting older, but as time went on even that didn’t seem right. The hEDS and Fibromyalgia diagnosis gave me a name to assign to it, and time allowed me to begin the phases of grief that I had to go through to accept that my days of badassery were over.

I gave so much of myself to my company that when I was finally able to process my diagnosis, my main concern outside of how to continue to be a housewife/stepmom was how to continue being a passionate overachiever for the Postgres community and for Command Prompt. How will I be an effective manager when I’m in debilitating pain? How will I lead projects and ensure client success when brain fog hits me? How will I show leadership to my team when I have zero energy?

I fought with this for months, wanting to hide my condition from colleagues and clients in order to keep meeting the high standards I set for myself. When a colleague came to me with a prompt for writing this blog that included my diagnosis, tips and tricks for working with a draining disease, and how to manage chronic pain, I thought “hell no, I’m not writing about that.” Accepting that I have chronic pain that will just get worse as I get older is hard enough; admitting it to all of my professional peers and discussing how I cope is another.

Then I started thinking about others with this diagnosis. Would I ask them to conceal a part of who they are because they want to meet the same standards as everyone else? Would I expect them to not show kindness and grace to themselves when they’re having a day full of pain? No - I would expect them to embrace their condition and be who they are. I would want them to continue to succeed and stand with their team, and have the team know what it takes for that person to show up and still have a smile on their face when they are fighting symptoms most will never experience. I would expect them to stand up and be a light for the rest of us who need to see what true badassery looks like.

Well, shit.

> “They say the power behind something great comes from a place of _vulnerability.”_ \- Brene Brown on the Power of Vulnerability

Awareness is more important than my fear of vulnerability.

I started by participating in the EDS Society’s Acts of Awareness Challenge, addressing prompts across Instagram, Facebook, and Twitter about my personal journey. I set up a website with the goal of helping other [Zebras](<https://www.ehlers-danlos.com/why-the-zebra/>) through this, and I started telling more of my colleagues. I worked with JD Drake, one of my co-owners and best friend, to put out a newsletter to thousands of people about invisible illnesses and EDS from the Postgres Conference. Most importantly, I decided not to let this disease define me and by doing that, I am redefining badassery.

My new version of being a badass is getting S&^% done in a zebra onesie while being out of my comfort zone all of the time. I will have to ask for help, and that’s not something I enjoy doing. I will continue to fight for the success of my team and my clients every day, and I’ll sometimes have to do so with a heating pad. I will have good days and bad days, and on the good days I hope my colleagues are prepared for the pent up productivity I’ll be making up from the bad days (sorry Tiffany). I will advocate and do everything I can to increase awareness for this disease, hoping that someday there is a cure.

The more I think about chronic conditions, from cancer to EDS to mental illness, I can’t help but think, “wow.” I spent so many years unaware of the challenges they face every day. We get wrapped up in first world problems that we fail to open our eyes to people in our own lives who have something beyond the normal. We make snap judgements, and we don’t take enough time to get to know what people are really going through. I hope that someday this changes.

For those who have a chronic condition and keep going, I stand vulnerable for you. To those with EDS, Fibromyalgia, and chronic pain. To those who are disabled. To those who have given up their dreams because of a medical condition. To those who stand beside and fight beside those who have a chronic condition. To those who are considerate and kind to the genetically faulty. To those who overcome whatever life throws at them, chronic condition or not.

You are the ones we should look up to. You are the ones our children should be learning about. You deserve the applause that is given to fictional characters on our screens. You have to work harder and suffer more. You have to be more cautious and fight longer. You are a warrior every day you get up and don’t give up. You are one of those who define badassery.

---
[View this page online](https://www.commandprompt.com/blog/redefining-badassery/)

---

# Docker Logging With RSyslog

> Docker offers quite a few options for storing log files. However, the traditional syslog format remains one of the most flexible to this day. Chances are you&#x27;r…

Docker offers quite a few options for storing log files. However, the traditional syslog format remains one of the most flexible to this day. Chances are you're familiar with the concept of a central logging server. It is an indispensable component in any infrastructure that is incredibly convenient and powerful. It allows for easier audits, managing and archiving of log files in a very controlled and secure manner.

We're going to explore and show how to configure Docker to write container logs in syslog format on Docker hosts as well as how to forward to and store those log files on a centrally managed logs server.

##  **The Big Picture**

Before we go into the details, let's take a moment to look at what kind of logging system we want to implement.

On a Docker host, processes in containers send their logging output to STDOUT and STDERR. A Docker daemon routes logs to /dev/log, which is a symlink to AF_UNIX socket of datagram-oriented (SOCK_DGRAM) type /run/systemd/journal/dev-log. Rsyslog running on the same Docker host listens on /dev/log and collects, parses and writes Docker containers logs in a structured format. Each log entry is tagged with container name. Each container gets an individual log file under /var/log/docker directory. Rsyslog also sends the logs to a logs host via RELP protocol.

On Rsyslog host, the logs are received via the RELP protocol (uses TCP for transmitting data), processed, sorted and stored in the central logs archive directory under /var/log/central. Each Docker host gets its own directory named after the Docker host hostname. Each container also has an individual log file.

Logrotate is configured on the Docker host and logs host to compress and prune old logs.

##  **Default Docker Logging Configuration**

How Docker captures and where it writes out logs depends on what logging driver is used. Logging drivers cover a range of options from local files to remote logging destinations. Currently, the options are:

  * local file (file-based storage in binary format)
  * Logentries
  * local files in JSON format
  * Greylog Extended Format (GELF)
  * Syslog
  * Amazon CloudWatch
  * ETW (Event Tracing in Windows)
  * Fluentd
  * Google Cloud
  * Journald (systemd) and
  * Splunk.  




By default, Docker writes container logs in JSON format using the "json-file" logging driver. The log files generated by this logging driver are stored locally in container directories.

###  **The Two-Tier Logging Configuration**

Docker has a two-tier logging configuration. There's Docker daemon (dockerd) logging configuration and containers logging configuration. The Docker daemon logging settings define default logging configuration for any new container. Newly created containers inherit Docker daemon logging driver settings. However, the default settings can be overridden when a new container is created.

Let's take a closer look at how this works.

To determine which logging driver is currently used as a default for Docker daemon we need to run docker info command:
    
    
    admin@dockerhost:~$ sudo docker info | grep Logging
    WARNING: No swap limit support
    Logging Driver: json-file

If we create a new container and generate some output to STDOUT:
    
    
    admin@dockerhost:~$ sudo docker run -td ubuntu echo "Test log entry"
    7317241f66bd56b5d9c35440ee68a66b29eaa4b88efb1615bcc231153632c6dc

We'll see that the newly created container inherited Docker daemon logging settings and it is configured to write logs via the json-file logging driver:
    
    
    admin@dockerhost:~$ sudo docker inspect 7317241f66bd | grep -A 3 LogConfig
    "LogConfig": {
    "Type": "json-file",
    "Config": {}
    },

As it was mentioned earlier, the default json-file logging driver stores log files locally on Docker host in container directories.
    
    
    admin@dockerhost:~$ sudo cat /var/lib/docker/containers/7317241f66bd56b5d9c35440ee68a66b29eaa4b88efb1615bcc231153632c6dc/7317241f66bd56b5d9c35440ee68a66b29eaa4b88efb1615bcc231153632c6dc-json.log
    {"log":"Test log entry\r\n","stream":"stdout","time":"2021-03-22T10:52:48.128860524Z"}

One can override default Docker hostwide logging settings and create a new container that will use a different logging driver.
    
    
    admin@dockerhost:~$ sudo docker run --log-driver syslog --log-opt syslog-address=unixgram:///dev/log -td ubuntu echo "Test log entry"
    594112caf3edb97711fe460e87b6de2a3dd2c65634b2d74e44e627da424af47d

Inspect the new container logging configuration and we can see that it uses syslog logging driver with options all set from the command line.
    
    
    admin@dockerhost:~$ sudo docker inspect 594112caf3ed | grep -A 5 LogConfig
    "LogConfig": {
    "Type": "syslog",
    "Config": {
    "syslog-address": "unixgram:///dev/log"
    }
    },

As expected, there's no log file in the container directory now.
    
    
    admin@dockerhost:~$ sudo ls -la /var/lib/docker/containers/594112caf3edb97711fe460e87b6de2a3dd2c65634b2d74e44e627da424af47d
    total 44
    drwx-----x 4 root root 4096 Mar 22 11:27 .
    drwx-----x 5 root root 4096 Mar 22 11:27 ..
    drwx------ 2 root root 4096 Mar 22 11:27 checkpoints
    -rw------- 1 root root 2343 Mar 22 11:27 config.v2.json
    -rw-r----- 1 root root 43 Mar 22 11:27 container-cached.log
    -rw-r--r-- 1 root root 1507 Mar 22 11:27 hostconfig.json
    -rw-r--r-- 1 root root 13 Mar 22 11:27 hostname
    -rw-r--r-- 1 root root 174 Mar 22 11:27 hosts
    drwx-----x 2 root root 4096 Mar 22 11:27 mounts
    -rw-r--r-- 1 root root 585 Mar 22 11:27 resolv.conf
    -rw-r--r-- 1 root root 71 Mar 22 11:27 resolv.conf.hash

The test log entry was sent to a system socket at /dev/log, which on a systemd-based Linux distribution is a symlink to journald AF_UNIX socket of datagram-oriented (SOCK_DGRAM) type /run/systemd/journal/dev-log. journald uses this socket for receiving syslog messages and for forwarding them to any other syslog daemon.

It means that our test log entry made via the syslog logging-driver should appear in journald records and one of the system logs created by rsyslogd on Docker host.
    
    
    admin@dockerhost:~$ sudo journalctl -u docker.service | grep "594112caf3ed\[.*\]"
    Mar 22 11:27:02 dockerhost 594112caf3ed[9447]: Test log entry
    
    
    admin@dockerhost:~$ sudo grep -r "594112caf3ed\[.*\]" /var/log/
    /var/log/syslog:Mar 22 11:27:02 dockerhost 594112caf3ed[9447]: Test log entry

The logging-driver settings provided on the command line are permanent. You can stop and start containers and the logging settings will persist.

If you delete a container and recreate it, default Docker daemon settings will be used unless you override them again with --log-driver and --log-opt command line flags.

Unfortunately, logging driver settings cannot be changed for existing containers. A container must be deleted and recreated with desired logging configuration settings.

##  **Logging With Rsyslog. Docker Host Configuration.**

###  **Docker**

Now that we understand how the Docker syslog logging driver works, let's build a logging system where Docker logs are routed to and processed by rsyslog daemon.

rsyslogd running on Docker host will collect, process and write Docker containers logs in a structured format that we'll define to meet our requirements. Each log entry will be tagged with container name to allow for easier identification, differentiation, analysis, sorting and grouping of log entries. Each container will have an individual log file under /var/log/docker directory. Finally, rsyslogd on Docker host will send all logs generated on docker host to a logs host via Reliable Event Logging Protocol (RELP) protocol.

We start by defining global logging configuration settings for Docker daemon and thus effectively all new containers.
    
    
    admin@dockerhost:~$ cat /etc/docker/daemon.json
    {
    "log-driver": "syslog",
    "log-opts": {
    "syslog-address": "unixgram:///dev/log",
    "tag" : "docker/{{.Name}}"
    }
    }

Here we use the syslog logging driver and tell dockerd explicitly to use /dev/log system socket. We also specify with unixgram:// that the /dev/log socket type is datagram-oriented as opposed to unix://, which is used for stream-oriented type of sockets.

Then, we define the format for our syslog message tag. The {{.Name}} will be replaced by a container name. Thus, the "docker/{{.Name}}" tag will become, for example, "docker/bold_mendeleev".

This docker "tag" log option matches rsyslog syslogtag property and can be used in logical expressions as well as for customizing filesystem paths in rsyslog configuration. There are other template markups similar to {{.Name}} that can be used to build a unique syslogtag property. However, keep in mind that by default size for syslogtag is limited (by RFC standards) to 32 characters. The syslog tag suggested in our examples requires less than that and makes the tag property both functional and compliant with the standards.

It is possible to overcome the 32 character limit in case you really need to have longer container names or use full-length 64-character container ID's. You can read more about this [here](<https://www.rsyslog.com/sende-messages-with-tags-larger-than-32-characters/>).

If daemons.json is already present, add or modify the logging configuration settings as necessary. If daemon.json does not exist yet, simply create the file and copy-paste the block of JSON code shown above. Make sure the file is owned by root:root and permissions mode is set to 0644.

This is all you need to do to configure Docker daemon.

Before we move on to rsyslog configuration, let us first create a new docker container and execute a command that will generate one log entry every 60 seconds. This way we can easily confirm if logging works as we work on setting up our logging system.
    
    
    admin@dockerhost:~$ sudo docker run --hostname container0 --name container0 -it ubuntu
    root@container0:/# c=0; while true; do echo "$c: $(date) $HOSTNAME"; c=$((c+1)); sleep 60; done
    0: Mon Mar 22 14:19:19 UTC 2021 container0
    ...

Press Ctrl+P+Q to detach from the container.

Confirm that the container is still running:
    
    
    admin@dockerhost:~$ sudo docker ps | grep container0
    container0 ubuntu "/bin/bash" 2 minutes ago Up About a minute container0

The "Up About a minute" field tells us that the container is up and has been running for that long.

Verify that the while loop in the container is generating log messages and they're written to system log files:
    
    
    admin@dockerhost:~$ sudo grep -r "container0\[.*\]:" /var/log/
    ...
    /var/log/syslog:Mar 22 14:19:19 dockerhost docker/container0[10742]: 0: Mon Mar 22 14:19:19 UTC 2021 container0
    /var/log/syslog:Mar 22 14:20:19 dockerhost docker/container0[10742]: 1: Mon Mar 22 14:20:19 UTC 2021 container0
    /var/log/syslog:Mar 22 14:21:19 dockerhost docker/container0[10742]: 2: Mon Mar 22 14:21:19 UTC 2021 container0
    /var/log/syslog:Mar 22 14:22:19 dockerhost docker/container0[10742]: 3: Mon Mar 22 14:22:19 UTC 2021 container0

###  **Rsyslog**

To configure Rsyslog on Docker host we will need to update /etc/rsyslog.conf and create two new configuration include files in /etc/rsyslog.d/ directory: 00-logshost.conf and 10-docker.conf.

Open /etc/rsyslog.conf and add the following configuration statement to "GLOBAL DIRECTIVES" section:
    
    
    $PreserveFQDN on

The $PreserveFQDN statement accepts either on or off. When set to on, it ensures that fully-qualified domain names are used in log messages.

Now create /etc/rsyslog.d/10-docker.conf with the following contents:
    
    
    admin@dockerhost:~$ cat /etc/rsyslog.d/10-docker.conf
    $FileCreateMode 0644
    $template DockerDaemonLogFileName,"/var/log/docker/docker.log"
    $template DockerContainerLogFileName,"/var/log/docker/%SYSLOGTAG:R,ERE,1,FIELD:docker/(.*)\[--end:secpath-replace%.log"
    if $programname == 'dockerd' then {
    ?DockerDaemonLogFileName
    stop
    }
    if $programname == 'containerd' then {
    ?DockerDaemonLogFileName
    stop
    }
    if $programname == 'docker' then {
    if $syslogtag contains 'docker/' then {
    ?DockerContainerLogFileName
    stop
    }
    }
    $FileCreateMode 0600

In this configuration file we make sure that Docker container log files will have permissions mode set to 0644. The DockerLogFileName template defines location and filenames for the containers log files.

If you're not familiar with rsyslog property replacement syntax the "%SYSLOGTAG:R,ERE,1,FIELD:docker/(.*)\\[--end:secpath-replace%.log" bit probably looks quite confusing and intimidating.

What it means is that the template filename path will be set to /var/log/docker/{{.Name}}.log. Here {{.Name}} is equivalent to dockerd log option "tag" we saw a bit earlier in the example /etc/docker/daemon.json file.

The following if ... then expressions test if programname property matches 'dockerd', 'containerd' or 'docker' string for each syslog message that is being processed by rsyslog. The first two expressions ensure that docker daemon logs are written to the /var/log/docker/docker.log file.

The last if ... then expression is a little different. It compares if the programname property matches 'docker' string. If there is a match, one more test is done to see if syslogtag, another syslog message property, contains 'docker/' string. This is where our custom tag "docker/{{.Name}}" comes into play. If the test evaluates to True, rsyslog will use the DockerLogFileName template to create a log file named /var/log/docker/{{.Name}}.log and write the syslog message that is being processed to this file.

Finally, the "stop" word is a discard action that tells rsyslog to stop processing the current syslog message and move on to the next one. Effectively, this ensures that docker log messages are only written to the files referenced by the DockerDaemonLogFileName and DockerContainerLogFileName templates.

To validate the new configuration file run
    
    
    admin@dockerhost:~$ sudo rsyslogd -f /etc/rsyslog.d/10-docker.conf -N1
    rsyslogd: version 8.32.0, config validation run (level 1), master config /etc/rsyslog.d/10-docker.conf
    rsyslogd: End of config validation run. Bye.

If rsyslog encounters any errors when parsing the configuration file, it will issue a warning and give you a hint as to what the problem might be and where it is located. For example, here's what happens if you intentionally break the first if ... then clause by writing 'if' statement as 'xxif':
    
    
    admin@dockerhost:~$ sudo rsyslogd -f /etc/rsyslog.d/10-docker.conf -N1
    rsyslogd: version 8.32.0, config validation run (level 1), master config /etc/rsyslog.d/10-docker.conf
    rsyslogd: error during parsing file /etc/rsyslog.d/10-docker.conf, on or before line 11: warnings occured in file '/etc/rsyslog.d/10-docker.conf' around line 11 [v8.32.0 try http://www.rsyslog.com/e/2207 ]
    rsyslogd: invalid or yet-unknown config file command 'programname' - have you forgotten to load a module? [v8.32.0 try http://www.rsyslog.com/e/3003 ]
    rsyslogd: error during parsing file /etc/rsyslog.d/10-docker.conf, on or before line 20: syntax error on token '}' [v8.32.0 try http://www.rsyslog.com/e/2207 ]
    rsyslogd: CONFIG ERROR: could not interpret master config file '/etc/rsyslog.d/10-docker.conf'. [v8.32.0 try http://www.rsyslog.com/e/2207 ]

As soon as you restart rsyslogd on Docker host, you should see Docker containers log files in /var/log/docker directory:
    
    
    admin@dockerhost:~$ sudo ls -la /var/log/docker/
    total 20
    drwxr-xr-x 2 syslog syslog 4096 Mar 22 14:24 .
    drwxrwxr-x 9 root syslog 4096 Mar 22 06:25 ..
    -rw-r--r-- 1 syslog adm 110 Mar 22 14:24 container0.log
    -rw-r--r-- 1 syslog adm 2833 Mar 22 10:48 container1.log
    -rw-r--r-- 1 syslog adm 2815 Mar 22 10:48 container2.log
    -rw-r--r-- 1 syslog adm 595 Mar 22 14:25 docker.log

Log messages printed to STDOUT and STDERR in containers are sent by Docker daemon to /dev/log system socket. Rsyslog collects these logs from the socket, processes them and writes to /var/log/docker/{{.Name}}.log files. Each container has a dedicated log file.

Now that that's been taken care of, we can also send these log messages to a remote logs host.

Create /etc/rsyslog.d/00-logshost.conf.
    
    
    admin@dockerhost:~$ cat /etc/rsyslog.d/00-ship.conf
    $ActionQueueType LinkedList # use asynchronous processing
    $ActionQueueFileName forward # file name; enables disk mode
    $ActionResumeRetryCount -1. # infinite retries on insert failures
    $ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
    $ModLoad omrelp
    *.* :omrelp:10.8.7.52:2514 # IP address of the logs host

Restart rsyslog on the Docker host.

##  **Logging With Rsyslog. Logs Host Configuration.**

On logs host, create /etc/rsyslog.d/00-remote.conf with the following contents.
    
    
    module(load="imrelp")
    input(type="imrelp" port="2514" ruleset="RemoteLogProcess")
    $template PerHostAuth,"/var/log/central/%HOSTNAME%/auth.log"
    $template PerHostCron,"/var/log/central/%HOSTNAME%/cron.log"
    $template PerHostDaemon,"/var/log/central/%HOSTNAME%/daemon.log"
    $template PerHostDebug,"/var/log/central/%HOSTNAME%/debug.log"
    $template PerHostKern,"/var/log/central/%HOSTNAME%/kern.log"
    $template PerHostLpr,"/var/log/central/%HOSTNAME%/lpr.log"
    $template PerHostMail,"/var/log/central/%HOSTNAME%/mail.log"
    $template PerHostMailInfo,"/var/log/central/%HOSTNAME%/mail.info.log"
    $template PerHostMailWarn,"/var/log/central/%HOSTNAME%/mail.warn.log"
    $template PerHostMailErr,"/var/log/central/%HOSTNAME%/mail.err.log"
    $template PerHostMessages,"/var/log/central/%HOSTNAME%/messages.log"
    $template PerHostNewsCrit,"/var/log/central/%HOSTNAME%/news.crit.log"
    $template PerHostNewsErr,"/var/log/central/%HOSTNAME%/news.err.log"
    $template PerHostNewsNotice,"/var/log/central/%HOSTNAME%/news.notice.log"
    $template PerHostSyslog,"/var/log/central/%HOSTNAME%/syslog.log"
    $template PerHostUser,"/var/log/central/%HOSTNAME%/user.log"
    $template PerHostDockerDaemonLogFileName,"/var/log/central/%HOSTNAME%/docker/docker.log"
    $template PerHostDockerContainerLogFileName,"/var/log/central/%HOSTNAME%/docker/%SYSLOGTAG:R,ERE,1,FIELD:docker/(.*)\[--end:secpath-replace%.log"
    ruleset(name="RemoteLogProcess" queue.type="fixedarray") {
    $FileCreateMode 0644
    if $programname == 'dockerd' then {
    ?PerHostDockerDaemonLogFileName
    stop
    }
    if $programname == 'containerd' then {
    ?PerHostDockerDaemonLogFileName
    stop
    }
    if $programname == 'docker' then {
    if $syslogtag contains 'docker/' then {
    ?PerHostDockerLogFileName
    stop
    }
    }
    auth,authpriv.* ?PerHostAuth
    *.*;auth,authpriv.none -?PerHostSyslog
    cron.* ?PerHostCron
    daemon.* -?PerHostDaemon
    kern.* -?PerHostKern
    lpr.* -?PerHostLpr
    mail.* -?PerHostMail
    user.* -?PerHostUser
    mail.info -?PerHostMailInfo
    mail.warn -?PerHostMailWarn
    mail.err ?PerHostMailErr
    news.crit ?PerHostNewsCrit
    news.err ?PerHostNewsErr
    news.notice -?PerHostNewsNotice
    *.=debug;\
    auth,authpriv.none;\
    news.none;mail.none -?PerHostDebug
    *.=info;*.=notice;*.=warn;\
    auth,authpriv.none;\
    cron,daemon.none;\
    mail,news.none -?PerHostMessages
    }
    $FileCreateMode 0640

This configuration does two main things.

It tells rsyslog how to process general system logs (/var/log/auth.log, /var/log/syslog, etc.) received from any host that is sending its logs to this logs host.

There are also configuration statements that tell rsyslog how to process Docker logs. You can see that configuration statements are almost identical to those we used on Docker host as we want to have a similar filesystem layout, file names and permissions on the logs host. We also use the same property replacement expressions to extract Docker container names and use that as part of log files names.

In the now familiar-looking recursive if ... then logical expressions we subject each log message to the same tests as on the Docker host and take essentially the same actions: write matching log messages to /var/log/central/%HOSTNAME%/docker/docker.log and /var/log/central/%HOSTNAME%/docker/{{.Name}}.log files and stop processing of a syslog message thus ensuring that rsyslog writes Docker logs only to the log files that we want and not any other files.

One minor difference is the use of %HOSTNAME% property which is replaced by a fully-qualified domain name of the host that generated and/or sent a log message to the logs host.

The imrelp module listens on TCP port 2514 for a stream of data generated by omrelp module on our example Docker host and any other host that's configured to send log stream data to the logs host. The RELP protocol extends the functionality of the syslog protocol and provides a more reliable method for sending and receiving log messages.

The general system logs will be created in /var/log/central/%HOSTNAME%/ directories for each host that sends its logs to the logs host. Traditional syslog facilities (daemon.*, cron.*, kern.*, etc.) are used to filter (select) log messages and corresponding templates are used to instruct rsyslogd where to write those messages.

Now, save the changes and restart rsyslog:
    
    
    admin@logshost:~$ sudo systemctl restart rsyslog

Wait for a few minutes and confirm that general system log files are being written to the correct destination:
    
    
    admin@logshost:~$ sudo ls -la /var/log/central/dockerhost/
    total 360
    drwxr-xr-x 3 syslog syslog 4096 Mar 22 09:23 .
    drwxr-xr-x 3 syslog syslog 4096 Mar 16 18:15 ..
    -rw-r--r-- 1 syslog adm 95493 Mar 22 18:17 auth.log
    -rw-r--r-- 1 syslog adm 27829 Mar 22 18:17 cron.log
    -rw-r--r-- 1 syslog adm 54804 Mar 22 18:26 daemon.log
    drwxr-xr-x 2 syslog syslog 4096 Mar 22 17:19 docker
    -rw-r--r-- 1 syslog adm 15476 Mar 22 17:20 kern.log
    -rw-r--r-- 1 syslog adm 20882 Mar 22 17:20 messages.log
    -rw-r--r-- 1 syslog adm 104135 Mar 22 18:26 syslog.log
    -rw-r--r-- 1 syslog adm 1272 Mar 21 07:00 user.log

and that Docker logs are being received and written out as well:
    
    
    admin@logshost:~$ sudo ls -la /var/log/central/dockerhost/docker/
    [sudo] password for admin:
    total 52
    drwxr-xr-x 2 syslog syslog 4096 Mar 22 17:19 .
    drwxr-xr-x 3 syslog syslog 4096 Mar 22 09:23 ..
    -rw-r--r-- 1 syslog adm 29254 Mar 22 17:19 container0.log
    -rw-r--r-- 1 syslog adm 3053 Mar 22 10:48 container1.log
    -rw-r--r-- 1 syslog adm 2925 Mar 22 10:48 container2.log
    -rw-r--r-- 1 syslog adm 605 Mar 22 14:32 docker.log

That is all that you have to do to configure rsyslogd on the logs host.

Of course, there are quite a few more things to do to make the logging system more secure and performant. Communications of rsyslogd daemons via RELP protocol could benefit from TLS encryption. You may need to fine-tune rsyslogd and Docker configurations to ensure optimal performance in your environment and so on.

###  **Managing Log Files**

There is perhaps one more thing left to do. A finishing touch. We need to compress and rotate older log files both on our Docker host as well as the logs host.

The old trusty logrotate is one way to do it.

On the Docker host you might want to use a logrotate config like this:
    
    
    admin@dockerhost:~$ sudo cat /etc/logrotate.d/rsyslog-docker
    /var/log/docker/*.log
    {
    daily
    rotate 10
    minsize 200M
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
    /usr/lib/rsyslog/rsyslog-rotate
    endscript
    }

And on the logs host like this:
    
    
    admin@logshost:~$ cat /etc/logrotate.d/rsyslog-central
    /var/log/central/*/*.log /var/log/central/*/*/*.log
    {
    daily
    rotate 10
    minsize 200M
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
    /usr/lib/rsyslog/rsyslog-rotate
    endscript
    }

These are pretty standard configs. Note that they take care of Docker logs and general system logs in the /var/log/central directories.

The general system logs on both Docker host and the logs host are already managed by /etc/logrotate.d/rsyslog which is installed by default on, for example, Ubuntu 18 LTS systems.

 **Conclusion**

You can think of this particular setup as a foundation for perhaps most of your logging needs. Modern logs collection and analysis systems such as ELK, Fluentd and others can now be easily integrated into your logging infrastructure by configuring rsyslogd to send any and all logs from a single central location to those systems.

And there you have it. Docker logs fully managed by Rsyslog.

Let us know if you found this tutorial useful or if you have any questions!

---
[View this page online](https://www.commandprompt.com/blog/docker-logging-with-rsyslog/)

---

# Machine Learning 2.0: Living My Sophomore Year as a Digital Nomad

> I’ve always lived in a tech-forward household. My dad, being a software consultant, always had computers around. My sibling and I were home-schooled throughout…

I’ve always lived in a tech-forward household. My dad, being a software consultant, always had computers around. My sibling and I were home-schooled throughout my elementary school years, so we spent much of our time on our laptops. As a result, I consider myself to be pretty familiar and comfortable with technology as a whole. Now, being in my sophomore year of high school during this pandemic, this skill has allowed me an advantage over many adults, and even my peers, during remote learning. When the time came for us all to learn and work from home, my family saw it as an opportunity – a chance to travel the United States on our own terms.

### How This Works

We (my family and I) have converted a school bus into an RV of sorts. It has a bed, a refrigerator and freezer, counters, a couch, and plenty of storage; it’s essentially a home-on-wheels. This set-up allows us to take relatively long road trips around the continental U.S.

As I’m writing this, we’re on a four-week adventure: I say “adventure” because that’s really what they are. We don’t just plot out a route to take us to various destinations. A big part of our trips is improvisation; choosing on the spot where we want to go, what direction we’re headed, how long we want to take, etc. We start with a general idea – I wanted to see Meteor Crater in Arizona, my dad wanted to see Tombstone, Arizona, and my stepmom wanted to see Saguaro cacti, so we made Arizona our end game. There’s a lot of space between Washington and Arizona, so we decided what to see in between those points. We went to Hurricane, Utah on our way, and we originally wanted to head through Las Vegas. Unfortunately, an unexpected heat wave rolled through that area, so instead we headed east to Two Guns, Arizona.

### Remote Learning

Learning from home is different for everyone. For me, it means getting up at 8 am, sitting in the dining room and joining class meetings for the next four hours. What we do in class has mostly stayed the same; say good morning, take attendance, explain assignments, etc. What’s different is the _way_ we do these things; we turn on our microphones to answer questions, the teacher shares their screen to go over the assignment, kids fall asleep during class and no one can tell. Everyone, especially teachers, have had to learn a different way of doing things. We have had to adapt, and although everyone is still eager to get back to an in-person learning environment, for the most part it really hasn’t been as bad as people say it is.

I know I’m privileged in this way. My family has always had access to what we need, including the technology necessary to remote learning. There are many families who aren’t the same, and who genuinely do struggle with remote learning, for many reasons, like no internet access, no at-home computers, or no one to watch kids at home. I’m not at all trying to invalidate that, but at the same time, I know many people who complain about remote learning are in a similar situation as I am, and therefore exaggerate how bad it really is for them.

### What I’ve Learned

For decades, people thought a classroom was a necessary component to education. But COVID-19 has provided an opportunity to prove that there’s so much more to learning than sitting behind a desk and (pretending to) take notes. Learning should both be, and happen through, _experience._ I’ve learned things on this trip I’m not going to forget. I learned about the locations we visited, yes, but I had more important lessons, too. I finally grasped _why_ we take these trips; not just to see all there is to see, but to grow closer as a family. In the past, I resented these trips; I wanted to stay home and play video games, as cliché as it sounds. But this time I decided to stop thinking about going home the whole time and just live in the _now_ and appreciate what I was being given, and it was that decision that allowed me to see the real reason behind it all.

There’s a distance in many families that my dad and stepmom will not allow in our family. We travel together to spend time with and to grow closer to each other. Of course, there are times when we need to get away from each other; being trapped together in a 70-square-foot bus for weeks at a time will do that to anyone. But it just makes us appreciate our time together that much more.

When I have my own kids, as cliché as it is, I’m not going to tell them about that meme I saw in seventh grade or that show we watched one night. I’m going to tell them about our reactions to the reenactments of famous gunfights in Tombstone, or my dad and I going on a ride in the Meteor Crater visitor center that was clearly meant for kids but was super fun anyway. Or (gross alert) that time I projectile vomited all over the bus that led to me holding a bowl with me at all times while traveling. _Those_ are the fun, silly, sometimes gross stories that I want to be able to tell them.

### Why This Matters

We’re all struggling right now. Lifestyles have changed, routines have been disrupted, plans have been thrown out the window, and mental health has plummeted. Many people are hoping to go back to the way things were _before_ the virus, but the fact is, nothing is ever going to be the same. Companies are realizing they don’t need offices, teachers are being forced to finally learn how to use technology, kids (and adults) are learning how to live without their friends.

When the world changed, we changed along with it. But one thing that has never, and will never, change, is the human and animal instinct to survive. We survived this, and we’ll survive whatever comes our way next. There is always a silver lining, even on the darkest of clouds, and for me, that silver lining was bonding with my family in a way that many families don’t get to. What’s your silver lining?

(P.S. If you can, take a trip to Tombstone; there’s nothing quite like watching men with fake mustaches pretending to have a shoot-out in the Arizona sun.)

---
[View this page online](https://www.commandprompt.com/blog/machine-learning-20-living-my-sophomore-year-as-a-digital-nomad/)

---

# Episode Four and Five of: More than a refresh available

> A couple of our recent podcasts are directly related to PostgreSQL, they are listed below. I have really enjoyed meeting the people behind the technology that …

A couple of our recent podcasts are directly related to PostgreSQL, they are listed below. I have really enjoyed meeting the people behind the technology that drives PostgreSQL in the global community. A lot of us are used to collectively gathering a few times a year with conferences. Obviously the pandemic has put a halt to that but launching the podcast has allowed me to connect with some amazing folks.

## Episode Four: Daniele Varrazzo, Creator of Python Driver Psycopg3

Listen in as he discusses Open Source licensing, "humble" drivers, photography, and the nature of adapt or die with Daniele Varrazzo, Creator of Python Driver Psycopg3.

[Listen Now.](<https://anchor.fm/more-than-a-refresh/episodes/Episode-Four-Daniele-Varrazzo--Creator-of-Python-Driver-Psycopg3-ermrt9>)

## Episode Five: Erik Brandsberg, Founder and Chief Architect of Heimdall Data

Welcome to episode five of More than a Refresh, with Joshua "JD" Drake. Listen in as he and Heimdall Data Founder, Erik Brandsberg, discuss demonstrating value to potential clients, visiting 40 countries in 40 years, and how automated caching and read/write split are really one in the same.

[Listen now.](<https://anchor.fm/more-than-a-refresh/episodes/Episode-Five-Erik-Brandsberg--Founder-and-Chief-Architect-of-Heimdall-Data-eva8fg>)

---
[View this page online](https://www.commandprompt.com/blog/episode-four-and-five-of-more-than-a-refresh-available/)

---

# Reverse DNS Zones With AWS Simple AD

> Consider a fairly complex design of a DNS service in AWS cloud: one that includes native AWS Route 53, AWS Simple AD and traditional BIND service running on EC…

Consider a fairly complex design of a DNS service in AWS cloud: one that includes native AWS Route 53, AWS Simple AD and traditional BIND service running on EC2 instances to cater to different needs of development and production environments in terms of serving DNS requests and providing directory services.

All EC2 hosts in one of your production VPCs are pointed to Simple AD DNS servers that are your primary DNS servers for this VPC and associated subnets.

You need to configure reverse DNS lookups to be able to resolve PTR records by using the DNS service provided by the Simple AD. Additionally, you would like to manage PTR records using command line interface from one of the EC2 instances running Linux in the same VPC.

That's probably mind-boggling enough already if you don't work with DNS and Active Directory on a daily basis.

On top of that, there's a hard requirement:

You can't cheat your way out of this by using the friendly AWS Management Console to create and edit a Route 53 hosted zone.

So, how does one configure reverse DNS lookups when using Simple AD DNS service? You need an EC2 host running Linux that can talk to Simple AD DNS servers and tools to query and modify DNS configuration.

Repurpose or designate an existing, suitable EC2 instance as Simple AD control host. Alternatively, provision a dedicated EC2 instance.

To keep this discussion focused on managing DNS zones, we'll assume you opted for the latter and that you also have Simple AD already provisioned.

Once the new EC2 instance is up and running it needs to be configured.

Note: All commands and configuration examples were tested on Debian GNU/Linux 9.13 (stretch).

Set a hostname and configure /etc/hosts.
    
    
    $ sudo hostnamectl set-hostname sadch
    $ cat /etc/hosts
    127.0.1.1 sadch.yourcompany.com sadch

Install ntpdate and sync the system clock against Simple AD.
    
    
    $ sudo apt-get install ntpdate
    $ sudo ntpdate -q sad.yourcompany.com
    $ sudo ntpdate sad.yourcompany.com

Install samba-tool and Kerberos authentication tools.
    
    
    $ sudo apt-get install krb5-config krb5-user samba-common-bin

On a Debian-based system a curses dialog will be presented to configure Kerberos realm. Enter SAD.YOURCOMPANY.COM (use upper case) for the default Kerberos realm.

If asked to provide Kerberos servers for the realm and administrative server for your Kerberos realm, enter sad.yourcompany.com (use lower case) as answers to both questions.

With Kerberos installed and configured, obtain and cache an initial ticket-granting ticket.
    
    
    $ kinit Administrator
    Password for Administrator@SAD.YOURCOMPANY.COM:

Here Administrator is Simple AD administrator account.

Review results of the kinit command.
    
    
    $ klist
    Ticket cache: FILE:/tmp/krb5cc_1000
    Default principal: Administrator@SAD.YOURCOMPANY.COM
    Valid starting  Expires Service principal
    03/18/2021 02:48:09 03/19/2021 02:48:01 krbtgt/SAD.YOURCOMPANY.COM@SAD.YOURCOMPANY.COM

You're now all set up and ready to work with Simple AD DNS.

To start, inspect zones that are controlled by Simple AD DNS servers.
    
    
    $ samba-tool dns zonelist sad.yourcompany.com
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    3 zone(s) found
    pszZoneName  : sad.yourcompany.com
    Flags  : DNS_RPC_ZONE_DSINTEGRATED DNS_RPC_ZONE_UPDATE_SECURE 
    ZoneType : DNS_ZONE_TYPE_PRIMARY
    Version  : 50
    dwDpFlags  : DNS_DP_AUTOCREATED DNS_DP_DOMAIN_DEFAULT DNS_DP_ENLISTED 
    pszDpFqdn  : DomainDnsZones.sad.yourcompany.com
    pszZoneName  : 0.20.in-addr.arpa
    Flags  : DNS_RPC_ZONE_DSINTEGRATED DNS_RPC_ZONE_UPDATE_SECURE 
    ZoneType : DNS_ZONE_TYPE_PRIMARY
    Version  : 50
    dwDpFlags  : DNS_DP_AUTOCREATED DNS_DP_DOMAIN_DEFAULT DNS_DP_ENLISTED 
    pszDpFqdn  : DomainDnsZones.sad.yourcompany.com
    pszZoneName  : _msdcs.sad.yourcompany.com
    Flags  : DNS_RPC_ZONE_DSINTEGRATED DNS_RPC_ZONE_UPDATE_SECURE 
    ZoneType : DNS_ZONE_TYPE_PRIMARY
    Version  : 50
    dwDpFlags  : DNS_DP_AUTOCREATED DNS_DP_FOREST_DEFAULT DNS_DP_ENLISTED pszDpFqdn  : ForestDnsZones.sad.yourcompany.com

In this example, in the output for the zonelist command we can see that reverse lookup zone 0.20.in-addr.arpa is controlled by Simple AD DNS servers.

By default Simple AD is configured to forward DNS requests to the IP address of the Amazon-provided DNS servers for your VPC. That is, unless it can find an answer to a request in the zones that it controls.

The Amazon-provided DNS server for your VPC is at IP address plus two of the subnet associated with the VPC. For example, if your subnet is 20.0.0.0/20 the IP address of Amazon-provided DNS server will be 20.0.0.2/32.

Your Simple AD DNS IP address can be found by looking up DHCP Options Set settings for your VPC via AWS Management Console or by running the following command from our control host. This command returns the contents of the sad.yourcompany.com zone.
    
    
    $ samba-tool dns query sad.yourcompany.com sad.yourcompany.com @ ALL
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    Name=, Records=4, Children=0
    SOA: serial=14, refresh=900, retry=600, expire=86400, minttl=3600, ns=aws-d6b6cbbea6.sad.yourcompany.com., email=hostmaster.sad.yourcompany.com. (flags=600000f0, serial=14, ttl=3600)
    NS: aws-d6b6cbbea6.sad.yourcompany.com. (flags=600000f0, serial=110, ttl=900)
    A: 20.0.140.45 (flags=600000f0, serial=110, ttl=900)
    A: 20.0.15.59 (flags=600000f0, serial=14, ttl=900)
    Name=_msdcs, Records=0, Children=0
    Name=_sites, Records=0, Children=1
    Name=_tcp, Records=0, Children=4
    Name=_udp, Records=0, Children=2
    Name=aws-30c24aad3c, Records=1, Children=0
    A: 20.0.15.59 (flags=f0, serial=13, ttl=900)
    Name=aws-d6b6cbbea6, Records=1, Children=0
    A: 20.0.140.45 (flags=f0, serial=7, ttl=900)
    Name=aws-d6b6cbbea6 
    CNF:e3c7611e-509f-4030-8751-ad8567d59928, Records=1, Children=0
    A: 20.0.140.45 (flags=f0, serial=7, ttl=900)
    Name=DomainDnsZones, Records=0, Children=2
    Name=EC2AMAZ-C5RBOM0, Records=1, Children=0
    A: 20.0.7.86 (flags=f0, serial=110, ttl=1200)
    Name=ForestDnsZones, Records=0, Children=2

Here we can see NS and A records for the DNS servers that resolve to 20.0.140.45 and 20.0.15.59.

Now, if we add a PTR record for our Simple AD control host, we will be able to resolve it from any EC2 host in this production VPC. Note the reverse order for specifying an IP address.
    
    
    $ samba-tool dns add sad.yourcompany.com 0.20.in-addr.arpa 117.15 PTR sadch.yourcompany.com

By running the following dig command from any EC2 host that is pointed to Simple AD DNS servers we can confirm that reverse lookups work correctly.
    
    
    $ dig -x 20.0.15.117
    ; <<>> DiG 9.9.5-9+deb8u14-Debian <<>> -x 20.0.15.117
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12449
    ;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;117.15.0.20.in-addr.arpa. IN PTR
    ;; ANSWER SECTION:
    117.15.0.20.in-addr.arpa. 900  IN PTR  sadch.yourcompany.com.
    ;; AUTHORITY SECTION:
    0.20.in-addr.arpa. 3600 IN SOA  aws-d2b1cbbea6.sad.yourcompany.com. hostmaster.sad.yourcompany.com. 109 900 600 86400 3600
    ;; Query time: 1 msec
    ;; SERVER: 20.0.140.45#53(20.0.140.45)
    ;; WHEN: Thu Mar 18 10:20:22 UTC 2021
    ;; MSG SIZE rcvd: 141

However, in this particular setup A record for sadch.yourcompany.com does not exist in any of the zones controlled by the Simple AD DNS. If you make a request to resolve this domain name to an IP address it will be forwarded to AWS Route 53 service and resolved via Amazon-provided DNS and not the DNS service of Simple AD. Even though dig output may lead you to believe otherwise.
    
    
    $ dig sadch.yourcompany.com
    ; <<>> DiG 9.9.5-9+deb8u14-Debian <<>> sadch.yourcompany.com
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16482
    ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ;; QUESTION SECTION:
    ;sadch.yourcompany.com. IN A
    ;; ANSWER SECTION:
    sadch.yourcompany.com.  60 IN A  20.0.15.117
    ;; Query time: 3 msec
    ;; SERVER: 20.0.140.45#53(20.0.140.45)
    ;; WHEN: Thu Mar 18 10:29:24 UTC 2021
    ;; MSG SIZE rcvd: 65

Note "SERVER: 20.0.140.45#53(20.0.140.45)" which tells us that the answer came from one of Simple AD DNS servers. In reality, the answer was provided by Route 53.

This is crucial to understand if you want to use both AWS Route 53 and Simple AD DNS services in your environment. In a way, Route 53 acts as a backup DNS service when Simple AD DNS fails to resolve a domain name or do a reverse IP lookup.

You could exploit this default behavior and configure a reverse lookup zone as a Route 53 hosted zone. If the reverse lookup zone exists only in Route 53, Simple AD DNS will forward your request to Route 53.
    
    
    $ dig @20.0.0.2 -x 20.0.15.117 
    ; <<>> DiG 9.10.3-P4-Debian <<>> @20.0.0.2 -x 20.0.15.117 
    ; (1 server found) 
    ;; global options: +cmd  
    ;; Got answer: 
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14010  
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1  
    ;; OPT PSEUDOSECTION: 
    ; EDNS: version: 0, flags:; udp: 4096 
    ;; QUESTION SECTION: 
    ;117.15.0.20.in-addr.arpa. IN PTR  
    ;; ANSWER SECTION:  
    117.15.0.20.in-addr.arpa. 4  IN PTR  sadch.yourcompany.com.  
    ;; Query time: 0 msec  
    ;; SERVER: 20.0.0.2#53(20.0.0.2) 
    ;; WHEN: Thu Mar 18 01:31:08 EST 2021 
    ;; MSG SIZE rcvd: 87

Note "SERVER: 20.0.0.2#53(20.0.0.2)" which tells us that an Amazon-provided DNS (Route 53) successfully performed a reverse DNS lookup. This doesn't happen automagically. A reverse zone should exist in Route 53 configuration and contain a relevant PTR record.

Now, let's step back for a moment and assume that you would like to configure and manage a reverse lookup zone controlled by a Simple AD DNS service.

We already know how to list and examine zones.

To create a new zone run:
    
    
    $ samba-tool dns zonecreate sad.yourcompany.com 168.172.in-addr.arpa
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    Zone 168.172.in-addr.arpa created successfully

To add a new PTR record to the 0.20.in-addr.arpa reverse lookup zone from earlier examples:
    
    
    $ samba-tool dns add sad.yourcompany.com 0.20.in-addr.arpa 117.15 PTR sadch.yourcompany.com
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    Record added successfully

To examine a single record:
    
    
    $ samba-tool dns query sad.yourcompany.com 0.20.in-addr.arpa 117.15 ALL
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    Name=, Records=1, Children=0
    PTR: sadch.yourcompany.com (flags=f0, serial=110, ttl=900)

To show all records in a reverse lookup zone:
    
    
    $ samba-tool dns query sad.yourcompany.com 0.20.in-addr.arpa @ ALL
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    Name=, Records=2, Children=0
    SOA: serial=110, refresh=900, retry=600, expire=86400, minttl=3600, ns=aws-d6b6cbbea6.sad.yourcompany.com., email=hostmaster.sad.yourcompany.com. (flags=600000f0, serial=110, ttl=3600)
    NS: aws-d6b6cbbea6.sad.yourcompany.com. (flags=600000f0, serial=1, ttl=3600)
    Name=0, Records=0, Children=34
    Name=112, Records=0, Children=1
    Name=128, Records=0, Children=22
    Name=140, Records=0, Children=1
    Name=15, Records=0, Children=2
    Name=176, Records=0, Children=3
    Name=48, Records=0, Children=4
    Name=64, Records=0, Children=24

To show a subset of records:
    
    
    $ samba-tool dns query sad.yourcompany.com 0.20.in-addr.arpa 15 ALL
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    Name=, Records=0, Children=0
    Name=117, Records=1, Children=0
    PTR: sadch.yourcompany.com (flags=f0, serial=110, ttl=900)
    Name=59, Records=1, Children=0
    PTR: AWS-30C24AAD3C.SAD.YOURCOMPANY.COM (flags=f0, serial=9, ttl=900)

To delete a record:
    
    
    $ samba-tool dns delete sad.yourcompany.com 0.20.in-addr.arpa 117.15 PTR sadch.yourcompany.com
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    Record deleted successfully

  
To learn more about your Simple AD server run:
    
    
    $ samba-tool dns serverinfo sad.yourcompany.com
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    dwVersion  : 0xece0205
    fBootMethod  : DNS_BOOT_METHOD_DIRECTORY
    fAdminConfigured : FALSE
    fAllowUpdate : TRUE
    fDsAvailable : TRUE
    pszServerName  : AWS-30C24AAD3C.sad.yourcompany.com
    pszDsContainer : CN=MicrosoftDNS,DC=DomainDnsZones,DC=sad,DC=yourcompany,DC=com
    aipServerAddrs : ['127.0.0.1', '20.0.15.59']
    aipListenAddrs : ['127.0.0.1', '20.0.15.59']
    aipForwarders  : []
    dwLogLevel : 0
    dwDebugLevel : 0
    dwForwardTimeout : 3
    dwRpcPrototol  : 0x5
    dwNameCheckFlag  : DNS_ALLOW_MULTIBYTE_NAMES
    cAddressAnswerLimit  : 0
    dwRecursionRetry : 3
    dwRecursionTimeout : 8
    dwMaxCacheTtl  : 86400
    dwDsPollingInterval  : 180
    dwScavengingInterval : 0
    dwDefaultRefreshInterval : 168
    dwDefaultNoRefreshInterval : 168
    fAutoReverseZones  : FALSE
    fAutoCacheUpdate : FALSE
    fRecurseAfterForwarding  : FALSE
    fForwardDelegations  : TRUE
    fNoRecursion : FALSE
    fSecureResponses : FALSE
    fRoundRobin  : TRUE
    fLocalNetPriority  : FALSE
    fBindSecondaries : FALSE
    fWriteAuthorityNs  : FALSE
    fStrictFileParsing : FALSE
    fLooseWildcarding  : FALSE
    fDefaultAgingState : FALSE
    dwRpcStructureVersion  : 0x2
    aipLogFilter : []
    pwszLogFilePath  : None
    pszDomainName  : sad.yourcompany.com
    pszForestName  : sad.yourcompany.com
    pszDomainDirectoryPartition : DC=DomainDnsZones,DC=sad,DC=yourcompany,DC=com
    pszForestDirectoryPartition : DC=ForestDnsZones,DC=sad,DC=yourcompany,DC=com
    dwLocalNetPriorityNetMask  : 0xff
    dwLastScavengeTime : 0
    dwEventLogLevel  : 4
    dwLogFileMaxSize : 0
    dwDsForestVersion  : 4
    dwDsDomainVersion  : 4
    dwDsDsaVersion : 4
    fReadOnlyDC  : FALSE

To see more information about a zone run:
    
    
    $ samba-tool dns zoneinfo sad.yourcompany.com 0.20.in-addr.arpa
    Password for [Administrator@SAD.YOURCOMPANY.COM]:
    pszZoneName  : 0.20.in-addr.arpa
    dwZoneType : DNS_ZONE_TYPE_PRIMARY
    fReverse : TRUE
    fAllowUpdate : DNS_ZONE_UPDATE_SECURE
    fPaused  : FALSE
    fShutdown  : FALSE
    fAutoCreated : FALSE
    fUseDatabase : TRUE
    pszDataFile  : None
    aipMasters : []
    fSecureSecondaries : DNS_ZONE_SECSECURE_NO_XFER
    fNotifyLevel : DNS_ZONE_NOTIFY_LIST_ONLY
    aipSecondaries : []
    aipNotify  : []
    fUseWins : FALSE
    fUseNbstat : FALSE
    fAging : FALSE
    dwNoRefreshInterval  : 168
    dwRefreshInterval  : 168
    dwAvailForScavengeTime : 0
    aipScavengeServers : []
    dwRpcStructureVersion  : 0x2
    dwForwarderTimeout : 0
    fForwarderSlave  : 0
    aipLocalMasters  : []
    dwDpFlags  : DNS_DP_AUTOCREATED DNS_DP_DOMAIN_DEFAULT DNS_DP_ENLISTED 
    pszDpFqdn  : DomainDnsZones.sad.yourcompany.com
    pwszZoneDn : DC=0.20.in-addr.arpa,CN=MicrosoftDNS,DC=DomainDnsZones,DC=sad,DC=yourcompany,DC=com
    dwLastSuccessfulSoaCheck : 0
    dwLastSuccessfulXfr  : 0
    fQueuedForBackgroundLoad : FALSE
    fBackgroundLoadInProgress  : FALSE
    fReadOnlyZone  : FALSE
    dwLastXfrAttempt : 0
    dwLastXfrResult  : 0

This should help you hit the ground running.

Whether you prefer to create your reverse lookup zones as Route 53 hosted zones or Simple AD DNS zones, or maintain zones in both DNS services the technical ability is there.

Normally, you probably wouldn't want to set up your DNS this way but understanding how Simple AD and Route 53 work when both are deployed alongside each other is crucial and can help you save a lot of time when you venture to build a more complex DNS system in your cloud.

At Command Prompt, Inc. we champion Linux and Open Source solutions but if these tools don't float your boat, know that you could set up a Windows-based Simple AD control host and do the same from the comfort of a graphical user interface.

If you have any questions don't hesitate to contact us.

We'll be thrilled to help!

---
[View this page online](https://www.commandprompt.com/blog/reverse-dns-zones-with-aws-simple-ad/)

---

# Keys to Moving Forward In Your Life and Career - How Self Awareness Affects Your Life Pt. II

> Finding the right path when moving forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when you are r…

_Finding the right path when moving forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when you are ready to move up into a new role, to refining the skill set you have; there are many steps that have to be put in place in order to further your career. In this article series I’ll provide tips as a COO for what I look for in a highly performant team members, and what has been expected of me over the years. The goal being to help you reach your professional and personal goals._

\---

In part one of this article we went over how self awareness affects your confidence, contentment, happiness, and love. In part two we will focus on inspiration, forgiveness, gratitude/appreciation, and work ethic.

####  **Inspiration**

Realizing that you aren’t exactly who you want to be and putting into words who you are can reshape your existence. Finding inspiration to be better tomorrow and setting goals are the ways people living with a self aware soul keep going. Humans need purpose, and inspiration is often the healthiest way to find it. The moment you start acting on what you want to do in order to become who you want to be, you begin to cultivate inspiration within yourself. That alone is an amazing thing.

When you acknowledge the inspiration within yourself, others will notice and often become inspired themselves. The straightforward way to start doing this is to say you’re going to do and ignore the excuses. Our excuses, AKA the lazy bitches in our brain, run our lives and are the main reason for our lack of happiness and fulfillment. Get them in check and you will become an inspiration.

####  **Forgiveness**

Happiness and success are built on a foundation of forgiveness. It’s essential, plain and simple. It’s also something everyone has the ability to bestow. Everyone has someone they are trying to forgive, be it themselves or someone else. It’s in our nature to forgive because that’s how we resolve conflict, how we make progress, and how we find happiness. Hate, anger, and resentment take up space in our hearts where love could be. Why do we give space to things that are so detrimental to our mental health? Forgiveness is as much for us as it is for the other person. No matter what the other person deserves, your life is the one you have power over. Are you willing to give that power to something that happened in the past?

 _Food for Thought: What are some tools or tactics you use to let go?_

####  **Gratitude and Appreciation**

With everything going on in the world and our personal lives, it is far too easy to forget gratitude. _“Sure, but how is that impacted by self awareness?”_

Those who practice self awareness have an often holistic perspective. Reducing blockers can open our eyes to everything we _do_ have in the midst of chaos. Studies have shown that people with a mindset focused on gratitude have less negative stress and depression. Being able to take a step back from being driven by negative emotion is key to finding some semblance of peace in your life. In addition, gratitude can help you be a resource for those around you who need to be reminded that they will get through whatever life is throwing at them.

####  **Work Ethic**

While some people have an ingrained work ethic, others must strive to identify motivation to do more than “the bare minimum.” Self awareness can help identify what motivates you and what you need in order to develop a work ethic that drives you to achieve. Do you work best alone or in a group? Do you want more or less support from management? Does working from home add or distract? There is an important difference between getting the job done and being pleased with the final product. The sweet spot is found by being clear with your employers/colleagues about your needs and motivations. Sometimes your needs are not always heard, and that’s where you need to be self aware enough to take the initiative and have a conversation about what you need to optimize your performance.

####  **Closing**

I challenge you to take a moment and reflect on what you want out of life. Self awareness will without a doubt help you achieve your goals and will help you become the optimal version of yourself.

For further reading:

[ _7 Habits of Highly Effective_](<https://smile.amazon.com/Habits-Highly-Effective-People-Anniversary/dp/1642503177/ref=sr_1_1_sspa?crid=1PCP6CGQUX13O&dchild=1&keywords=7+habits+of+highly+effective+people&qid=1617638826&sprefix=7+habits+of+highly+eff%2Caps%2C167&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExTDFBQVRVMTZTWEY0JmVuY3J5cHRlZElkPUEwNDg3NDM1UE9DTkxINFlOTjFWJmVuY3J5cHRlZEFkSWQ9QTA0NjA0NDMxMDNGSkQ1Ukg3VFRHJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==>), People, by Stephen Covey

[ _The Four Agreements_](<https://smile.amazon.com/Four-Agreements-Practical-Personal-Freedom/dp/1878424319/ref=sr_1_3?crid=9C8QP3SJNCCR&dchild=1&keywords=the+four+agreements+by+don+miguel+ruiz&qid=1617638870&sprefix=The+Four+Agreements+%2Caps%2C203&sr=8-3>), by Don Miguel Ruiz

[ _You are a Badass_](<https://smile.amazon.com/You-Are-Badass%C2%AE-Doubting-Greatness-ebook/dp/B00B3M3VWS/ref=sr_1_1?crid=2OKCCP1Z5YQZ&dchild=1&keywords=you+are+a+badass+book+by+jen+sincero&qid=1617638915&sprefix=You+are+a+Badass+%2Caps%2C185&sr=8-1>), by Jen Sincero

---
[View this page online](https://www.commandprompt.com/blog/how_self_awareness_affects_your_life_round_two/)

---

# Keys to Moving Forward In Your Life and Career - How Self Awareness Affects Your Life

> Finding the right path when moving forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when you are r…

_Finding the right path when moving forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when you are ready to move up into a new role, to refining the skill set you have; there are many steps that have to be put in place in order to further your career. In this series, I’ll provide tips as a COO for what I look for in highly performant team members and what has been expected of me over the years. The goal being to help you reach your professional and personal goals._

\---

When I started this blog series it was a different time: We had never heard of _COVID19_. From losing loved ones and learning to work from completely different environments, to being quarantined, 2020 was a year of self evaluation.

Arguably, self evaluation and self awareness should be the first in this blog series, but in my experience it’s easier to swallow and take action when there’s a goal you’re trying to achieve. My first two blogs: [Getting Out of Your Own Way](<https://www.commandprompt.com/blog/keys_to_moving_forward_get_out_of_your_own_way/>) and [Making the Leap to Uncomfortable](<https://www.commandprompt.com/blog/making-the-leap-to-uncomfortable/>) are important pieces to the puzzle, and will get you ready for success. Refining your self awareness is how you evaluate where you want to go and will help you plan how to get there.

While there are many articles and books about how to achieve this conscious knowledge, I haven’t found many elaborating on why it’s worth achieving and how it will affect your day-to-day. In light of that, I have put together two articles where I expound on some important areas we don’t always associate with self awareness in an effort to broaden the understanding of why it is critical that we take advantage of the opportunities it brings forth.

####  **Confidence**

Self awareness opens your truth to who you are, who you were, and are headed toward being: It can make you feel vulnerable, but it will also enable personal and professional growth. I’ve been in many conversations where people genuinely do not understand others who lack confidence. _“They’re great! They’ve got all kinds of things going for them. Why aren’t they comfortable in their own skin?”_ I’ve also never met an unconfident person who enjoys feeling that way. Typically it comes from a combination of a fear of being judged, genuinely having no faith in themselves, playing it as a victim card, or a mixture thereof. A self awareness check will let you know where you fall within your journey. Increasing (and creating) confidence is all about increasing your self awareness, embracing vulnerability and being willing to accept change. However, embracing who you are _now_ , facing what you’ve been through, and knowing where you want to go is the first step to being confident in who you are. That’s the problem.

####  **Contentment**

Knowing and embracing your flaws, habits, coping mechanisms, and areas of temptation is actually a good thing. There are few who don’t have some kind of vice. Example of vice beyond the ordinary and obvious: shaming ourselves with guilt for not making a daily practice around a hobby.

The moment you recognize the things that hold power over you is the moment you will be content with who you are. It’s like finally putting into perspective all of the things that nag at you during the day. You may want to make changes, but it’s not something that you want bad enough for the weight of the effort...so you’ll accept the consequences later. Whether you change or not is up to you. The power is in accepting that right _now_ , this is where you are, and that’s fine. (If it’s not fine, make a change). Once you’ve accepted it you will have the ability to be truly content, and happy.

 _Food for Thought: What were you doing the last time you were fully content, and what is it about that moment that made you feel complete?_

####  **Happiness**

We get so wrapped up in surface level materialism and instant gratification that we’ve forgotten how to find lasting happiness. Studies and psychologists everywhere will tell you that the more time a person spends on social media, the higher the risk of depression. I believe it’s because we’re focused on our image and that we’ve forgotten to experience what’s happening in the real world. We no longer take time to smell the flowers; instead we take pictures of the flowers to post on some platform in order to hopefully receive affirmation from people we don’t even know. We are impatient and compare our day-to-day lives to the “highlights” in our friends’ lives, exacerbating our feeling of insecurity and un-fulfillment. How do you find happiness within that kind of mindset? The only answer I’ve found is to develop self awareness, and to fine tune the skill continuously.

Self awareness will make many people uncomfortable in this arena as it reveals that happiness isn’t found in a new phone, a pool, the vacations, or even the money. True happiness comes from doing right by oneself. Often it involves working hard to earn a good, worthy reward, or having a mutually satisfying relationship. In a lot of ways it’s choosing to do the right thing even if there are unpleasant consequences. That’s hard when instant gratification doesn’t require much effort. The question you need to ask yourself is how you want to truly experience happiness, and if so, are you willing to put the effort in? That is, after all, what we all want in life, right?

####  **Love**

Self aware people have it better than most in relationships because they have the ability to take stock of the situation with a realistic perspective. It can be extremely difficult when one or both parties don’t understand where the other is coming from, or the origins of your feelings. When you lash out because someone didn't do something they said they would, you are creating distance between you and your partner. Distance in relationships is infectious, like a deadly disease. To you, to friends, to family. It breeds discontentment and un-confidence. And hurt.

 _Food for Thought: We’ve got enough hurt people. Let’s make self aware warriors again._

There’s something to be said about being aware enough to choose love over everything else. It’s easy to blame circumstances, the other person, etc. It’s not as easy to choose love and self-improvement, especially when you’re going through a hard time. They say, “If it’s broke don’t fit it.” What if it is broken? An attitude of blame will cause more distance and increase the dysfunction. A self aware perspective allows you to step back and see the situation as it is - a broken one that needs both parties’ involvement to fix. Talk to any couple that has been in a relationship for a long time and they will tell you that you have to choose love over everything else.

####  **Closing**

As you can see, self awareness goes far deeper than surface level. Self awareness goes hand in hand with a wide array of important components to life, including contentment, happiness, love, and finding success. Truly successful people are incredibly self aware, know when to say no (and yes), and take the time it needs to improve themselves in areas that align with their values. That isn’t to say they don’t struggle, because we all do, it’s that they struggle with proactively _acting_ instead of reacting. Can you imagine a world where more people didn’t simply react and instead responded with positivity?

For further reading:

[ _7 Habits of Highly Effective People_](<https://smile.amazon.com/Habits-Highly-Effective-People-Anniversary/dp/1642503177/ref=sr_1_1_sspa?crid=1PCP6CGQUX13O&dchild=1&keywords=7+habits+of+highly+effective+people&qid=1617638826&sprefix=7+habits+of+highly+eff%2Caps%2C167&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExTDFBQVRVMTZTWEY0JmVuY3J5cHRlZElkPUEwNDg3NDM1UE9DTkxINFlOTjFWJmVuY3J5cHRlZEFkSWQ9QTA0NjA0NDMxMDNGSkQ1Ukg3VFRHJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==>), by Stephen Covey

[ _The Four Agreements_](<https://smile.amazon.com/Four-Agreements-Practical-Personal-Freedom/dp/1878424319/ref=sr_1_3?crid=9C8QP3SJNCCR&dchild=1&keywords=the+four+agreements+by+don+miguel+ruiz&qid=1617638870&sprefix=The+Four+Agreements+%2Caps%2C203&sr=8-3>), by Don Miguel Ruiz

[ _You Are a Badass_](<https://smile.amazon.com/You-Are-Badass%C2%AE-Doubting-Greatness-ebook/dp/B00B3M3VWS/ref=sr_1_1?crid=2OKCCP1Z5YQZ&dchild=1&keywords=you+are+a+badass+book+by+jen+sincero&qid=1617638915&sprefix=You+are+a+Badass+%2Caps%2C185&sr=8-1>), by Jen Sincero

---
[View this page online](https://www.commandprompt.com/blog/how_self_awareness_affects_your_life/)

---

# Meet Tiffany Gustanski: Our Well-Rounded Project Manager

> Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we speak with Tiffany Gustanski, Assistan…

Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we speak with Tiffany Gustanski, Assistant Project Manager at Command Prompt.

 **How long have you been with Command Prompt?**

I’ve been with Command Prompt since August 2020.

 **What’s your background and expertise?**

Before Command Prompt, I was a project manager for a cloud SAAS company, implementing their accounting solution.. Prior to that, I had recently graduated from an MBA program at California State University Northridge (CSUN), so I’m still getting my feet wet in project management.

I worked between getting my undergrad and getting my MBA, most notably for Bank of America, through a contractor. I wanted to pursue my MBA after that job, and while I was getting my MBA, I worked for a management professor who was contracted by the city of Los Angeles, California state government entities, and nonprofits. I did research for him as part of his team and managed some of his major projects.

 **What has working in Open Source / Postgres taught you?**

I didn’t have much experience with Postgres before working with Command Prompt, so I’ve learned that it’s actually ingrained in a lot of other businesses. I’ve been familiar with the concept of Open Source for many years, and have supported it for a long time, so I’m really glad to be working for a company that is actively promoting that philosophy. I think it’s important to not lock knowledge in a box - it should be shared and it should be added to and grown. Anything that promotes that, I’m for.

 **What is it like to be on a team of SysAdmins and DBAs?**

Being on a team with SysAdmins and DBAs is enlightening - it’s a completely different job from what I do and from what my friends and former colleagues do, and I like seeing another perspective to solving problems. My father used to work in databases, and I’m familiar with this work, but he worked in a more entrepreneurial way, so he was promoting himself a lot too. Seeing a team working is a little different than seeing a single person.

The Command Prompt team always has the best intentions, so while it may be tough at times to oversee and balance the team’s tasks and responsibilities, I really enjoy working with this team because their ultimate goal is to be helpful to us and to our partners.

 **What’s your greatest motivator?**

My greatest motivator is knowing that I have helped someone. I like hearing the feedback that something I did was really helpful, so hearing that from our partners and from my teammates is what motivates me. I want to make sure that what I’m doing helps someone else.

 **If you could recommend one learning resource, what would it be?**

A year ago, I built my PC without any previous experience, and the top question I’ve gotten about it was how did I know what to do and what to get. PCPartPicker.com is a great resource if you’re interested in building one yourself. They have curated build guides for different price points and levels, so if you’re unsure of what you want, you know you can’t go wrong with their recommendations. Community members also post their own completed builds that you can draw ideas and inspiration from. PCPartPicker also has price comparison and tracking tools to help if you’re on a budget, and a compatibility checker to make sure parts are meant to work together.

 **What kinds of roles are available for non-technical people in tech?**

Project management is an obvious one because it’s what I do. In previous positions, like when I worked for the Cloud SaaS company, I primarily worked with non-technical people in professional services. Implementing a cloud solution, for example, doesn’t necessarily require technical knowhow. In the company I was previously with, we had been implementing an accounting solution, so a lot of those people were more _accounting people_ and not necessarily technical. If it falls under your wheelhouse, you could certainly be trained to implement services like that within a technical organization.

 _Professional services_ can encompass a wide range of non-technical people. With technical companies, they all need support and usually more than they think they do. I had wanted to pivot to tech, so project management was a way that I thought that my skills could make me useful.

I knew I wanted to go into the tech because there’s a lot of growth in the industry, and I wanted future job security. I decided to go about it by furthering my education by getting my MBA. Doing my MBA also had me researching companies regularly, so being able to do your homework was another skill that I was able to acquire. When you’re going about finding jobs, it’s important to explain how your skills apply to that job and make sure that that kind of parity is obvious to your potential employer.

 **What should a non-technical person look for in a tech-based organization?**

Knowing what kind of area that you want to be in is important, but also being able to do your research when it comes to applying. For example, if you know what company you’re applying to, I’m sure they have a website and you can see their products or services, then you can do your research so that you can be well prepared.

 **What tips do you have for those now working from home for the first time?**

I’ve been working from home since March due to the COVID-19 lockdown, and before that I’d been working from home on and off because my previous company was flexible about going into the office. I still feel a little new to it, but it hasn’t been a huge change for me. I’m also a freelance writer for a site that does entertainment news, so I’ve been working remotely doing that for a few years.

Having a dedicated work space is really important for working from home, even if it’s in your bedroom - it just shouldn’t be near your bed. I have a dedicated workspace within my bedroom with a desk and a PC that I built for gaming, but that I also use for work. Since I also have a laptop, I have a stand so that it’s more comfortable to use at my desk. Having that space is really important so that you know when you’re in work mode and when you’re in home mode.

Sticking to routine schedules is also really important as well. I have a roommate who’s currently working from home due to COVID, and her work space is similar to mine insofar as she’s in her bedroom with a desk. We joke that we’re coworkers even though we don’t technically work together.

 **Where can we find you on a Saturday afternoon?**

These days, you can probably find me on the couch playing video games - Right now I’m playing _Assassins Creed Valhalla_ , so I get to be a viking.

I would be going to baseball games if it were allowed. I had planned to go three times last year but was only able to go once due to COVID-19. The only way to go to a game was to go in Texas during the playoffs, and I happen to live in Texas. I also happen to be a fan of one of the teams that played, so I was really excited that I was actually able to go.

 **Would you rather battle one horse-sized duck or 100 duck-sized horses?**

I knew you were going to ask this question so I’ve been trying to think of an answer ahead of time - I’ve been going back and forth on it. 100 duck-sized horses is a lot to manage. I think I’d take the horse-sized duck, but I don’t have a plan. One horse-sized duck is only one thing to keep an eye on, though. Also mini horses are adorable, and I don’t want to fight them.

 **Desert island food?**

Pizza was my initial thought so I’m going to go with that. Probably a supreme pizza so that I get some vegetables but also some protein as well.

 **What book should everyone read?**

Unfortunately, most of my books are in LA, but one of my favorite books that’s interesting to me very specifically, is called [_Washington’s Spies_](<https://www.goodreads.com/book/show/19503231-washington-s-spies?from_search=true&from_srp=true&qid=f16MfjUn0g&rank=1>), by Alexander Rose. I’m a big US history fan, and I like learning about the American Revolution. The TV show _Turn: Washington’s Spies_ , on AMC is based on this book about the Culper ring.

If you’re interested in the American Revolution in any way, then this is a really good read and it’s not as long as the Alexander Hamilton book that _Hamilton_ was based on.

 **Other than project management, what topic are you an expert on?**

I am pretty good about knitting. I have surpassed the person who taught me how to knit - it was actually my roommate who taught me when we were in high school, and I’ve kind of gone further and have been able to do more complicated things since then. She didn’t know how to do cabling, but she asked me to make a cable knit scarf for her, so I learned how to do that on my own. That scarf is probably one of my favorite things that I’ve made because it ended up looking really nice - it has two cabled braids running along both sides.

 **Early bird or night owl?**

I’m a night owl - I don’t function in the mornings as well as I would like to, and I’m way too productive at night. I should be going to sleep, but instead I’ll be trying to do stuff - lots of late night cleaning.

 **What subject should be taught in schools but isn’t?**

I think people need to be more prepared for the umbrella of _adulting_ , so how to do your taxes, how to invest - even just minor investments. These aren’t things that people get taught unless they really look for it, and these aren’t things that should have a barrier to entry. This is something that should be started early, but by the time that someone who hasn’t been exposed to investing realizes that it’s something that they need to work on, they miss out on the benefits of starting early.

 **When you were a child, what did you want to be when you grew up?**

When I was a child, I wanted to make cartoons - I wanted to be an animator. However, I wasn’t very talented as far as drawing goes and I didn’t enjoy bettering myself at drawing, so it’s not something that I pursued. That being said, it is something that my best friend is pursuing, so I get to live vicariously through her.

---
[View this page online](https://www.commandprompt.com/blog/meet-tiffany-gustanski-our-well-rounded-project-manager/)

---

# Keeping the Fire Alive: Maintaining Client Relationships From a DBA Perspective

> In my seven years at Command Prompt I&#x27;ve helped many clients, often several of them at the same time. After a project is completed, I know that it was a job we…

In my seven years at Command Prompt I've helped many clients, often several of them at the same time. After a project is completed, I know that it was a job well done when that client calls on Command Prompt months and maybe years later for additional help. Often, they call for me by name, creating long lasting and mutually beneficial relationships, which are key to Command Prompt's success. How do I help keep the fire alive?

I work directly with clients, with my hands inside their database systems. Though the work is technical, I find that it's also personal: I need their trust. After the first client project or emergency is resolved and we say our good-byes, it's the foundation of trust that survives over the following months when the client needs us again.

## The First 60 Seconds

Building trust starts immediately on first contact. It's a fact of human nature that people establish persistent judgements of each other [within seconds of first meeting](<https://www.psychologicalscience.org/observer/how-many-seconds-to-a-first-impression>). Therefore, before that first meeting, _be_ trustworthy and get yourself in a proper state of mind: the next year could depend on it.

As a DBA, I always meet clients after my business development team has already initiated a relationship, and my first meetings nominally focus on technical content. In reality, I usually feel that little technical information is conveyed in that first meeting, and that the core of the meeting is about sizing each other up.

When a client is new they may be tentative about letting me into a very delicate and important part of their system. It's like someone handing me their infant: I try to show steady confidence and deep caring, as well as competence. It helps to start with small, clearly defined goals that I know that I can achieve, and then build up to bigger ones. I listen to the client and let their feelings - usually anxiety about certain problems - guide me. Trust builds when the client feels that I understand and am addressing their needs and their urgency. When I sense that the client feels relaxed at the end of the meeting, I know that I've done my job and that the client will allow technical work to begin in earnest.

## Make it Personal

Did you ever notice when someone asked for a meeting with you even when there was little business to discuss? Or did you ever notice on a video call how happy the other person looked after you enabled your camera for the first time?

Even in professional and technical contexts, everyone wants to connect personally to some degree. Even though I provide remote technical service and I never see many of my clients' faces, I enjoy fostering a friendly feeling with clients and I think most of them enjoy it as well. When I listen to a client share their weekend fishing story, or I joke about my inlaws, it adds energy and a new bond to the business relationship. If you rely solely on email to communicate, a relationship will tend to fade. Instead, I try to make it personal, and as a result clients continue to reach out to me.

## Managers and Gatekeepers: Different Allies

A long-term business relationship with another company partly depends on keeping the right relationship with the right people at that company. It only works when both parties have a long term stake in success; on the client side, managers have such a stake. The manager/director/CTO - more than a developer, for example - is likely to _need_ my alliance for their own success and survival at the company. As the saying goes, "It's lonely at the top" and managers often look to me as a peer and confidant. I try to foster that feeling.

On the other hand, developers, sysadmins, and devops staff have their own immediate concerns that often don't overlap greatly with mine or even with their own departmental concerns. Sometimes they initially see me as a competitive threat to their position of technical authority. Yet these are the people that I work with directly, and they have ways to block or facilitate my access to their systems, and even to their superiors. And they may remain employed in their position longer than their superiors! Alliance with these gatekeepers is one key to the long-term client relationship. I try to tread lightly on their turf and take any opportunity to be helpful; this often takes the form of openly recognizing their valuable contributions to the project. In short, I try to keep the "gate" open to their superiors.

## In the Desert

Like green grass in the desert, client work can be fleeting, often simply because projects are completed. When I've done my job well, the client relationship continues. My project manager, Amanda Nystrom, will call on them occasionally. Rather than attempting to drum up new business, we try to leave the client with the sense of checking on their welfare. We remind them that we’re still available for them and we remind them of how we can help them again. I show empathy for whatever is keeping them away. Clients are often very busy, and they can easily forget us simply because they are overwhelmed. I try to be a light in the darkness for them, or an ally to reach out to, and time has shown that well-established relationships bring them back.

---
[View this page online](https://www.commandprompt.com/blog/keeping-the-fire-alive-maintaining-client-relationships-from-a-dba-perspective/)

---

# Building Community in the Age of Remote… Everything

> Here we are in the beginning of 2021, and it’s been almost a year since we’ve been able to gather safely. While there are a handful of core value propositions …

Here we are in the beginning of 2021, and it’s been almost a year since we’ve been able to gather safely. While there are a handful of core value propositions to events - namely, increased brand awareness and increased market share - I would argue that one of those most often overlooked is community building. When a common interest brings people to a singular space, community is bound to build, and from that, anything is possible.

So how should we go about building a community these days? While there’s hope that we may be able to gather in person in the next year, it’s important that we lay the groundwork today. Read on for some core tenants of building a community in an age of remote...everything:

 **Build a community around a common interest**

There are two options for how a community will form: Either an existing group of people with a shared interest will band together and invite others, or one person will tap into an existing gap that people flock to. Neither option is right nor wrong. In fact, their core is the same: folks with a common interest have a need to find others who share in the same. Which option feels the most organic to you? Which option will help you achieve the community you are after? Either way, it’s time to start seeking out others with shared passions.

 **Create legitimacy in content and activities**

Once you have a group, content becomes king. Creating moments for engagement - be it with an idea, a shared project, or a webinar - is vital because it gives group members a jumping off point to connect with each other. Prior to 2020, this may have looked like a presentation followed by a happy hour. But, in a time when in-person events aren’t feasible, it’s the organizer’s responsibility to create a spark and then a space for conversation to flow. This will look different for every community, so consider how best for your group to “gather.”

 **Market and promote your community**

Your community is great, right? Time to shout it from the rooftops. Try posting your online events or engagements to event boards, and always be on the lookout for potential new members. Want to take it a step further? Craft a short _elevator pitch_ that will act as a catalyst for conversations about your community.

 **Be deliberate in the community culture**

Have you ever noticed that offices are full of suits when the boss wears them, or that organizations tend to be more casual when management is also casual? Because organizational leadership sets the tone, you need to determine the defining attributes of your group and then walk the walk. Aim to create an inclusive space where all feel welcome and where culture is a topic of conversation. Transparency is your best friend here, so set culture guidelines and goals early.

 **Emphasize your members’ needs**

Every community is different, and what may work brilliantly for one organization may bomb in another. The easiest way to know what your community craves is to ask them, and then make their feedback actionable. If there’s group buy-in, your members will be invested in both maintaining engagement and creating a value proposition to entice future members.

 **Empower members to grow the group organically**

A solid community frequently takes on a life of its own. It grows and evolves with changing markets, perspectives, and technologies. When folks enjoy and benefit from being part of a group, they are driven to bring in their network.

Given the key learnings of the last 12 months, 2021 is ripe with opportunity to create new and unique groups. It’s time to foster and expand existing communities, so now is the time to ask yourself: How will you build community in a remote age?

---
[View this page online](https://www.commandprompt.com/blog/building-community-in-the-age-of-remote-everything/)

---

# Thoughts on Forks and Open Source Licenses

> I had the opportunity to speak with Karthik Ranganathan of YugabyteDB a couple of weeks ago; he was the inaugural guest for our new podcast, “More than a Refre…

I had the opportunity to speak with Karthik Ranganathan of YugabyteDB a couple of weeks ago; he was the inaugural guest for our new podcast, “[More than a Refresh: A podcast about data and people who wrangle it](<https://www.commandprompt.com/about/more-than-a-refresh/>).” Karthik is the CTO and one of the Founders of YugabyteDB. He provided an interesting perspective on Open Source and the license changes of other database companies. YugabyteDB is a compelling product for the following reasons:

  1. It is Open Source (not marketing wishful thinking such as the SSPL).
  2. It is Postgres and Cassandra Compatible. This is not just wire protocol compatibility: It is Postgres and Cassandra feature compatible. It is a fork of PostgreSQL and Cassandra.
  3. It is globally distributed and supports Multi-Master.



Technical applications aside, it is the first number that we should consider here. There are people (rightfully) taking PostgreSQL code and forking it for their purposes. Each of the big three cloud providers have done so, as have other Fortune 500 companies such as VMWare. That is the foremost benefit of Open Source: the ability to take the code and make it work for you.

One of the recent trends in the market is to create something Open Source and market it as Open Source. The software may then begin to gain traction and other companies or people will fork it. These companies often get upset at people doing exactly what Open Source is designed for. A feeling of theft or betrayal is often expressed. Companies forget that Open Source is not a business model: it is a value add and the Open Source design is to share.

Likewise, it is not appropriate for Open Source advocates to become agitated when a company takes the code the company owns and re-licenses it. In today’s market a license such as the SSPL or Timescale License may allow the companies to remain competitive.

I agree that it is better for humanity if code is “Free” (as in Liberty not beer). Freedom, AKA Liberty, means that one has the ability and the right to consider a different path than one we may like. As an Open Source advocate, it is vital to publicize the benefits of Open Source over other models. We don’t need to attack those models, we just need to have objective discourse as to their failings and positive discourse toward Open Source solutions.

---
[View this page online](https://www.commandprompt.com/blog/thoughts-on-forks-and-open-source-licenses/)

---

# Meet Amanda Nystrom: Command Prompt's Compassionate Commander in Chief

> Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Amanda Nystrom, Owner…

Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Amanda Nystrom, Owner & Senior Project and Operations Manager.

 **How long have you been with Command Prompt?**

Six and a half years. I originally joined the team as a consultant in 2009 for about a year, and when the stars aligned I ended up back here in 2014.

 **What’s your background and expertise?**

My background is in communications, business, and psychology. I’ve spent a lot of time refining company processes and policy in order to achieve a balance of efficiency and quality for our partners.

 **What has working in Open Source / Postgres taught you?**

In the simplest terms, I’ve learned that there’s always another way of doing things beyond the status quo. I had no knowledge of open source when growing up; the only option I knew of was out-of-the-box Microsoft. When I discovered open source, I was blown away. The discovery that we have the freedom to create and design on our own terms was crucial to who I am today.

The fact that we have a complete database solution (and even more than that) that is community created, maintained, and free to the public is an amazing thing. It’s not just about making money; it’s about providing a stable, secure environment for everyone who doesn’t want to be limited by restrictions in order to do what YOU want. That’s what freedom is all about.

 **What is it like to manage a team of systems and database admins.?**

It’s a lot of fun and has been a good challenge. There are moments of frustration but overall it’s a great experience. Earning each other’s respect while working toward a mutually beneficial goal was top priority when I started, and it was something that I had to build with each member of the team. This is part of what makes Command Prompt different: we don't just send out paychecks, we invest in people and get to know our team on a much deeper level. We aren’t perfect by any means, but we’re honest and open about it, and we try to improve. Because of that, we are able to count on our team and they are able to count on us.

 **What kinds of roles are available for non-technical people in tech? What should a non-technical person look for in a tech-based organization?**

If you are adaptable and willing to learn, there are countless opportunities for someone who isn’t technical. From office management to marketing to business development to project management, every organization has needs across the board, whether it’s a tech-based company or not.

I love project management because it’s a great life skill and every business needs one to be successful. Being able to break down any project into its parts and lead a team to complete each part is infinitely useful in professional and personal life. It’s also a profession where you can grow, and you don’t necessarily have to know the project subject matter intimately in order to succeed.

For non-technical people looking at joining the tech field, do some self reflection and ask yourself what you are truly interested in and how much you are willing to learn. If the company as a whole represents something you believe in, then there’s no reason why you can’t learn the skills needed to join.

 **What’s your greatest motivator?**

My greatest motivator is taking care of people. It was never my intention to become a mother hen, but now I feel like it was inevitable. I love taking care of my family, friends, and colleagues, as well as people I work with at [Postgres Conference](<https://postgresconf.org/>). It’s not just about getting the job done; to me, it’s about investing in the people around me and doing what I can to help their lives be better. Sometimes it can be to my detriment, but honestly I believe that if we were to focus on each other more and ourselves less, we would have less hurt and pain in the world.

 **What tips do you have for those now working from home successfully as someone who has done so for years?**

Set a schedule for yourself and make sure you have a dedicated and comfortable non-interrupted space. Try it for a couple weeks, then reassess. Are there areas where you’re less productive? Are you distracted? Remove any personal items from your workstation (relocate to a folder) that remind you of things you’d rather be doing. Ignore your phone. Ignore the news. Stay off of social media. Take meaningful breaks every hour or so to walk around and stretch. Most importantly, take a break at least once during the day to kiss and hug your partner/kids/fur babies. It is a blessing to work from home and often we need reminders when it’s difficult. Taking two minutes with your family members can be a breath of fresh air that reminds you how blessed you are. (If you don’t have people or animals, get a plant and talk to it. They love it and it’s good for you.)

 **Where can we find you on a Saturday afternoon?**

Depends on the season. In the spring and summer it will often involve sharp tools, swear words, gloves, and blackberry bushes. In the winter, I’m usually with a book or working on any number of home projects. When I’m lucky, I’m traveling somewhere in my short bus.

 **Would you rather battle one horse-sized duck or 100 duck-sized horses?**

100 duck-sized horses. I am a big lover of checking things off a list in order to show progress, which keeps me motivated. With 100 duck-sized horses I could just check them off and know that the end was in sight, as opposed to fighting a boss duck that may or may not show weakness until it’s at the end. Finding what keeps you motivated is really important to achieving your goals, whether you're fighting mythical mega-ducks, or in reality.

 **Desert island food?**

My impractical answer: Any pasta dish from Italy. My practical answer: something like potatoes or beans. Basically anything where you have protein but also all of the nutrients your body needs to survive. Plants on the island may or may not be edible, so you need to make sure whatever your one food is has what you really need.

 **What book should everyone read?**

There are so many fantastic books out there that I’d love to recommend but I think the top three would be [Fahrenheit 451](<https://www.amazon.com/Fahrenheit-451-Ray-Bradbury/dp/1451673310/ref=sr_1_2?crid=1HO1N7ZU4GVU3&dchild=1&keywords=fahrenheit+451&qid=1607978165&sprefix=fahren%2Caps%2C237&sr=8-2>), [Unbroken](<https://www.amazon.com/Unbroken-World-Survival-Resilience-Redemption/dp/1400064163/ref=sr_1_6?dchild=1&keywords=unbroken&qid=1607979235&sr=8-6>), and[ Cowboys, Mountain Men, and Grizzly Bears](<https://www.amazon.com/Cowboys-Mountain-Men-Grizzly-Bears/dp/0762754311/ref=sr_1_1?crid=RBID6M3FVF0I&dchild=1&keywords=cowboys%2C+mountain+men%2C+and+grizzly+bears&qid=1607977972&sprefix=cowboys%2C+mou%2Caps%2C205&sr=8-1>). Really any nonfiction book that sheds light on how far we’ve come, what our ancestors went through to give us our privileged lives now, or what we need to be careful to avoid in the future. Our lives are short, and I believe we should spend that time with an attitude of gratitude and respect.

 **What should everyone see/do before they die?**

Travel, anywhere. Get out of your box and see how other parts of the world do things. Don’t just go to the tourist attractions; try to experience the place as the locals do. When I went to Rome in 2019 we didn’t wait in lines with hundreds of people to see the main attractions. Instead, we walked the back streets for hours experiencing the little shops, restaurants, and parks that most tourists would never see because they spent so much time at the “things you must see.” That said, if you are a “big sight” junkie, that’s great. My main point is just to get out there and experience other places and ways of life.

For those that can, take a road trip to Utah/Wyoming/Montana. It truly is a trip of a lifetime and opens your eyes to a world you never knew existed. From the dramatic landscape changes to the sheer power of Yellowstone to the nature and wild animals that make you appreciate the trek that our ancestors took through the “wild west,” it’s the most amazing area that far too many people aren’t aware of.

 **Other than project management, what topic are you an expert on?**

Wifery. I love being a partner and housewife, as well as a successful professional. Being a successful partner is arguably one of the hardest things we do, as it requires a level of consideration, balance, and cooperation that most other jobs don’t. You have to work on it 24/7 and pray your efforts are good enough to take care of the other person’s heart. You have to learn to grow with them as you both change, and adapt when things get hard. Outside of being a parent, it’s the most important thing we can do.

 **Early bird or night owl?**

I love early mornings...just not enough to experience them very often.

 **What subject should be taught in schools but isn’t?**

Personal finance, and how to be self sufficient. For some reason “you can do whatever you want to in life” has turned into “you can do nothing and still make money” to an unfortunate amount of people. Working hard shouldn’t be something we turn away from; it should add motivation to achieve. Maybe also “How to survive without your cell phone.”

 **When you were a child, what did you want to be when you grew up?**

A writer, a doctor, an architect, a lawyer, a singer, a business owner. Probably a wizard at one point. You know, the basics.

---
[View this page online](https://www.commandprompt.com/blog/meet-amanda-nystrom-command-prompts-compassionate-commander-in-chief/)

---

# Are We Working from Home or Living at Work?

> The general sentiment among my loved ones - those lucky enough to still have jobs - is that working from home has transformed their jobs on even the most basic…

The general sentiment among my loved ones - those lucky enough to still have jobs - is that working from home has transformed their jobs on even the most basic levels. Meetings are on Zoom, group tasks get completed at a different pace, and communication styles have rapidly evolved to account for the lack of face-to-face interaction (how many “virtual happy hours” have you been on since March?).

For the past year I have been working as a remote consultant, and even when it was safe to work in an office, I spent most days working either from my living room or from the coffee shop. The move into a consultant role gave me freedom that I didn’t know was possible, but the “work from home” part of it used to be completely voluntary.

My work, my flow, my day-to-day, and my projects have all undergone radical shifts as a result of everyone working from home. My work week feels different than it did a year ago because the lines between “home” and “work” have also shifted. In light of the last ten months, I can’t help but wonder: _Are we working from home, or are we actually living at work? Is a life balance even possible?_

The question felt silly at first, but its implications are very real. The concept of the American work/life balance was tenuous to begin with. I’ve worked for organizations that touted their positive work/life balance only to be disappointed. Worse, I’ve worked for companies that claimed, “There is no work/life balance. There’s only life, and work is part of that life.” Unlike at holistic companies, those experiences were only work and no balance.

Consider that there are 168 hours in a week. Subtract the 40-hour work week, and then subtract another 8 hours per night for sleep, and you’re left with less than half of your week to yourself. This doesn’t factor in the amorphous hours spent commuting, taking time for lunch, and checking email from your phone while you do other activities like leisurely reading, catching up on TV, and completing projects around the house. While this is not inherently negative, conflating work time and personal time in the same space may fan the flames of imbalance.

As of May 2019, [burnout](<https://www.who.int/mental_health/evidence/burn-out/en/>) is officially recognized by the World Health Organization as an “occupational phenomenon.” It’s listed in the International Classification of Diseases. And the research that went into this classification happened prior to shifting to near-mandated work from home. A common theme among those experiencing burnout is a diminishing boundary between work life and personal life. If so many workers were experiencing burnout at the start of the pandemic when working from an office, how many more experience it today from their living rooms?

The time for work and the time for life blends together more often these days, whether it’s taking a shower between Zoom meetings or putting in a load of laundry while you’re on a call. The bottom line is that homes have become offices, schools, gyms, and restaurants. The space that’s supposed to be a sanctuary - has come to fill our every need, but not everyone was prepared. I sure wasn’t - Had I known this was coming, I would have sprung for an apartment with office space instead of having to build a schedule for my partner and I so that we’re not taking calls from the same room at the same time.

Nothing is “normal” or “balanced” right now, but I’d posit that the change and adaptation that we’re currently experiencing isn’t necessarily a bad thing. It’s uncomfortable, sure, but growth is always uncomfortable - _it should be uncomfortable_ if we’re making progress. We’re uncomfortable because we’re laying the groundwork to ultimately outline a new definition of work itself, and this will have a positive effect on generations to come.

---
[View this page online](https://www.commandprompt.com/blog/are-we-working-home-or-living-work/)

---

# Optimizing the documentation

> The community has spent a lot of time optimizing features over the years. Excellent examples include parallel query and partitioning which have been multi-year…

The community has spent a lot of time optimizing features over the years. Excellent examples include parallel query and partitioning which have been multi-year efforts to increase the quality, performance, and extend features of the original commit. We should consider the documentation in a similar manner. Just like code, documentation can sometimes use a bug fix, optimization, and/or new features added to the original implementation.

Technical documentation should only be as verbose as needed to illustrate the concept or task that we are explaining. It should not be redundant, nor should it use .50 cent words when a .10 cent word would suffice. I would like to put effort into optimizing the documentation and am requesting general consensus that this would be a worthwhile effort before I begin to dust off my Docbook skills. 

I have provided an example below:

Original text (79 words):

 _This book is the official documentation of PostgreSQL. It has been written by the PostgreSQL developers and other volunteers in parallel to the development of the PostgreSQL software. It describes all the functionality that the current version of PostgreSQL officially supports._

 _To make the large amount of information about PostgreSQL manageable, this book has been organized in several parts. Each part is targeted at a different class of users, or at users in different stages of their PostgreSQL experience:_

Optimized text (35 words):

 _This is the official PostgreSQL documentation. It is written by the PostgreSQL community in parallel with the development of the software. We have organized it by the type of user and their stages of experience:_

Issues that are resolved with the optimized text:

  * Succinct text is more likely to be read than skimmed
  * Removal of extraneous mentions of PostgreSQL
  * Removal of unneeded justifications
  * Joining of two paragraphs into one that provides only the needed information to the user
  * Word count decreased by over 50%. As changes such as these are adopted it would make the documentation more consumable.



I have posted this example to [-hackers.](<https://www.postgresql.org/message-id/CAJvJg-Q-R1L%3DcxL8jG0kLosv3-HidGn-7pWYQemverLM_ABk3w%40mail.gmail.com>) What are your thoughts?

---
[View this page online](https://www.commandprompt.com/blog/optimizing-documentation/)

---

# Null Characters: Workarounds Aren’t Good Enough

> By Anders Cornell, Jr. DBAPostgreSQL is a great piece of software. Its features are well-designed, and they compose elegantly. It’s among the most versatile an…

By **Anders Cornell, Jr. DBA**

PostgreSQL is a great piece of software. Its features are well-designed, and they compose elegantly. It’s among the most versatile and reliable software I've ever used and its comprehensive superiority over other relational database products leads me to think of PostgreSQL as the data-store that can do anything. But today I'm here to discuss something that PostgreSQL can't do: handle null characters (also known as zero bytes) in text values.

Conventionally, a zero byte is reserved to mark the end of a text string, so a zero byte _inside_ a string is a contradiction. If a text string were to contain a zero byte, then that string would be truncated by any software that relies on C’s null-terminator convention. Text encodings have evolved since this convention was established, but no widely-used encoding has introduced a new meaning for the zero byte. So, regardless of encoding, if a zero byte is encountered within a string, it is probably safe to assume that it is there by mistake.

In contrast, modern systems treat zero bytes with much more passivity. Strings are no longer null-terminated in the software of this century; instead, every string is stored with an explicit length. This describes almost all software written in C++, Java, Python, Ruby, Go, JavaScript, Clojure, or Rust, for example, as well as most newer C code that does serious text handling. Application software that treats a zero byte as a string terminator is now the exception.

As a result, mistake or not, zero bytes occur in text nowadays. Cosmic rays, buggy UI code, and meddlesome users are all capable of producing a text string containing them.

Ideally, these zero bytes and other splashes of definite meaninglessness in text could be summarily rejected as errors, but human language is horrifically complicated, and in practice text validation must be conservative. Absent higher-level, application-specific validation, the most you can do without stepping on someone’s toes is to verify that the bytes of a string decode to a sequence of valid characters in your chosen character set.

Since it’s 2020, your chosen character set is Unicode, encoded with UTF-8. In UTF-8, a zero byte represents the code point U+0000 (NULL), just as a 0x61 byte represents U+0061 (LATIN SMALL LETTER A). The Unicode Standard does designate some code points “noncharacters” that “should never be interchanged,” but U+0000 is not one of them. In other words, there is no basis for rejecting null characters in the standard. Accordingly, UTF-8 decoders and Unicode normalization routines, as found in modern library code, do not reject null characters.

But PostgreSQL, whose backend codebase is over 30 years old and written in C, does. Try, for example:
    
    
     _postgres=# SELECT e 'string with a \0 byte';_
    
    
     _ERROR: invalid byte sequence for encoding "UTF8": 0x00_

PostgreSQL's UTF-8 text type does not allow zero bytes. In other words, there are valid Unicode text strings that PostgreSQL cannot store as text.

The implications are far-reaching due to the foundational nature of the text type. For example, jsonb represents JSON string values internally as text, which means that, counterintuitively, it is possible to give PostgreSQL some valid JSON and get back an error:
    
    
     _postgres=# SELECT '{"a_json_object": "with_a_\u0000_byte"}'::jsonb;_
    
    
     _ERROR: unsupported Unicode escape sequence_
    
    
     _LINE 1: SELECT '{"a_json_object": "with_a_\u0000_byte"}'::jsonb;_
    
    
     _^_
    
    
     _DETAIL: \u0000 cannot be converted to text._
    
    
     _CONTEXT: JSON data, line 1: { "a_json_object":..._

To give another example, it is similarly impossible to use PostgreSQL's text-search features on a document containing null characters, since such a document is not representable as text.

To be fair, for a system that cannot accept text with null characters, PostgreSQL handles text with null characters commendably. It's careful not to let a null character slip in through DML, and throws a descriptive error rather than silently truncating the string. Furthermore, the frontend-backend protocol does _not_ use null-termination, sparing database driver code the responsibility of catching zero bytes. It's hard to imagine how a system that uses null-termination internally could behave better in the face of null characters. Most software written in C does much worse, and PostgreSQL's diligence does a lot to head off potential [null-byte injection](<http://projects.webappsec.org/w/page/13246949/_>) vulnerabilities.

However, PostgreSQL **comes in last** among relational databases in null character support. Oracle, MS, and even MariaDB, for all their faults, treat U+0000 like any other character.

If one accepts that text can contain null characters, but still wants to store such text in PostgreSQL, there are two workarounds:

  1. Strip null characters out, or replace them with a different character (I suggest U+FFFD REPLACEMENT CHARACTER) before passing text values to the database. Otherwise, PostgreSQL will abort the transaction and throw an error. The possibility of null characters must be considered at every occasion where your application hands a string off to the database. Even though null characters are rare and unmeaningful, the need to remove them will present an unexpected burden.
  2. Abandon text and store the UTF-8 bytes of the string in PostgreSQL as bytea instead. Zero bytes are, of course, permitted in bytea values, so a column of type bytea can store any valid UTF-8 string. (Not to mention any invalid one.) With bytea, INSERTing a valid string will never cause an “invalid byte sequence” error, and when later SELECTed, a string will return from the database with all its characters intact. This transparency comes at the expense of all of PostgreSQL's text-processing features. JSON, full-text search, locale-aware comparison, regular expressions and more are unavailable when using bytea.



One of these approaches must be identified and implemented on an application-by-application basis. As long as PostgreSQL rejects null characters, individual engineering teams will continue to spend time working around the problem. Some teams have been lucky, their systems never encountering a null character, and haven’t had to spend time implementing a workaround. This will become less common as UTF8-encoded Unicode becomes the standard approach to text representation and the null terminator convention dies off--both of these processes are well underway.

There is only one solution. It will be difficult, but it is necessary. PostgreSQL must learn to accept null characters.

Supporting null characters will be a breaking change, but on the bright side, it need not break applications or database drivers--the frontend-backend protocol could be respecified to allow embedded nulls, without changes to client-side code, because text values in the protocol are already length-prefixed, not null-terminated. Text values are also length-prefixed in tuples on disk, so no change is needed in the disk data format either.

Here's my four-step plan for fixing PostgreSQL to support null characters:

  1. Switch to a length-prefixed string representation for all internal text-processing code: Datum (already length-prefixed) instead of char *. Null characters are still disallowed, but at this point, absent extensions, the database could handle them correctly.
  2. Deprecate public functions (functions in both the C and fmgr sense) that use the cstring data type. This includes supporting and preferring Datum-based I/O functions for new base types defined in extensions, instead of the cstring-based ones that are currently required.
  3. Introduce a cluster-wide, off-by-default configuration option for allowing null characters. Turning the option on will break extensions that use the deprecated functions, and applications that assume null characters are illegal.
  4. Far in the future, when the null-termination convention is but a distant memory, allow null characters by default.



Null-termination is a relic, and beginning to show its age. A previous generation of developers may protest, but in software that handles UTF-8 text, erroring on zero bytes should be considered a bug. To keep its status as a reliable, enterprise-grade, production-ready relational database and worthy core component in modern software stacks, PostgreSQL must make this difficult transition.

How has the null-character bug affected your company? Did you discover this blog post after a single zero byte crashed your entire application? What do you think of my four-step plan? Let's make PostgreSQL better together. Leave a comment below.

---
[View this page online](https://www.commandprompt.com/blog/null-characters-workarounds-arent-good-enough/)

---

# Meet Lindsay Rae Hooper: Command Prompt's fun-loving haystack

> Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Lindsay Rae Hooper, D…

Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Lindsay Rae Hooper, Director of Marketing and Events

 **How long have you been with Command Prompt?**

I started with Command Prompt in September 2019, so I’ve been here a little over a year. I knew JD and Amanda through [Postgres Conference](<https://postgresconf.org/>) so when I left my last organization it was a natural fit.

 **What’s your background and expertise?**

I originally moved to NYC to work in art galleries but quickly found myself doing events and marketing. From there, I took a deep dive into high end events, fundraising, and hosting galas for non-profits.

After a bit I was looking for more stability and so I joined a recruiting firm that had its own event series, which I ended up running for a few years. When I left, it was to go in house at tech companies before finally breaking off to consult and freelance. I was really lucky in that I was able to cut my teeth on events of all shapes and sizes, targeting a variety of audiences, so I’m a little bit of a jack-of-all-trades, master of..some?

My background in film has come in handy this year as it taught me how to handle digital media, which has made switching to a year of digital events far simpler than it could have been.

 **What has working in Open Source / Postgres taught you?**

As a non-technical person who’s been working in tech for the better part of her career, getting into open source has been illuminating. I don’t think that many non-technical people realize that there’s an arm of technology that’s a) so pervasive and b) free for anyone to access. Because Postgres is the crux of so many financial institutions and otherwise, we’ve all come into contact with it without knowing.

I spend a lot of my free time with a non-profit called Mouse, which brings STEM education to under-funded school districts. Knowing that there were coding languages that students could learn with no financial investment was a game changer in the way that I think about learning and teaching technology. Top it off that Postgres and OSS in general has such a vibrant, collaborative community, and I think OSS is going to be the future of how we teach children to code.

 **What kinds of roles are available for non-technical people in tech? What should a non-technical person look for in a tech-based organization?**

The thing that I think a lot of folks don’t realize is that all organizations - tech-based or otherwise - have universal needs. All companies need a technical arm, a brand awareness arm, an income arm, and a people arm. So the answer to this question is that there are loads of roles for non-technical people in tech. A Series B startup isn’t going to need as much [wo]manpower as a fortune 500, so the needs and scope of individual roles will vary within each organization.

Something that I think job seekers forget is that interviewing is a two way street - the potential employer is evaluating you as much as you are them. When it comes to _what to look for in a tech-based organization_ , I think the answer is that you should be looking for a good fit. You need to know that you will be valued and trusted and given equal credit for the work that you do, and that someone’s Ivy League degree in Data Science won’t make them more valuable in the eyes of your employer because you have something awesome and vital to offer as well.

 **What’s your greatest motivator?**

On a personal level, my greatest motivator is my family. I want to be successful in order to make my family and partner proud. I’ve carved out a wonderful life in NYC and I work to protect that.

My other greatest motivator is fun. I thrive where there’s work to be done in a creative way and a certain level of engagement is vital to my success. I know that being an events manager seems fun on paper, but the truth is that I spend more time working in spreadsheets and poking holes in my own plans than I do at events, especially these days. That being said, I actually have fun in spreadsheets and poking holes is one of my favorite pastimes, so I’m super engaged.

 **If you could recommend one learning resource, what would it be?**

Books. Read all sorts of books: memoirs, biographies, fantasy, history, mystery, anything you can get your hands on. I’ve learned more about myself through reading about the lives, perspectives, decisions, and experiences of others - real or imaginary - than I have anywhere else.

 **Considering the current state of things, what tips do you have for those now working from home successfully?**

My number one recommendation is to create systems to hold yourself accountable. I’m a meticulous tracker of time and tasks, so the last thing I do each Friday is completely outline the next week’s tasks and schedules so that I’m ready to dive in first thing Monday with a plan. I come up with a list of tasks that must be completed and then another list of tasks that either need to get done as housekeeping or that are projects that need to be built out slowly. Every week looks a little different for me, and that’s a plus in my book.

I’ve read through the other team members’ answers and while I agree that you need to set clear parameters for when and how you work, I’d also recommend _enjoying it_. That may not be groundbreaking, but last year I went from having to be in an office five days a week to completely controlling my own schedule.

I take building my schedule as a really serious responsibility, but I also take it as an opportunity to live a more holistic life. I’m able to exercise and cook when I please, and I’m able to make time to see friends who’s schedules haven’t always lined up with my own. All in all, I couldn’t recommend working from home enough.

 **Where can we find you on a Saturday afternoon?**

Every Saturday looks a little different for me. These days I can usually be found doing brunch with my COVID pod while we watch Penn State football. When NYC locked down in March we pretty religiously started finding fun meals to cook and TV series to binge, so between football games we’re currently watching Dexter and Fringe. Post-brunch I usually dive into my book or go for a long walk around my neighborhood.

 **Would you rather battle one horse-sized duck or 100 duck-sized horses?**

Another toughie. I’m not known for my coordination, but I think I’d fare better with the 100 small horses. At the very least I’d be able to beat their little legs to higher ground?

 **Desert island food?**

My two favorite foods are pickles and apples so probably one of those. Both provide hydration and I can eat them en masse without getting bored. I feel like I have to be specific here because if I’m getting stranded on a desert island but I get to choose my own food, there could be some monkey’s paw shenanigans going on, so specifically I think dill pickles or pink lady apples. I’d be just beside myself if I requested pickles and apples and got sweet pickles and tart apples.

 **What book should everyone read?**

There are so many good books out there. I’m torn between _The Cheese Monkeys_ , by Chip Kidd, and _The Great Gatsby_ , by F. Scott Fitzgerald. Both are incredible books about self exploration and identity, and they’re wrapped in some pretty delicious stories. One is obviously far more well known than the other, but I make a point to reread both annually.

 **What should everyone see/do before they die?**

I can think of some pretty profound things that could sufficiently answer this question, but I’m actually going to go with a relatively mundane and accessible suggestion: I think everyone should eat alone in a restaurant. And not just eat, but get comfortable sitting alone and enjoying a meal with yourself. I think it can be a hard thing to do - there’s even some stigma about it - but learning to enjoy your own company will be one of the most valuable experiences of your life. It’s a gift that keeps on giving.

 **Other than Postgres, what topic are you an expert on?**

I’m decidedly not a Postgres expert, but I can _talk the talk_ to some extent. I’m not sure I’m actually an expert on anything, but I do pride myself on being good with people. It’s important to meet folks where they are and on their terms, that I’d like to think that that’s something I’m pretty good at doing. While I can talk the paint off the walls, I pride myself on listening and placing appropriate value on the things that others say. I’m not sure if this answers the question, but it’s the best I got.

 **Early bird or night owl?**

Neither - I wake up at the entirely boring range of 8:30am - 9:30am and I like to go to bed on the earlier end of things between 9:30pm - 10:30pm. I think there are certain times of the day that I’m better at doing different tasks - I prefer to work on my own in the morning and take meetings in the early afternoon, but maybe it’s worth noting that I slowly sip on coffee from the moment my feet hit the floor until about 3pm when I switch to seltzer. So maybe I’m less of an _early bird_ or _night owl_ , and more of a _coffee-powered being_?

 **What subject should be taught in schools but isn’t?**

There are tons of things that I wish I had been able to learn in school, but I think my answer to this is less about what is or isn’t taught, and more about how it applies. In retrospect, a lot of what I learned in school was less about the material itself and more about how it taught me to think and react to challenges. I always thrived in English class because it’s “something I’m good at,” but the value that I took from those clases was less about reading and writing and more about critical thinking. I struggled my way though math and science, but the true lessons that I learned from those classes was how to create workarounds and ask for help when I needed it.

I have vivid memories of telling my mother that I would literally never need to know physics in my adult life, and to some extent I was right. What I didn't yet realize is the value of the resilience and fortitude that that class taught me. I thought I was just surviving the class but it was really teaching me a hard lesson about how to move through the world.

 **When you were a child, what did you want to be when you grew up?**

Like most kids, what I wanted to be changed moment to moment. The most enduring career choice was that I wanted to be a veterinarian, but because I couldn’t bring myself to do dissections, I wanted to create a way to become a vet without having to cut into animals. Simultaneously, I always wanted to be a Radio City Rockette, so I figured I could be a full time vet and a full time dancer, and when you’re a child, that’s entirely feasible.

---
[View this page online](https://www.commandprompt.com/blog/meet-lindsay-rae-hooper-command-prompts-fun-loving-haystack/)

---

# IS OF

> I am on the phone with Eric Ridge of ZomboDB and PGX fame. We chat often on the People, Postgres, Data Discord server (yes you should join) and we have unoffic…

I am on the phone with Eric Ridge of [ZomboDB](<https://zombodb.com/>) and [PGX](<https://github.com/zombodb/pgx>) fame. We chat often on the People, Postgres, Data [Discord server](<https://discord.gg/tjxNBCz>) (yes you should join) and we have unofficial “we are human so we get on the phone” calls about twice a month. The calls are generally about PostgreSQL and the awesome Open Source projects he is building around our famed database. However, on this call I got a question I don’t normally get: how good is your SQL?

Now this question is not nearly as mundane as you would expect. It is true, I would consider myself a PostgreSQL expert. However, that doesn’t mean I know anything about SQL and in fact I would argue that although I am competent in SQL, I am in no way (nor do I want to be) an expert. My love for PostgreSQL is in designing architecture, enterprise deployments and production class stability. In practice this means that I can design a highly available infrastructure in my sleep but I will be cursing the gods if you try to get me to write a CTE query.

## IS OF

The source of his question was that during the development of one of his upcoming Open Source Rust tools for PostgreSQL he ran into “IS OF” and asked if I have ever heard of it. I had not and we went on a mission to find out what IS OF was all about. It appears that the purpose is simple, useful and potentially powerful. I would also like to mention that IS OF appears to be PostgreSQL specific and completely undocumented except in some obscure portions of the code.
    
    
    postgres=# SELECT 4 IS OF (text);
    
    
    ?column? 
    
    
    ----------
    
    
    f
    
    
    postgres=# SELECT 'four' IS OF (integer);
    
    
    ?column? 
    
    
    ----------
    
    
    f
    
    
    postgres=# SELECT 2 IS OF (integer);
    
    
    ?column? 
    
    
    ----------
    
    
    t

As you can see IS OF is used to determine if a value is valid as a particular data type. In these two cases, 4 is not considered text (it would be if you were to use ‘4’), ‘four’ is not of type integer and 2 is of type integer. What could we use this as in a real world example? Would it make sense to extend IS OF abilities?

---
[View this page online](https://www.commandprompt.com/blog/is-of/)

---

# Professionalism Matters - Even When Working Remote

>  Today we are working from home, from the road, or from family’s homes. Article after article has been written about how to work productively outside of our no…

Today we are working from home, from the road, or from family’s homes. Article after article has been written about how to work productively outside of our normal work environment. What they tend to leave out is that professionalism isn’t just for the cubicle; it extends to all matters of the office including working remotely. 

That means being purposeful and professional _every day_. That includes being respectful, dressing for success, being punctual, having a positive attitude, keeping your working area clean, minding your manners, having a brain to mouth filter, avoiding gossip, not slacking off, etc. It’s amazing how quickly these simple behaviors go out the window the moment we aren’t in a physical office. Being in an office has constant accountability; working elsewhere doesn’t. Why worry about such things when working from home? It isn’t about mandating a conformist ideal to suppress your individuality. It’s about setting a standard of excellence for the job to be done, and also setting a better standard for yourself. It helps create a mindset that is essential for staying productive, which is necessary in a time full of distractions.

One of the most underrated and important ways to stay productive is dressing for the part. If normally a suit is required, wearing a sweatshirt and sweatpants will not provide the same level of psychological support and professional accountability. For some roles the outfit is part of the job - that doesn’t change when working from home. It becomes part of how you get things done. 

There is a reason that Major League Baseball is now placing cardboard cutouts of fans in the stands during games. It’s a simple yet effective solution to get players in the right mindset. 

Don’t reinvent the wheel when you already have a full toolset. Habits we have learned to focus our minds allow us to not focus on the minutia and be productive. Simple, professional habits such as the clothes that you wear or the visual fans you use are tools that we’ve already learned and shouldn’t be abandoned in this time of flux. They should be relied upon as easy ways to help us achieve success.

A defining part of being a professional is presentation, not just in your clothing but also your attitude, your written word, and your ability to perform at a level that defines success for yourself. The suit or dress may not be essential for you and that’s for you to decide. Being a professional, however, is vital. It is not only for your success and future, but also for the company you represent. Even though it may not be face to face, your presence is viewed by others and it’s important to remember how blessed you are.

The opportunity for success is only limited by your willingness to put in the right amount of effort.

---
[View this page online](https://www.commandprompt.com/blog/professionalism-matters-even-when-working-remote/)

---

# Meet Justin Graf: Command Prompt's Offgrid Aficionado

> Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Justin Graf, DBA.How …

Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Justin Graf, DBA.

 **How long have you been with Command Prompt?**

I started in March 2020, but I’d known about Command Prompt since 2004/05. At the time I was looking for a new ERP/MRP package for the company that I was working for as the one we bought for the Y2K Bug wasn’t working out. It required too many people to keep touching things, there were a lot of repetitive steps, and there was no way to automate tasks. I knew a little bit about Postgres but everything I had read said that it was still an immature database and to use MySQL. But MySQL had way too many issues with data types - it would do all kinds of interesting things like autocast and make data disappear. It treated Nulls pretty weird - all bad things for a DBA type person, so I ran into it with xTuple. I ran back into Postgres when I started using that.

I was doing some benchmarking and the Postgres community noticed me when I posted on Channel9 on Microsoft, and the community goes, _well who’s this yahoo_ , and I piped up and was like, _I’m the yahoo!_ That’s when I met Greg Smith and JD (Command Prompt’s founder).

Eventually I went to a company that did non-destructive test equipment - I did their ERP/MRP rollout and custom programming, but I got bored. It was when I had just started to look for another job that Command Prompt put a posting out there. I jumped on it, they liked me, and so here I am six months later.

 **What’s your background and expertise?**

My expertise primarily has to do with MRP, programming, and computer architecture around manufacturing. I have a strong background in programming around cost accounting and manufacturing techniques.

 **What’s something you wish more people understood about Postgres?**

In terms of databases as a whole, I wish more people understood relational algebra. Relational algebra is the base theory of all relational database models - doesn’t matter if it’s SQL, MySQL, Postgres, or Oracle. It’s a theory that was created in the 1970s by an IBM engineer named Edgar F. Codd, and it’s the core idea behind how to build a relational model.

If programmers spent time doing some basic research behind relational algebra and how the relational model works, then a lot of our job would go away. They would also avoid a lot of the pitfalls of using bad technology, and that feeds into MongoDB and document databases.

If engineers understood how relational databases actually worked and how freeing they are - how easy they are to manipulate and play with - then they’d understand why the document model of databases was abandoned in the ‘70s. It didn’t work in the ‘70s and it doesn’t work today, but here we are.

 **What’s your favorite project of all time?**

Personally it would have to be my ongoing project with my kids. My kids are my life-time project.

Technically speaking, my offgrid project would be my favorite. I’m getting my own solar panels and building my own off-grid stuff. Piecing it together myself - not buying a kit - I have to source the inverter and I want to be able to flip between on grid and off grid quickly and easily in case I lose battery or the solar panels. It’s a bit of an oddball requirement because it’s not typically addressed by most systems out there. I’m trying to make it all automatic, and then tie it all together with a computer at some point with automatic switching.

 **What’s your greatest motivator?**

I hate that question because what motivates me is a challenge. If I don’t have a challenge then I don’t want to get up and do it. I’m really enjoying working with Command Prompt because somebody’s always going to come up with a new challenge, so I always get to work on something new and interesting. I like challenges - I don’t like sitting still.

 **If you could recommend one learning resource, what would it be?**

The help files: Read the help files that come with whatever program you’re using. You should always start by reading the help files - be it the man page or the Postgres help pages. It’s the single greatest thing that programming languages offer in terms of learning resources because that’s where everything you need to know lives.

Googling for answers or looking on Stack Exchange doesn’t guarantee the right answer: So many engineers have tried to lean on Stack Exchange, but it usually blows up in their faces because it’s wrong. I’ll use it occasionally, but I always start with the help files.

 **What’s the future of open source technology?**

Open Source continues to expand and grow. I think the days of closed source tools are numbered - Users are starting to demand more free tools because so many closed source tools haven’t actually improved in years. I think that type of revenue source will disappear and instead we’ll be left with Open Source, or at least freemium, tools.

Open Source is taking over the market as time progresses. It’s already taken over the server world and it’s slowly but surely taking over the database world because of high pricing. The cost motivator will continue to drive this change as the economic downturn continues to hit us. People will be able to fix their problems with Open Source and not have to worry about spending on closed source technologies. It’s going to continue to expand to other fields because people will be able to expand the use of a product as they need to instead of being trapped to a vendor’s desire to fix their code.

The only potential pitfalls are if they don’t keep the corporate minders out of it. Knowing the history of large corporations, I could easily see them trying to take a divide and conquer approach by putting people in key places. Like if someone gets into the Linux kernel, and they started adding issues or breaking it so that the code isn’t trustworthy. This would be absolutely intentional, so I see the pitfall being if we let these giant corporations in and they start contributing significantly more code and get on the steering committees. If they get on those committees I can easily see them torpedo Open Source in order to force users back into their loving, embracing arms.

 **As someone who has successfully worked from home, do you have any tips for those now working from home for the first time?**

Stick to your schedule - follow the same schedule as you would if you were going into an office. Get up, take a bath, do all the basic stuff you do to go to work, get dressed, and work diligently that way.

 **Where can we find you on a Saturday afternoon?**

Working in my yard, farming, gardening, cutting down trees. In terms of farming and gardening, if it’s not edible I don’t grow it. I have chickens, but they’re pretty self sufficient - I just have to feed them once a day. I have them trained so that when I clap, they come and they know it’s food time.

 **Would you rather battle one horse-sized duck or 100 duck-sized horses?**

Well, I’ve been swatted by a duck when it was mad and once you’ve been slapped upside the head by a small duck wing, I don’t want to think what that horse-sized duck is going to hit me with. That’s just terrifying, so I’ll take 100 small horses because you can outrun them. Believe me, if you get hit by that duck’s wing you’re in big, big trouble. That’s not a fight I want.

 **Desert island food?**

Potatoes: You can live off them and you aren’t going to die of malnutrition. Potatoes have all the vitamins and minerals you need. They’re also easy to grow. Finally, you can fry them or bake them or cook them all kinds of ways, unlike most foods. It’s one of those rare plants that covers the whole gamut.

 **What book should everyone read? Watch?**

I think everyone should read [_Democracy in America_](<https://www.goodreads.com/book/show/16619.Democracy_in_America>) because I think it shows a very important concept of society. How you’re supposed to work in a democracy or in a republic. It’s the story of how French aristocrat arrived in the US in the mid-1800’s and saw how democracy was working in America. I think it would correct a lot of false impressions around what a democracy actually is. Without a free society, you don’t have anything: You stagnate.

 **What’s one thing that everyone should watch?**

Star Trek is a good philosophy flick. It has a lot of philosophy and science in it, and it’s inspirational for people, especially when you’re younger. From that perspective, I think it’s a good series to watch.

 **Other than Postgres, what topic are you an expert on?**

I like to call myself a jack of all trades, master of nothing. So I know quite a bit about manufacturing, ERP packages, Postgres, Python, FoxPro but that’s getting long in the tooth, and electrical theory.

 **Early bird or night owl?**

Neither - I wake up when the sun comes up and I don’t even have an alarm clock.

 **What subject should be taught in schools but isn’t?**

Morality and spirituality. Look at our great philosophers: They all state that without morality, you cannot have a republic. WIthout a moral, just society, you cannot have a functional republic. It just devolves into corruption.

 **When you were a child, what did you want to be when you grew up?**

I wanted to be a doctor because I wanted to help people. Specifically, I wanted to be a surgeon, but as I grew up, it wasn’t the schooling that scared me off that path - it was all the legal hoops.

---
[View this page online](https://www.commandprompt.com/blog/meet-justin-graf-command-prompts-offgrid-aficionado/)

---

# Pay it Forward

> Where were you the first time you were told to “pay it forward?” Were you the recipient of someone else’s good deed, or did a friend or mentor help you out of …

Where were you the first time you were told to “ _pay it forward?”_ Were you the recipient of someone else’s good deed, or did a friend or mentor help you out of a pickle? _Paying it forward_ is a fascinating concept with far reaching effects. [According to Dictionary.com’s Pop Culture Dictionary](<https://www.dictionary.com/e/pop-culture/pay-it-forward/>), _Paying it Forward_ is defined as “an expression for when the recipient of an act of kindness does something kind for someone else rather than simply accepting or repaying the original good deed,” and it’s a concept that has been popularized through books, TV, movies, and theatre. Even Oprah launched her own [Pay it Forward Challenge](<https://www.oprah.com/spirit/paying-it-forward/all>), where audience members went into their own communities with the goal of inspiring others to pay it forward.

At a time when everyone could use a little extra kindness, paying it forward has never been more important. Some are out of work and hoping that their local food bank stays open, others are doing their damndest to save the post office. Even beyond that, most of our nation has been cooped up for the past six months, and we’re cagey. We can all use a little extra love right now. So in that spirit, I present to you a list of ways that you can pay it forward:

 **The everyday kindness**

Everyday kindness is often overlooked as we move through the day-to-day: Proactively holding doors, offering to get something from the kitchen for our partners, making eye contact and saying thank you to the grocery store clerk. These are all simple ways to make someone’s day easier. These small acts can make a huge difference. A simple way to start is by considering what those around you could do to make your day a bit brighter, and doing that for someone else.

 **The technical know-how**

The open source community is uniquely positioned to contribute to one another's' projects. Because OSS depends on its users also moving the needle forward, the opportunity to pay it forward becomes inherent in our everyday work and projects. Have you been struggling with a particular bug in someone else’s code? Submit a patch that will make it easier for everyone to benefit from the project. 

**The community builder**

What do you consider to be your core community? Is it the neighborhood where you live or your online network of fellow makers? Aiding those within your network will have long-reaching effects that will leave your community better than you found it. Start a catalyst by asking around to see who needs help, and be proactive about seeking out ways to volunteer your time, offer your talents, or donate your treasure. 

**The** **_call to action_**

Check in with organizations and nonprofits that bring value to your community. See what their needs are (I promise you they’re in need of something), and fill the gap. Looking for low hanging fruit? Many nonprofits depend on volunteers and pro-bono work to get their websites built and up to date - how could you make an impact there? If website building isn’t your thing, offer to donate time by editing content, creating graphics, or launching a social media campaign.

 **The** **_I’ve been there before_**

Where were you during the hardest point in your career? Were you laid off, struggling to make ends meet, working in a toxic environment, or just graduating from college and looking for a foot in the door? Consider what you needed then: Was it a shot at employment, or was it a mentor? You can provide both today by engaging with your network and putting the call out to those who need support.

 _Paying it forward_ is a two part process: Doing something kind, and then instilling in the recipient the desire to do something kind for someone else. It’s all of our responsibility to make the world a kinder place, and the impact is tangible: If 100 people in the OSS community did one kind act in the next month, and set off a chain reaction of one more person doing one more good thing per month for the next year, that’s nearly 1,200 acts of kindness in the next year. And even better, if they continued to create one act of kindness _per month_ for an entire year, that’s an exponential number if acts of kindness started by our very own community. 

How will you pay it forward?

---
[View this page online](https://www.commandprompt.com/blog/Pay_It-Forward/)

---

# The COVID-19 Pivot: An Opportunity for Reflection

> As we get more immersed in our careers and lifestyles, we get comfortable. And when we’re comfortable, we avoid tasks outside of our wheelhouse like the plague…

As we get more immersed in our careers and lifestyles, we get comfortable. And when we’re comfortable, we avoid tasks outside of our wheelhouse like the plague (or pandemic). Yes, we grow and we learn, but we love to stay in our field; our realm of comfort, our box. Generally speaking, we can stay where we want, but with the changes of 2020, the question for many people has now become: what else does my skill set allow me to do that I hadn’t considered? 

Having worked in-house on marketing teams and more generally in the events industry - an industry, which, sadly, will be forever altered - I still need to make a living until I can go back to planning galas, conferences, and even intimate events. The pandemic has forced me to take a look at what I know how to do and find a way to retool it. By considering my skills with an open mind, I’ve discovered that I’m a project manager, and _project manager_ is infinitely more employable than _event professional._

This revelation has encouraged me to expand the industries where I can apply my skills. I’ve grown to see events less as discrete entities and more as a means to an end, with the “end” being increased sales, brand awareness, or market share. With that in mind, I’ve been inspired to branch out to markets that I had previously thought myself unqualified for. 

Case in point? My background hardly qualifies me to work in open source software, but every contemporary organization demands a marketing presence, so here I am, applying my core skill set within this industry in order to fill a need within an OSS organization.

This may not be where I saw myself in 2020, but I’m also one of the few events professionals who is still working in the middle of a pandemic. I’m grateful for that, and it’s only possible because I took what I know and pivoted in a new direction. The truth is that we don't know what the hiring market in the events industry will look like for the foreseeable future. Regardless, it is imperative that we look at **all** of the opportunities we have.

Tips on how you can explore your own COVID-pivot:

  * Consider what your core skill set is and where/how it can be applied elsewhere. 
  * Consider what value you bring to the roles where you’ve had past success. 
    * Are you better with strategy or tactically executing a plan?
    * Do you prefer being behind the scenes or in front of people?
      * Reach out to past managers to get their feedback. Not comfortable reaching out to them? Consider talking to peers and co-workers about your perceived strengths and pain points.
      * Write all of this down - the act of writing will help you look at everything from a holistic perspective and allow you to be objective.
  * Ask yourself how you can create opportunities for yourself. When your home market returns, you’ll be more prepared than ever to tackle your next role or project. 
  * Look into industries where your skill set fills existing needs. 
    * Leverage your network and test the waters a bit. By virtue of existing in 2020, every industry has diverse needs, so be sure to explore industries where you may not feel comfortable. 



You may end up doing things that aren't in your normal wheelhouse, or you may find yourself in a familiar industry. Either way, you are still moving forward. You will find success if you are flexible and willing to retool your skills or learn new ones. If you wait for the perfect opportunity, you'll be left behind while the world heals.

---
[View this page online](https://www.commandprompt.com/blog/the_covid_pivot/)

---

# Meet Ron Farrer: Command Prompt's Lifelong Tinkerer

> Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Ron Farrer, one of Co…

Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Ron Farrer, one of Command Prompt's System Administrators and JR DBA. 

**Where are you based?**

 _I’m from Bellingham, Washington. I currently reside 20 minutes north, but in a few weeks I’ll be moving back to Bellingham._

 **How long have you been with Command Prompt?**

 _I’ve been with Command Prompt for five years. JD posted in the_ [_Bellingham Linux Users Group_](<https://www.blug.org/>) _and I didn’t know it at the time, but JD was also located in Bellingham. All I knew was that Command Prompt did open source work and a lot of stuff with Linux, so I emailed him directly to ask if he had any job openings. After a few interviews, I joined the team. It was only after I got hired that I learned that JD, Amanda, and Eric are all in the Bellingham, Washington area._

 **What’s your background and expertise?**

 _I’ve been using Linux since late 1993, and Unix-like systems since the late ‘80s/early 90’s. I’ve had an interest in computing since I was quite young - I loved the way that computers worked and the possibilities of everything you could do with them._

 _I actually studied computer science in college, and for my first bachelors degree I majored in history and minored in computer science. For my second bachelors, I majored in computer science and minored in mathematics._

 _I’ve worked for a few places over the years. I worked for a value-additive vendor in the Seattle area when I was in my late teens, and then I owned a few businesses, one of them doing web hosting. I worked for Debian for a few years, and then moved to a few open source projects, and I was still doing the web hosting business right up until I was hired at Command Prompt. By that time, I think the business side of web hosting wasn’t there anymore because people were migrating to the big companies like Rackspace._

 **What’s your favorite project of all time?**

 _My favorite project that I personally worked on would be the Debian GNU/Linux Alpha port team back in the late 1990s. We worked on porting 32-bit Intel x86 code to the 64-bit Alpha AXP architecture. Unfortunately, the Alpha architecture met its demise through a series of mergers/buy-outs when Digital Equipment Corporation (DEC) merged with Compaq, then shortly after Compaq was consumed by Hewlett Packard (HP). None of these companies cared about the Alpha and so it quickly became a relic, but the work those of us on the port teams did paved the way and made for an easier transition to 64-bit Intel/AMD processors in the early 2000s. It was a fun project to work on and the issues were interesting to think about at the time because the computing world had largely been 32-bit since the mid-1980s. Far too many people created things based on the assumption that the system is and would remain 32-bit._

 **What’s your greatest motivator?**

 _As far as work goes I still have that childhood fascination with computers and how they work, and I love to tinker with them. On the personal side, I’d have to say that my family and kids are my main motivators._

 **If you could recommend one learning resource, what would it be?**

 _It depends on the topic. For Postgres, as funny as it may sound, I’d recommend going to Youtube - there’s so many tutorials out there, and some of them are really great. For Open Source, I’d recommend investigating the discussion forums for your favorite aspect of open source. So for instance, if you’re interested in a Linux distribution, then the discussion forum for that distribution would be the best place to get information._

 **Considering the current state of things, what tips do you have for those now working from home successfully as someone who has done so for years?**

 _I would recommend keeping a set schedule, having a set work area, and remaining professional when you’re in that area. I’d also suggest taking breaks, or else you can end up in a mental funk. At least for me, when you get stuck on a problem and you don’t take a break, you end up repeating the same thing over and over again._

 **What’s the future of open source technology?**

 _The future is heading toward more cloud computing and more decentralized resources. I feel like, in general, we’re heading toward a place where we have our own personal devices - phones, laptops, etc. - but they’re going to do less and less on their own, and rely more heavily on computations in the cloud. I’d venture to say that the impact will be that you can do more with less, so our phones may become less expensive because they will do less on their own._

 **Where can we find you on a Saturday afternoon?**

 _Normally I’d be off doing something fun, but given our current lockdown situation, I’m probably going to be at home cleaning or doing random projects. Nothing too exciting these days._

 **Would you rather battle one horse-sized duck or 100 duck-sized horses?**

 _I’d go for the giant duck because then you’d only have one problem to focus on and commit to solving. With 100 small horses, it could be like death by 1,000 paper cuts._

 **What’s your desert island food?**

 _I’d have to go with tacos because they’re the most versatile thing ever. Carne asada is my go to._

 **What’s your best hidden talent?**

 _Deductive reasoning, and being able to step back and see things from a different point of view than most people._

 **Other than Postgres, what topic are you an expert on?**

 _There are a lot of areas that I have great interest in, but technically speaking, I’m an expert on operation-level stuff: virtual machines, networking security and cryptography, programming._

 _From a non-technical perspective, I’m an expert problem solver. It’s one of the things that draws me to computer science, mathematics, and helping people in general. If it has a hint of mystery to it, even if it’s only intriguing to me._

 **What subject should be taught in schools but isn’t?**

 _Teaching social skills in schools would be really helpful because I feel like the last few generations kind of lack that basic ability to interact with other people in a way that’s productive and non-confrontational._

 **When you were a child, what did you want to be when you grew up?**

 _I wanted to be a police officer when I was a kid. Cops just had that intriguing coolness factor for me._

---
[View this page online](https://www.commandprompt.com/blog/meet_ron/)

---

# Meet Debra Cerda: Command Prompt's Ranged Attack Expert

> Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Debra Cerda, Director…

Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Debra Cerda, Director of Business Development.

![](../../../../uploads/images/img_4046.jpg) 

**Where are you based?**

_I 'm based in Austin, Texas, and I've been here since 1993. I'm a native Texan, born and raised in Houston, but I visited Austin in '93 and fell in love with it. "Keep Austin Weird" is a throwback to the '60s and '70's of Austin, the very hippie culture - I'll definitely say that's something that appealed to me when I first visited. It's very laid back and eclectic._

**How long have you been with Command Prompt?**

_I joined Command Prompt in May of 2017 as Director of Business Development, so it 's three years this month. I actually knew our company Founder, Joshua Drake, and our Operations Manager, Amanda Nystrom, through volunteering at Postgres events. Most notable was as a room monitor and registration volunteer at the Postgres Conference in 2016 in NY when I was working for another Postgres company._

**What 's your background and expertise?**

_My background is quite varied. I would say that I have a bit of a_ portfolio career _that spans across a few industries, but what I bring to the table is 20+ years as a professional in the water industry, which helped pave the way for me to work within the Postgres community and subsequently volunteer with the PG Central Foundation.  _

_Water is data, whether it's technical specifications on ground water wells that have been drilled over the last century, risk analysis of drinking water contaminants, or trend analysis of contaminant pollutants -- how that data is processed into useful information is critical._

_I'm really fortunate that I had awesome professors and mentors throughout college. I credit them with teaching me the ethics and caveats of data collection and interpretation, which helped significantly when I was a drinking water quality specialist for the state of Texas. They taught me to really make sure that decisions were being made on a valid data set, that the data interpretation was very stringent, and that my documentation and findings were reviewed thoroughly by peers and experts.  _

_I was essentially a data manager and a database administrator when I worked for the state because I would create my own databases to run particular analyses relative to drinking water contaminants.  _

**What 's your favorite project of all time?**

_This is a tough one - I think that my favorite project was being part of the Accessibility Work Group for the state agency that I worked for. The purpose of the workgroup was to determine and advise action plan strategies to ensure compliance with the accessibility requirements of the state and the federal government. It was important because we ensured that everyone had equal access to information: building accessible websites and accessible content benefits everyone.  _

_A cored philosophy of accessibility is that accessible design is universal design. For example, closed captioning was created for people who are hard of hearing, but how many of us use it routinely, whether it's watching a foreign film that 's subtitled, or being at the gym and watching the newscast through the subtitles instead of sound._

_Achieving our goals for accessibility was challenging at times, though, because we were trying to shift a culture which included older staff members who were not familiar or comfortable with newer software programs.   _

**What 's your greatest motivator?**

_My greatest motivator is that I like to solve problems. I enjoy talking to people to understand their challenges and pain points so that I can help them find the right solution. This has been true when I was a drinking water specialist, helping a water operator to solve a problem with a contaminant, and now that I 'm working in Postgres, I help folks get on the right track by identifying their needs and determining what options are the best fit for them._

**If you could recommend one learning resource, what would it be?**

_One learning resource that I 'd recommend is Postgres Conference because conferences provide an immersive experience with so much to takeaway. _

_I was working on an evaluation for a client recently and I recalled relevant information that I 'd learned two years earlier at a conference session. I have a photographic memory, and I distinctly remember being in the room and the speaker made a specific statement about lessons learned in their cloud migration, and I was able to utilize that. I wouldn't have necessarily gotten the same takeaway had I not been in that room._

**As someone who has successfully worked from home for years, what tips do you have for those now working from home for the first time?**

_The top tip I have for working from home is to set a routine and boundaries, both for work and home. It 's easy to say "well here's what my work day is going to be," but your home routine is also important. Sometimes I find myself waking up and going straight to my computer, but then I've skipped the morning routine of shower/coffee/breakfast! Suddenly it's 1pm and I'm famished, so it's important to set a routine and boundaries. _

_It 's more challenging now for people who are working from home, perhaps because they have partners/roommates/kids who are also in the house with them. I live with my sister, so I always communicate to her when I'm getting on a client call and she respects that. Just because you work from home doesn't mean that you're accessible all day. _

**What 's the future of open source technology?**

_I think the future of open source technology is quite bright in that it can only be more embraced, especially considering our current economic crisis. Companies must be more mindful of spending while remaining resilient, and having to budget for licensed, proprietary closed source products doesn 't make great business sense. _

_Open source is a key driver of innovation. It 's wonderful that Postgres is a product that has a really supportive community worldwide, both in the product and in the community in itself. One challenge of open source is its messaging: Just because it's open source doesn't mean that it's not enterprise ready. Far from it, actually. There are many Fortune 500 companies that are using open source. I think that there are still some folks that believe that Postgres is a "hobbyist" database._

![](../../../../uploads/images/datageek.jpg)

**Where can we find you on a Saturday afternoon?**

_Pre COVID19, you could find me out at_[ _Jester King Brewery_](<https://jesterkingbrewery.com/>) _, leading public tours of the brewery and the farm. Maybe relaxing with the Nigerian dwarf goats who live on the property - I 'm missing those furry little beasts right now. I'll also often be at a local nonprofit volunteer day, for trail and park maintenance or at Urban Roots sustainable farm as a coordinator for our Jester King Volunteer Corps. _

**Would you rather battle one horse-sized duck or 100 duck-sized horses?**

_Is this solo or can I have a squad? Because if I can have a squad, then I 'd prefer a third option where you have one big boss duck and then all his little minion horses. I'd take the smaller ones out first and then go for the big guy. I like to use ranged attacks, so I'd be sitting back doing damage from afar, with a bow and arrow or something. But then again, if I could have a few folks from the Walking Dead, then I think we got it. I'd like to bring my Walking Dead posse with me. I'll let them handle the big duck because I do not like to deal in fowl play._

**What 's your desert island food?**

_My first thought was watermelon because I can eat so much of that, but the other thing is that it 's hydration. I could have said something like eggs because I love eggs and can eat them fried every day, but if you're on a desert island, it's going to be a lot easier to open and eat a watermelon to stay hydrated than it is to cook an egg._

**What 's your best hidden talent?**

_My hidden talent is being able to think "oh gosh there's nothing to eat in the house," but then pick out items from the pantry and be able to combine them to make a really great dish. For instance, if I see capers in the pantry, and then think, oh there's a lemon, oh we have olive oil and butter, then I'll end up with lemon pepper chicken piccata._

**Other than Postgres, what topic are you an expert on?**

_I 'm an expert on water: I've been involved in water since 1998, and I maintain my surface water license because once you lose it, it's really hard to get back._

**What subject should be taught in schools but isn 't?**

_I have two answers for this: The first is environmental literacy and food sustainability, so the understanding of where our food comes from and what our impacts are on the environment.  _

_The second course that should be taught is critical and analytical thinking. While I 've spent my entire life puzzling over how things operate and are put together, which included taking a butterknife to an electrical outlet cover as a child, I believe that a course that I took at UT on Pseudoscience is where I truly honed my critical and analytical thinking skills. It was a wonderful course by a physics professor that was essentially about questioning things. Critical and analytical thinking is paramount._

**When you were a child, what did you want to be when you grew up?**

_I wanted to be an archeologist when I grew up. I was fascinated by the stories of the tomb of King_ _Tutankhamun. I would - mind you this was when I was easily under ten years old - bury pieces of wood and come back to dig them up a few weeks later to see if they had petrified. I didn 't realize that that took more than a few weeks. I also dug a hole in the backyard to see if I could strike oil like Jed Clampett, and in my defense, not only were we in Texas, but there were oil fields and salt mines from about two miles from where I grew up. It wouldn't have been implausible - I just wasn't going to find it 2 feet down, it would have been more like 7,000 feet down into the ground. It's only recently that my dad understood why he always found holes in the backwater - I was digging for ruins and fossils and oil. _

_![](../../../../uploads/images/goats_landscape.jpg)_

---
[View this page online](https://www.commandprompt.com/blog/meet_debra/)

---

# Meet Andrew Smith: Command Prompt's Australian Altruist

> Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. Last month we talked with Andrew Smith, one of Comma…

Welcome to our blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. Last month we talked with Andrew Smith, one of Command Prompt's senior Developers. 

![](../../../../uploads/images/20200101.jpg)

**Where are you based?**

_I 'm based in Cebu, Philippines. There are probably more people telecommuting from Cebu than anywhere else in the world, and Cebu felt like the most natural place to live because I telecommute anyway. _

_I 'm originally from the Sunshine Coast, Queensland, Australia. I moved to Tasmania in my late 20's, and a few years ago I decided to challenge myself with the most difficult and scary thing that I could possibly imagine doing, and that was moving to a different country entirely._

**How long have you been with Command Prompt?**

_I first heard of Command Prompt 15 years ago, and way back then I was thinking that it would be a great fit for me because I love PostgreSQL. I 'm probably more passionate about PostgreSQL than any other single thing, but back then I was dealing with a myriad of other things. I waited to begin working for Command Prompt until I was certain that I could give it everything I had, and that was five years and one month ago. I'm so passionate about what I'm doing._

**What 's your background and expertise?**

_My background is in computer science and computer programming. It 's all I ever cared about or wanted to do, even from the earliest age. My earliest memories are of taking clocks apart and making little machines - back in primary school all I could think about was getting my hands on computer components. I was thinking about making computers before many people had even heard about them. I managed to do that when I was in high school, and I was able to get the parts to put together logic circuits - I designed and soldered them together, way back in the 70's._

_I studied computer science in university, and was fascinated by robotics, AI, and computer programming. I 've stayed in the field ever since._

**What 's your favorite project of all time?**

_The most significant project I 've ever worked on happened when I was approached by a man who had an idea for project management. He had been implementing his idea via spreadsheets. which was extremely labor intensive, and he contacted me to ask if there was a better way to do it to realize his vision. I spent 10 years - and a lot of time since - figuring it out. I came up with the database system for him, which saved him 30 hours each week and enabled him to realize his vision. When I first met him, he was working by himself in a rented office at the back of an industrial estate. 10 years later, his company was managing projects worth $100 million a year and he owned the industrial estate. _

_Eventually, I had the vision of creating web applications as fast as you could think of them, so that you could go meet the CEO of a company, talk to them for two hours, and by the time you left, they had a working web application that could do what they wanted. I wrote software that could do that._

_I had already discovered that out of all the things I was interested in, databases were the most fascinating. I guess a lot of people don 't realize it, but SQL, and PostgreSQL, would not exist without an extremely sophisticated artificial intelligence at its core: every time you formulate a query, you're basically telling the system "this is the information that I want." That request gets sent off to the database systems manager, which stores the data and understands the nature of the data. From there it works out lots and lots of different plans around how to satisfy your query, and it chooses the best one. It's just like a human being translating between one set of specifications and another, working out all the different possible ways to do it, and then intelligently figuring out the best one. _

**What 's your greatest motivator?**

_It 's a bit of a cliche, but my biggest motivator is to make the world a better place. For most of my life, I thought that the way to do that was to write software for artificial intelligence database systems, because I saw over and over the incredible impact that a good database system could have on businesses and communities. So for years, I worked on incredible pieces of software._

_But then as I got older, I started to think that the best way to help people was on a personal level. The more I helped people on a personal level, the more joy it brought me. They say that to be truly happy, you need to help people, and I believe that that 's true. _

**If you could recommend one learning resource, what would it be?**

_I 'd like to say Wikipedia because it really is one of the greatest wonders of the world, but in terms of getting down and dirty and learning how to do stuff, you can't beat Youtube. It doesn't matter what you want to learn to do, someone somewhere has done it and they've probably put it on Youtube. If you need to know something, you can probably find it on Youtube faster than any other way._

**As someone who has successfully worked from home for years, what tips do you have for those now working from home for the first time?**

_You 've got to establish a routine and stick to it - you need to be doing the same thing at the same time every day no matter what. That way, you always know what you should be doing without having to think about it. Otherwise, you risk wasting your time by dithering around._

**What 's the future of open source technology?**

_Open source technology *is* the future: Even Microsoft has started to move toward Linux. For its entire existence, Windows has been demonstrably inferior to Linux in just about every way except adoption. With Linux, your machine is constantly being updated and maintained with rarely any down time. Proprietary software can be so intrusive and counterproductive, even leaving out the technical inferiority issues, and yeah, it 's nice and polished and gives non-technical users the warm fuzzies, but if you just plain want to get work done, you can't beat Linux and PostgreSQL and open source software._

![](../../../../uploads/images/20190811.jpg)

**Where can we find you on a Saturday afternoon?**

_Either at my computer, pursuing some great idea, or being a mallrat. I love malls, and the Philippines is the mall capital of the world - it has more and bigger malls than anywhere else in the world. There are three different malls that are within ten minutes drive that would typically have 200,000 people pass through them in a single day. Think of a building the size of an aircraft hanger that has thousands of shops in it, and every mall is different - they 're like theme parks in that they all have different shops and different kinds of people in them._

**Would you rather battle one horse-sized duck or 100 duck-sized horses?**

_I 'd take one horse-sized duck because I'm the world's worst multi-tasker and I love ducks. I'd be riding it._

**What 's your desert island food?**

_Either rice or sardines because they 're my favorite foods here in Cebu. Ideally, they'd be together._

**What 's your best hidden talent?**

_I really care about what's going on in the world. I try to stay informed about issues and world events, although I would rarely express an opinion to anyone. Nevertheless, it shapes my long term goals and actions more than anything. I think it contributed to my decision to move to Cebu._

**Other than Postgres, what topic are you an expert on?**

_In the case of everything other than Postgres, I become a jack of all trades and a master of none. I 'm reasonably knowledgeable about linguistics, language, and grammar, but I'm not an expert - I don't feel like I've mastered it._

**What subject should be taught in schools but isn 't?**

_The first is the Socratic paradox - I know that I know nothing. Psychologists have actually quantified this in the Dunning-Kruger Effect, where the less someone knows about something, the more they think they know about it. It 's the essence of ignorance. It's something that most people have heard of, but it's difficult to put into practice because our brains don't work that way: We have cognitive bias. There comes a point when you're learning things that you either have to take a position or just move on, but at the same time, you need to know when to abandon a position in order to do that._

_The second is based on the quote, "perfect is the enemy of good." Voltaire made this famous. I've always been a perfectionist, so I was revolted when I first heard this, it totally went against every principle I've ever had. But the more I thought about it, the more I realized that it's true. It's the biggest lesson that I've learned recently, and far too late in life. I wish somebody had taught me that in school._

**When you were a child, what did you want to be when you grew up?**

_I wanted to be an engineer or an architect because it wasn 't until grade 12 that I knew that computer science was a profession in its own right. I absolutely wanted to work with computers, but I thought that I'd have to be some kind of engineer to do that. In grade 12, I read a book that was written in the year I was born called _A for Andromeda _, by Sir Fred Hoyle. The hero of the story was a computer scientist, and I read that and realized that computer programming was a career in it 's own right, not just something that you do as part of another career. I always knew I was going to be an engineer so that I could use or build computers, but it wasn't until I read that book that I discovered that I could do pure computer science as a career._

_![](../../../../uploads/images/img_20171008_154945.jpg)_

---
[View this page online](https://www.commandprompt.com/blog/meet_andrew/)

---

# How to add seconds to a timestamp to get an ending timestamp

> Command Prompt is one of the oldest Postgres support companies in the world and we have been blessed to be extremely busy with Professional community developme…

Command Prompt is one of the oldest Postgres support companies in the world and we have been blessed to be extremely busy with Professional community development including meetups and conferences. With the current climate we thought it would also be useful to remind people of “Simple Tips”. Simple tips will help new users of Postgres and related technologies to answer those pesky little questions that are in the back of their heads about how to do “insert idea here”.

## How to add seconds to a timestamp to get an ending timestamp?

Assume you have have 2 values:

starting timestamp

duration (seconds)

## How do you determine the ending time? 

There are a number of ways this can be done and here are two:

The first one is to use an interval as your second column.
    
    
    CREATE TABLE time_test (one TIMESTAMP, duration INTERVAL);
    INSERT INTO time_test VALUES (now(), '10 seconds');
    SELECT one, one + duration AS duration FROM time_test;
    
                one             | duration          
    
    ----------------------------+----------------------------
    
     2020-04-08 10:03:34.806522 | 2020-04-08 10:03:44.806522

The second option is to use the function make_interval():
    
    
    CREATE TABLE time_test_2(one TIMESTAMP, duration INTEGER);
    INSERT INTO time_test_2 VALUES(now(), 10);
    SELECT one, one + make_interval(secs => duration) AS duration FROM time_test_2;
    
                one             | duration          
    
    ----------------------------+----------------------------
    
     2020-04-09 13:51:53.703337 | 2020-04-09 13:52:03.703337

This is just the first of a series of simple tips that we will be delivering to make your life easier with Postgres!

---
[View this page online](https://www.commandprompt.com/blog/how-add-seconds-timestamp-get-ending-timestamp2/)

---

# Meet Eric Worden: Command Prompt's Mushroom Maven

> Welcome to our new blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Eric Worden, one …

Welcome to our new blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Eric Worden, one of Command Prompt's senior DBAs.  


 **Where are you based?**

 _Bellingham, WA. It’s a pretty cool coincidence that this is where JD and Amanda live as well._

 **How long have you been with Command Prompt?**

 _I’ve been with Command Prompt for five years and a few months, so I’m going on six years._

 **What’s your background and expertise?**

 _Well I studied zoology and biochemistry in college, and my first job was teaching middle school science. Later, in my first IT job, I got started in databases. I designed an Access database which was pretty cool. In my second IT job I was a SQL server DBA for a mental health organization, and then I got into data warehousing at my third job at a school district in the Seattle suburbs. Like it is for most people, each job was a bit of a step up as far as the specialist learning and complexity._

 _When you work for a school district, you have a lot of reports that you have to run so that you can send data to the state and federal government to prove that you’re doing what you’re supposed to be doing. It was great working with the dashboards. Managers and execs just love those dashboards with their dials and bar graphs._

 **What’s something you wish more people understood about Postgres?**

 _In the past, people didn’t understand open source and thought it was poor quality and unfit for “real work.” I think we’re finally over that hump, and people are starting to realize that things have changed. Perception is better than it used to be. People realize that open source is a great resource. Still, when I talk to new people and I tell them that I work in databases, sometimes even IT people haven’t heard of Postgres because they 're more familiar with Microsoft. In my bubble, it’s perfectly normal that open source is taking over the world, but that’s not so for everyone._

 **What’s your favorite project of all time?**

 _While it’s no longer live, my favorite project of all time was a website called the Collective Garden. It was essentially a social network for gardeners.The basic idea started a really long time ago, long before I got into IT, because I’ve always been into gardening. I noticed that year after year, different plants and flowers came up at different times and they would kind of go through a sequence through the year. When you’re a gardener, it’s helpful to know when things are going to happen so that you can know when to plan things and how long until you need to harvest your broccoli and other veggies._

 _I couldn’t find this information anywhere, but then web 2.0 came around - Facebook and things - so I started building the Collective Garden during my evenings and weekends for about three years. I didn’t really know much about programming at that point, but I decided to use MediaWiki, which led me to use Postgres. Even when I found out that Wikipedia uses MySQL, I could tell that it was no good. I was on the right track then and didn’t even know it. Actually, I guess I did know it to some degree - you can go to postgreql.org and it’s a very coherent website. You can tell that it’s really active and there’s a lot of contributors from various parts of the computer world. Lots of volunteer input and collaboration. The documentation is awesome._

 _Metaphorically, Postgres is kind of like Linux in that it’s built by the people for the people, whereas things like legacy Oracle and MySQL are built by large organizations. They’re built by someone, but I don’t know who their design is for because it 's weird and awkward and cumbersome. It’s really strange, especially these commercial products are just no fun to work with at all. When I got into Postgres I was like, wow everything’s so well designed, and I just loved using it. I could tell that the technical parts were well thought out and it felt really natural from the beginning for me._

 _Collective Garden was really fun because it brought my interest in biology training together with the social aspect. From a technical perspective, the most interesting thing was the GIS aspect of the whole project: The database had map data for climates from around the world and it would connect people based on that information because gardeners need to talk to peers in similar climates in order to collaborate. Through my system, people in Australia realized that their climate was similar to the climate in parts of Texas, and they were able to share information and insight._

 **What’s your greatest motivator?**

 _What motivates me is putting together systems that just run really well - and are designed well - they’re like little machines, like clocks. I think that any person who has learned a craft can appreciate this to some degree: You get great pleasure from creating something because there’s so much that goes into it._

 _Programming is a craft that you develop, and you get better and more sophisticated the longer you do it. It’s nice to think about things doing what they’re supposed to do - it’s a thing of beauty. I think it’s something that a lot of managers don’t understand - you have all of these motivational systems, but many programmers just want to make things work._

 **If you could recommend one learning resource, what would it be?**

 _Man pages. It may seem like a joke-ey thing to say because they’re so basic and may seem really boring, but they’re so important and I literally read these things several times a day. There are all these little programs and tools we need to use, and almost all of them have a man page. I think a lot of people take them for granted because they’re so common, but they’re actually really cool._

 **What’s the future of open source technology?**

 _Open source technology is this amorphous, organic thing that grows and grows over time, and in that sense it is always the same. Open source is a reflection of what people want at any given time because it’s a collaborative thing that’s out there that people can work on. For example, these days there’s less effort spent on desktop open source technologies like there was when I got started. People don’t care about desktops, they care about phones and there are tons of people working on phone apps. There are all these new, modern things._

 _I also know that there’s more work going into distributed systems. I hope that someday we can get away from Google and Amazon servers controlling our email and communication, and that we can move toward open source programs. But it’s a hard problem to solve, and technically easier when everything’s centralized._

 _There’s a big paradigm leap to a new world where we can use open source for everything and cut out the middle men like Facebook and Google. That’s my hope at least, but who knows when - or if - it will happen._

 **Where can we find you on a Saturday afternoon?**

 _Walking in the woods. Around here, there are a lot of woods so I don’t have to go far to get to them. It’s what people do in this area._

 **Would you rather battle one horse-sized duck or 100 duck-sized horses?**

 _Definitely one horse-sized duck, just because I’d want to see what it looks like. It would be scary, but I’d take the challenge. It would be amazing._

 **What’s your desert island food?**

 _Tempeh tacos - I just learned how to make tempeh from scratch and I eat it all the time now._

 **What’s your best hidden talent?**

 _I’m a walking science encyclopedia. Today I learned that molasses is 10% minerals by weight. Very unusual for any food. Very high in calcium, iron, magnesium, manganese, and potassium._

 **Other than Postgres, what topic are you an expert on?**

 _I’m sort of a mushroom expert - This may not be the most relatable thing to folks who aren’t from the Washington area, but it’s so lush and they grow like crazy out here. There’s a big mushroom club out here and we have this big show every year in a big hall and it has a scientific orientation._

 _If you haven’t been to the show, you may not understand the concept. There are so many mushrooms in so many different sizes, shapes, colors, and smells, and when people go there for the first time their eyes bug out and their minds are blown because of these big mushroom displays. You have to see it to believe it._

 **Early bird or night owl?**

 _Night owl. Easy one._

 **What subject should be taught in schools but isn’t?**

 _The best things in life are so hard to teach, unfortunately. If they were so easy to learn, they’d already be taught in schools. Mushrooms could be taught so maybe they should make that a standard course? Within school as it exists, there’s nothing more they can do - it’s been pushed to its meager limits._

 **When you were a child, what did you want to be when you grew up?**

 _I wanted to be a biologist - I lived in the boondocks and was totally into nature, even as a kid. Carp muddy up the rivers and kill the good fish so I wanted to clean them out. I wanted to save my little part of the world that I knew about, and saving my river from those carp was my way of doing that._

---
[View this page online](https://www.commandprompt.com/blog/meet-eric/)

---

# How to Achieve Success When Working From Home

> In today’s world it is important to know that you have a team to back you up. From all of us at Command Prompt, we are here to help. It is our goal to help our…

In today's world it is important to know that you have a team to back you up. From all of us at Command Prompt, we are here to help. It is our goal to help our clients, partners, and community succeed. 

As a pioneer in building a successful employment from home culture we have moved through the trial and test phases of what does and doesn't work when working without a central office. In an effort to help you transition with ease, we have put together a list of important things to take into consideration. 

###  

### How to achieve success when working from home: 

#### **Set a routine and stick to it.  **

  * Your work schedule shouldn't change much. Though you theoretically have flexibility, it needs to be constrained. Your total hours working shouldn't change.
    * Keep to a meal schedule.
    * Spend the time you would normally spend commuting with your family or doing something you enjoy in order to offset the time you are at home but in the office unavailable. 
  * When work is done, work is done. 
  * This includes a routine for your family/SO. 



#### **Include self care within your daily routine.**

  * Exercise is key to productivity. Don't sit all day. Make sure to keep moving, whether it's a walk (if you can), yoga, squats, etc.



#### **Have appropriate boundaries.**

  * Limit distractions.
  * Communicate clearly with your household members that from X time to X time, you are working and should not be interrupted. 
    * In the interest of family overall health it is important to be flexible and also be consistent in your expectations as you work from home. 



#### **Try to achieve as close to your normal productive work environment as possible.**

  * If you normally have face to face meetings, use technology to your advantage and continue to have them through software such as Zoom.



#### **Be task oriented.**

  * Working from home is, generally speaking, now about completing tasks efficiently and not just being in an office for 8 hours.
  * You should have actionable items, as well as an action item list for each task to help avoid getting overwhelmed. 
  * Set a to-do list of what you will accomplish with deadlines. 



#### **Take appropriate breaks.**

  * Leave the computer/house (if possible) for at least thirty minutes in the middle of the day. 
  * Don't be afraid to take walks while on the phone (a hands free device is useful here).
  * Find someone to talk to that isn't in your household (if possible).



#### **Ignore your phone unless it is for work purposes.  **

  * Don't use your phone for personal reasons unless it is during scheduled breaks. 



 

### Need help finding the right mindset? 

#### **Dress for the part.  **

  * Wear what you would wear to the office. If you wear a suit to the office, wear a suit to your home office.



#### **Have a dedicated space.**

  * Whether it's a home office or a space at the dinner table, that space needs to be dedicated to you getting your work done. 
  * Do your best to make this comfortable. 
  * If sharing with a spouse or roommate, make sure you communicate your schedules before the work day starts and do your best to not interrupt each other.



#### **Use a method of marking off your todo items.**

  * Could be a notepad, spreadsheet, app, etc. Show yourself you are making progress.



#### **Turn off the TV, the phone, and the news.  **

  * Knowing what is going on at all times will restrict you from being able to successfully get work done.



 

### Other helpful tips: 

#### **Maintain healthy habits.**

  * Meals, exercise, and sleep are essential for productivity, especially when stress is high and there is a lot of uncertainty. Make sure you are taking care of yourself. 
  * Go to bed at a normal time.  



#### **Work with your team.  **

  * Whether by way of project check ins, delegation, or a quick "water cooler" chat, keep in contact with those you normally work with. 
  * Communicate your tasks, plans, and roadblocks to your coworkers and managers frequently. 
  * Relying on your team is a great way to get work done in a successful way and keep you focused on your task at hand. 



#### **When frustrated or trying to focus, remember that you have a job while many others are facing layoffs and furloughs.**

  * Take a mental health break if you need one. Even 15 minutes playing with your pet or pulling weeds in the yard will declutter your brain.

---
[View this page online](https://www.commandprompt.com/blog/how_to_achieve_success_when_working_from_home/)

---

# Coronavirus (COVID-19) Update - Letter From Our Founder

> As the global spread of COVID-19 (SARS-CoV-2) hits home, disrupting lives and communities, our Command Prompt team has been working diligently to ensure that o…

As the global spread of COVID-19 (SARS-CoV-2) hits home, disrupting lives and communities, our Command Prompt team has been working diligently to ensure that our clients receive the quality and excellence in experience we've promised them. As Command Prompt is a strategically globally distributed company, our staff continue to do their best work – all in a safe, remote, and productive environment.

Please be aware that we are committed to supporting your company and team needs during this time of uncertainty. We have and will continue to deliver high-quality and reliable professional Postgres support and service as we’ve done for over two decades.

Our technical support, education, and project management teams are standing by to help you in this time of crises. Online resources are available to teams around the world whether it be our remote DBA support or on-demand educational webinars. We will also share our best tips via our blog and social media from our team on how to stay productive while working remotely.

On behalf of the Command Prompt team, we’re here for you. We hope the best for you, your family, your colleagues, your community, and your success in business.

Take care,

Joshua D. Drake (JD)  
Founder

---
[View this page online](https://www.commandprompt.com/blog/covid19_update_03242020/)

---

# Meet Eugene Dubinin: Command Prompt's Postgres Sailor

> Welcome to our new blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Eugene Dubinin, o…

Welcome to our new blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. This month we are talking with Eugene Dubinin, one of Command Prompt's senior Developers. 

![](../../../../uploads/images/photo_2020-02-04_11-44-47.jpg)

**Longform Questions:**

**How long have you been with Command Prompt?**

_I 've been working with Command Prompt since May 2016, so almost four years now_

**What 's your background and expertise?**

_Computer science started as a hobby around 8th grade. My first job in technology was when I was in school: I started out as a part time systems administrator for the university.  _

_I did a lot of IT-related work after college, and I have a background as a systems administrator for a regional ISP so I have a pretty strong background in Linux/network administration. After that I switched over to mostly doing coding and development, which is what I 'm doing at the moment._

**What 's something you wish more people understood about Postgres?**

_While I 'm not a Postgres expert, I am using it daily and it's the go to database for most of my projects. For many people working on smaller projects, like simple web applications, Postgres isn't necessarily a go-to database. Most people choose MySQL, which is fine, but I've always wondered why not Postgres._

_People use MySQL more than Postgres because it 's a trend. Maybe some people see it as simpler to start with, so they believe that it has a simpler learning curve. I don't think that Postgres is a complex thing to learn, but maybe MySQL just looks easier to get started on because it can be managed through a console and a set of user-friendly UI tools and you don't have to mess around with configuration files to just start your work. I mean - MySQL also has configuration files, but it's usually not necessary to change them to set up a local development database instance._

_Another thing, which is less applicable since the release of the new PG Admin interface, is that MySQL used to have a better graphical interface than Postgres. Today, it 's a common misconception that Postgres doesn't have a solid graphical interface: People don't realize that it's user friendly._

**What 's your favorite project of all time?**

_I have quite a few projects that I really enjoyed. I was lead architect on a project that aimed to improve HR-related legacy applications for a big Asian telecom company with more than 1,500 employees. Our job was to rewrite these legacy apps from scratch, and then merge them into a single application which could take care of tasks. This was a Rails-based application and it used Postgres. They had a pretty significant Postgres installation on site, and the legacy applications used Postgres as well, so they migrated data to a new schema._

_This was one of my favorites because we created it from scratch and had, in my opinion, a good and modern architecture. A lot of applications are legacy in corporate environments - they 're really old and poorly maintained and documented. I like to make things better than I found them, and this was a great opportunity to do this for big systems within a large organization. _

_There were a lot of things to improve, and I was pleased with the result because the new application was quite a lot faster than the legacy applications: It had a nice, easy to understand interface. Because it was a resource for Human Resources, and not really geared toward tech employees, it needed to be easy to understand and add no surprises in the business process. It needed to be fast, responsive, and have a nice UI and work on different screen sizes, and it did._

**What 's your greatest motivator?**

_Like I said, I like to improve things, so that 's probably my biggest motivator. Equally important, I enjoy it when people see improvements and appreciate your work. Creating something really useful is a great feeling._

**If you could recommend one learning resource, what would it be?**

_If the audience is a beginner administrator or developer, then documentation is actually pretty good - It 's well written. Documentation has all the technical details, but it may be a bit boring. But hey, technical instructions aren't exciting. When I have Postgres questions, I go to the Postgres website, and their documentation is my go-to site for general knowledge._

_Secondly, I 'd recommend Command Prompt's blog. It's not go-to documentation in any way, but you can always learn something interesting and new there. Our blog has some really interesting technical stuff that a Postgres user or Junior DBA could really benefit from. We have a lot of people in the company who know a lot about Postgres. Spend some time there. Other companies have great blog posts as well, and _[_Postgres Conference_](<https://postgresconf.org/>) _is a pretty interesting source of knowledge and Postgres-related news._

**What 's the future of open source technology?**

_I believe that open source as a paradigm will be the main thing in the future, because even massive companies like Microsoft are buying up companies like Github. They 're a main stakeholder and they're submitting to the open source community. They have an IDE (Integrated Development Environment), which I'm using daily as visual studio code, which is also hosted on Github. Even big corporations are moving in this direction. I don't think I need to mention giants like Google and Amazon because they are building their infrastructure on top of Linux, Postgres, etc. This will be the biggest thing in the future._

  
![](../../../../uploads/images/photo_2020-02-20_12-49-08.jpg)

**Short Form Questions**

**Where can we find you on a Saturday afternoon?**

_On a Saturday afternoon I may be in the gym - I try to go three times each week. It depends on the weather. Sometimes I 'll ride my bike instead, but for now in the winter I'm going to the gym. After the gym, I'm doing renovations on my home: I bought a new apartment and there's still a lot to do on it. Now I'm a painter and an electrician at home!_

**Would you rather battle one horse-sized duck or 100 duck-sized horses?**

_I guess one horse-sized duck because it 's just one thing and it's easier to manage. 100 is too many little horses - how can I concentrate on all of them at once? People are better when they aren't multi-tasking._

**Desert island food?**

_This is a tough one. I guess I 'd say pizza because you can do a lot of variants on the same theme, but I may be cheating here._

**What 's your best hidden talent?**

_I 'm a perfectionist. I really like to polish things up, and I like when things are in order and when you don't have to improve on them anymore. It makes me so happy when things just work and you're pleased with the results._

**Other than Postgres, what topic are you an expert on?**

_From a technical perspective, I 'm an expert on Ruby on Rails development. From a non-technical perspective, I'm an expert mountain biker._

**Early bird or night owl?**

_Night owl. It got even more severe when I started working remotely from home - it erases the boundary between work and the things you do at home._

**What subject should be taught in schools but isn 't?**

_The answer to this question depends on where you are - different countries teach different things. In Ukraine, I think it would be helpful if classes on the economy and money management were taught. It 's really important. _

_I see that so many adults who just don 't know where their taxes go - they still think that "free" education or "free" medical services are really free, which they aren't. I believe that the next generations should learn where these services come from and how they're financed - where they're taxes are going and why they pay taxes; how to spend their own money efficiently and how to plan their resources. _

_I studied economics in school, but it was boring stuff about the global economy that didn 't apply to me. Nothing was applicable to daily life, when what I actually needed was usable knowledge. _

**When you were a child, what did you want to be when you grew up?**

_I don 't think I understood the question when my parents first asked me, so I told them that I wanted to be a sailor. It was some random default answer, and the funny thing is that I still can't swim. I don't know why I said that._

_![](../../../../uploads/images/img_0125.jpg)_

---
[View this page online](https://www.commandprompt.com/blog/meet_eugene/)

---

# Meet Ivan Lezhnjov: Command Prompt's Open Source Detective

> Welcome to our new blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. First up is Ivan Lezhnjov, Lead Systems Administ…

Welcome to our new blog series: Meet the Team, where we will introduce you to the minds behind Command Prompt. First up is Ivan Lezhnjov, Lead Systems Administrator.

![](../../../../uploads/images/54447161_2021982597911393_1159150079966400980_n_\(2\).jpg)

**Longform Questions**

**How long have you been with Command Prompt?**

_Since the fall of 2012, so around 7+ years._

**What 's your background and expertise?**

_I 'm a Lead Systems Administrator / DevOps Administrator. I'm self-taught and have been fascinated with Linux and the free software movement since the early days. When I was in highschool, and throughout university, I was really fascinated with Linux as a hobbyist. Somehow that transformed into a career. _

**What 's your favorite project of all time?**

_It 's so difficult, because there's so many great open source projects and it's really difficult to pick one. I really like GnuCash and GIMP, the photoshop of Linux. _

_I obviously love the PostgreSQL database, because it 's _**_the_** _database these days. So many contemporary startups use PostgreSQL. What else? I think Mozilla Firefox is a great web browser and a great open source project / free software community. A lot of software is really great, so it 's hard to choose._

_Oh! The greatest project of all, which is the elephant in the room, is the Linux operating system itself because it 's ubiquitous and the basis of everything. It's technologically advanced, but it's also free. The thing is that free and open source software basically opens the door to anyone to enter this field, and as it was in my case, you can enter as a hobbyist but also level up to a real life career. I think that's awesome. Not many things allow you to do that - for so many things, you have to get formal education, etc., and the free nature of this open source world basically means that if you desire to learn on your own, as I did, then you can become a professional at something that really matters. I find that fascinating, really, because you don't have to depend on anyone else and you don't have to pay a single penny to a single learning institution. You just have to pay your internet bills, which is amazing when you think about it._

**What 's your greatest motivator?**

_My greatest motivator is the desire to master whatever I 'm doing. My other greatest motivator is creating things that give value to others._

**If you could recommend one learning resource, what would it be?**

_I would recommend getting a mentor as one of the best things that you can do to further your education. No one can teach you anything unless you put the effort in, but it 's helpful to have guidance along the way. _

_I 'd also recommend reading books on the subject of interest, which are so overlooked these days because there's so much instantly available information on the web and a lot of us end up relying on blogs more than we should. Unfortunately the quality of blog content isn't always up to the same standard as published books. Generally speaking, I think that people would really benefit from reading more technical, fiction, and non-fiction books._

_One last resource that I 'd recommend is Youtube. The key is to approach it as an educational resource, not as entertainment. There's a lot of educational content out there and video is a powerful form of expression because you can see and hear the information, which often results in faster processing and comprehension. In a way, Youtube has become a substitution for reading for me. It may not be a replacement for books, but there is merit in Youtube so long as you exercise discipline and don't get sucked into funny cat videos._

**What 's the future of open source technology?**

_Open source technology is on the rise and I think it 's going to be a lot more widespread and popular. That's the current trend and I believe that it will continue. _

_When I was starting out, if you used Linux then you were some sort of revolutionary. You didn't have to do anything else: you stayed at home, you ran Linux, and you were radically different from a lot of people at the time. Back then the Macintosh - who calls it that anymore? - was not even as popular as Windows was where I lived and obviously Linux was even less popular.  _

_In the early 2000s I saw a great documentary called Revolution OS, which was all about the history of Linux, the genesis of the Open Source movement, and the people getting on board with the free software movement. That documentary actually had footage of people protesting at Microsoft headquarters, you know, holding up posters with the Windows logo with a slash over it, and it was sort of like a revolution that very few were aware of._

_What I 'm trying to say is that what I saw back then is a lot different than what I see today. Open source was a sort of geeky, niche thing that only a few technically-inclined people did, and now it's not uncommon to see people who are not as familiar with Linux as those geeky enthusiasts protesting at Microsoft headquarters were, running Ubuntu on their laptops. It's a huge improvement of what I observed at the beginning of the 2000s. A lot more people are familiar with Linux these days. It was really different back then. What I see today is that where Microsoft used to try to destroy Linux, they now understand that they can't do that - so they joined forces. Today, they have all sorts of open source projects._

_The takeaway here is that companies like Microsoft have started to do things today that they would have never even considered back in 2000. It 's telling when such a monstrously big corporation is basically caving into the geeky penguin who has taken over the world. What other evidence do we need to see that open source is on the rise? _

 ![](../../../../uploads/images/64903325_129153251627906_1532420806231290975_n_\(1\).jpg)

**Rapid Fire Questions**

**Where can we find you on a Saturday afternoon?**

_If it 's summer you can find me riding my motorcycle, and if it's winter, I'm probably sitting at home playing Playstation. _

**Would you rather battle one horse-sized duck or 100 duck-sized horses?**

_Life hasn 't prepared me for such an encounter. But a horse-sized duck? Is it yellow? Can it float? Fortunately we'll never have to find out._

**Desert island food?**

_I 'll be practical: Water and dark chocolate with whole hazelnuts, but only if there are whole hazelnuts. It's just tasty. _

**What 's your best hidden talent?**

_My hidden talent is that I speak fluent sarcasm._

**Other than Postgres, what topic are you an expert on?**

_Giving advice, but isn 't everyone an expert on that?_

**Early bird or night owl?**

_I 'm definitely an early bird. Going to bed early and getting up early works best for me._

**What subject should be taught in schools but isn 't?**

_A lot of things should be taught in schools but aren 't. Relationship science would be really helpful - not just romantic relationships, but friendships as well. It's so important because so many people don't get it and so they go through a lot of emotional pain, and waste so much energy on something that is otherwise supposed to be fun. Relationships are such an important ingredient to a high quality life, and I believe that when you have great relationships, your life is profoundly affected. If we could help future generations to be better at this then we'd see increased productivity and generally happier nations. A lot of good stuff would come out of it._

**When you were a child, what did you want to be when you grew up?**

_I wanted to be quite a few things actually. I was really interested in becoming a detective. I wanted to figure out things and solve crimes and that sort of thing, and ironically my current job gives me something like that because I have to figure out a lot of problems and play the tech detectives. For instance, a lot of things aren 't obvious and you have to guess because open source, as great as it is, has one big problem: poor documentation. You often don't understand how something works so you have to play detective. _

_What else? It 's silly because I was really little, but for a period of time my dad was fixing CRT TVs for people, so I wanted to do that because that's what my dad was doing. _ _  
_ _When I was growing up, to some degree, I wanted to become an IT professional. And like I said, my career progression was just so natural that I didn 't really have to think twice about it. _

_![](../../../../uploads/images/65484180_123988338832883_6524405730204774138_n_\(1\).jpg)_

---
[View this page online](https://www.commandprompt.com/blog/meet_ivan/)

---

# Recognizing and Developing Emotional Intelligence

> There are many ways to define intelligence, and the most commonly accepted definition being in relation to facts, figures, and reasoning. This leaves out the e…

There are many ways to define intelligence, and the most commonly accepted definition being in relation to facts, figures, and reasoning. This leaves out the emotional, interpersonal, or social aspects of intelligence, known as the Emotional Intelligence Quotient, or EQ. According to Merriam-Webster, intelligence is defined as:

  1. the ability to learn or understand or to deal with new or trying situations : [REASON](<https://www.merriam-webster.com/dictionary/reason>) _also_ : the skilled use of reason
  2. the ability to apply knowledge to manipulate one's environment or to think abstractly as measured by objective criteria (such as tests)



Per Google, _Emotional Intelligence is the capacity to be aware of, control, and express one’s emotions, and to handle interpersonal relationships judiciously and empathetically_. EQ is ruled by the portion of the brain that process emotion.

EQ is hard to measure, leading some to treat it as a lesser skillset, and classifying it as a _soft skill_. This is a titanic mistake, however, as EQ plays an equally important role as IQ in the workplace. Like so many other intangibles that contribute to success, EQ is instantly recognizable in others. 

Recognizing EQ

Highly developed EQ is reflected not just in how we interact with others, but how we manage ourselves. Per the Consortium for Research on EQ, it can be broken down into five skill sets:

  * Personal
    * Self-awareness - EQ actually starts from within, and recognizing one’s emotions and their effects, and being able to accurately self-assess in the moment are paramount to a high EQ.
    * Self-regulation - This one can be summed up by exercising self control, being consistent, and maintaining flexibility. People with great EQ are trustworthy, adaptable to changing situations, and have well developed impulse control. 
    * Self-motivation - People with high EQ strive for excellence, take initiative to achieve personal and group goals, and operate with a certain level of optimism that they can _and will_ achieve their goals. 
  * Social
    * Social awareness - This is probably the most well-known aspect of EQ, and it can be distilled into having empathy for those around you. Empathy can be developed by taking an active interest in the feelings and opinions of others, and then acting in their best interest.
    * Social skills - This is unsurprisingly the broadest aspect of EQ.Social skills range from leadership and communication to conflict management and building relationships. Social skills are the most outward facing faset of EQ.



EQ affects every aspect of our lives, and it’s important to note that while some may be predisposed to have a naturally higher EQ, these skills can be learned, honed, and improved upon by anyone. It is in all of our best interest to work toward a high EQ as it’s a key predictor of success: According to a [study by Johnson and Johnson](<http://www.eiconsortium.org/reports/jj_ei_study.html>), the highest performers in the workplace were those who possess and display a higher EQ.

Developing EQ

It’s certainly true that practice makes perfect, or at least better, but how do you practice? I would argue that it comes down to three main actions:

 **Check in with yourself** \- What is happening around you, how does it make you feel, and how are you reacting? Is your reaction appropriate to the situation at hand, and if not, what feeling is driving your response? Knowing what’s going on internally and how it makes you feel is step one in developing EQ. Taking stock of your internal status is a wonderful practice, whether you are upset or elated. So many people only check in with themselves once they’re in a negative place, but why would you want to let it get that far? You shouldn’t. Checking in with yourself on the way could change outcomes. On the flip side, considering positive situations are a wonderful tool for developing EQ as well. Pinpointing which parts of the process lifted you up can contribute to you lifting up others in the future.

 **Successful communication** \- Once you are able to measure where you are internally, you need to practice communicating that to others in actionable and approachable ways. We’ve all been there: A project isn’t going well, the feedback loop is broken, and you’re ready to lose it. Before you get to this point, consider how many opportunities there were to hit pause, communicate, and change course. If no opportunities present themselves, then create them. As a member of a team, it is not only your right, but your responsibility, to contribute to the success of the group, and a group can’t succeed if they don’t know what you need. And your team can’t know what you need if you don’t tell them.

 **Practice empathy** \- Put yourself in someone else’s shoes - what’s going on in their lives and what experiences have they had that are influencing their current stance? Making a decision from a place of empathy isn’t always natural, but it is always your best bet. This means understanding and sharing the feelings of another, and then using that as the basis for next steps. Opinions and feelings always have an origin, and frankly, if they seem to spring from nowhere, it’s because you haven’t found the source of the trigger. Practicing empathy is the most effective way to create pathways.

Reflecting on and developing your EQ is important

It is vital in today’s world of constant input, distributed teams, and trigger/cancel culture that your EQ becomes a skill and talent that you can rely on. We are all challenged to define our values, our professionalism, and our ability to work together to move forward in life. If you take the time to sharpen your EQ, you are going to find yourself rising above in your career and relationships.

---
[View this page online](https://www.commandprompt.com/blog/Recognizing-and-Developing-Emotional-Intelligence/)

---

# Keys to moving forward in your life and career - making the leap to uncomfortable

> Finding the right path when trying to move forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when y…

_Finding the right path when trying to move forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when you are ready to move up in a role, to refining the skill set you have; there are many stepping stones that have to be put in place in order to successfully move forward in your career. In this article series I provide tips as Senior Management for what I look for and what has been expected of me over the years to help you reach your professional and personal goals._

\---

 **Making the Leap to Uncomfortable**

In the last article I discussed the importance of [getting out of your own way](<https://www.commandprompt.com/blog/keys_to_moving_forward_get_out_of_your_own_way/>) and becoming uncomfortable in order to succeed. “Easier said than done,” is the response I would have given before I had taken the leap. Where do you even begin? It can be a long process of questioning whether or not you can truly make that leap, doubting yourself and your abilities along the way. 

We get in our way so much that we get stuck in the “how do I get there” phase and do not move passed it, therefore never discovering the excitement and passion we have for experiencing <insert next step for you>. Or maybe the passion is there but the mindset isn’t right, the risk is too great, or it’s too hard. Luckily, if you are wondering how to get started in the right direction, the first steps are straightforward.

That said, it is important to know when going into it that sometimes the most straightforward tasks are the hardest _and_ the most important. Change is hard; making yourself uncomfortable even harder. Go into change with your eyes wide open knowing you will face challenges, but that you **can** conquer them. You are the biggest showstopper for your success. 

### Identify your boundaries

Your boundaries define your decisions, your experiences, and your life. They are what tells you not to jump off that cliff, or not to ask for that raise. It is easier to create boundaries than to deal with hurt, disappointment, grief, conflict, etc., and often that leads to more boundaries than necessary.

It is important to recognize that your boundaries may not be real. We all have them. We implement boundaries based not only on our experiences, but others’ experiences and recommendations, and what the media and television tells us about <topic>. We don’t legitimately dislike mushrooms - we just think we do because that’s how mom raised us. We don’t really want to be in debt with the giant house in suburbia, that’s just where the American Dream says we’ll find happiness so we create walls against any unconventional idea that does not fit. 

We hold true to the type of person we think we are and define what we do and what boundaries we set based on that. What would happen if we let go of the requirement to always define ourselves in the way we’re most comfortable and started to think out of our self defined box?

Identifying your boundaries, whether firm or flexible, is key to moving forward. Often you can only discover where your true boundaries lie by starting to push on those boundaries, which leads us to the next step.

### Push and/or eliminate your boundaries

Whether one step at a time or all at once, start pushing your boundaries. Have sound judgement - do not start off skydiving if you are afraid of heights (that works for some people, but not most). Instead, push yourself to try new things that make you feel and experience something that you were not willing to entertain before. Don’t break the boundary itself until you’ve spent some time identifying why you implemented it. 

Throughout this process you will find that some things are not your cup of tea but the process of pushing back was not as brutal as expected. You may also find new boundaries you didn’t know you had, and current boundaries that are a “hell no we won’t go” kind of permanent double sided tape. The key is to know where you stand. 

If your mind starts to get in your way, try Nike’s motto of Just Do It. 

### Repeat

These two straightforward steps may happen over and over, together and apart, as you work through this process. The important part is to keep moving, stay focused, and fine tune your self awareness. By doing so, it will open your eyes to where you truly stand and help you see the limits you are placing on yourself and your career. Then you can get out of your own way and start making steps toward living your best life.

\---

Want to have a conversation? I’d love to hear your story. Connect with [me on LinkedIn](<https://www.linkedin.com/in/postgreswarrior/>).

\---

Biography

 _Amanda Nystrom has been in the Open Source industry since 2009. Today she is a major stockholder and Senior Operations and Project Manager at Command Prompt, Inc.. Also a Co-Chair of the international Postgres Conference series, she is developing content and managing conferences for the nonprofit world with a focus on People, Postgres, Data. Amanda has a passion for providing tools and motivation for people in order to help them succeed professionally and personally._

---
[View this page online](https://www.commandprompt.com/blog/making-the-leap-to-uncomfortable/)

---

# Keys to Moving Forward In Your Life and Career - Get Out of Your Own Way

> Finding the right path when trying to move forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when y…

_Finding the right path when trying to move forward with your career can be challenging. From the difficult subject of compensation increases, to knowing when you are ready to move up in a role, to refining the skill set you have, to truly understanding what your boss expects of you; there are many stepping stones that have to be put in place and in the right sequence in order to successfully move forward in your career. In this article series I provide tips as Senior Management for what I look for and what has been expected of me over the years to help you reach your professional and personal goals._

**Get out of your own way**

There are many reasons for not achieving success in a career and more often than not we get in our own way. We end up frustrated because we’re not moving forward for <insert> reason. That reason impacts our ability to take the steps to set ourselves apart in a positive way. We end up afraid, we stop taking chances, we stop asking “what if.” We are ashamed, we let envy stop our progress, and we get angry. We get attached to people, habits, hobbies, and things that keep us from growth. We have become fantastic procrastinators and skilled in self pity. 

We get comfortable. Being comfortable is the number one way to impede moving forward in life. When we are comfortable, we limit ourselves, our growth, and our opportunities. We are allowing the place where we are at to be good enough but deep down we want more. I’ve struggled with this while envying others’ success and being “protected” by the bubble of comfort I created for myself. I dug into why I was not content or satisfied and found that I was hiding from my aspirations. I was afraid to put myself out there and to help people achieve their goals because of fear; fear of rejection, fear of not having anything worthwhile to say, fear of it not benefiting my career. It was easier to stay in my bubble and build my procrastination toolset. Then I realized I was _creating_ reasons to not step up. I was getting in my own way by creating fearful “what ifs” that hadn’t happened. Today I write this confidently and uncomfortably in order to get out of my way and help you do so as well.

Aspirations and goals take work to achieve, and you may face scrutiny and backlash. You will undoubtedly be uncomfortable and have to overcome obstacles you didn’t plan for. Focusing on the things we cannot control is an easy way to push your goals off, but it will not lead you down the path of success. Life has and will throw everything it can at you; it’s up to you whether or not you become another stone.

How to get out of your own way: 

  * Stop telling yourself where you’re at is good enough. 
  * Stop saying you cannot do it, whatever **it** is. 
  * Be proud of the steps you have made and how far you have come. 
  * Don’t compare yourselves to others.
  * Follow through. 
  * Have confidence, not arrogance. 
  * Take chances and embrace risk. 
  * Take advantage of your resources. They are at your fingertips.
  * Realize that perfection does not exist.
  * Actively and consistently work on your goals.
  * Experience and demonstrate gratitude.
  * Remember that success is on the other side of fear. 



This isn’t to say that you shouldn’t be content with where you are in your life. Be proud of where you are at, even if it isn’t the goal. The hardships and mistakes are what enable us to grow. Take humble confidence in where you are at and don’t let yourself stop you.

Want to have a conversation? I’d love to hear your story. Connect with [me on LinkedIn](<https://www.linkedin.com/in/postgreswarrior/>).

Resources

[Get Out of Your Own Way: Overcoming Self Defeating Behavior](<https://www.amazon.com/Get-Out-Your-Own-Self-Defeating/dp/0399519904/ref=asc_df_0399519904/?tag=hyprod-20&linkCode=df0&hvadid=312049124368&hvpos=1o1&hvnetw=g&hvrand=9607432673050706817&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=&hvtargid=pla-536600035619&psc=1&tag=&ref=&adgrpid=61851652213&hvpone=&hvptwo=&hvadid=312049124368&hvpos=1o1&hvnetw=g&hvrand=9607432673050706817&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=&hvtargid=pla-536600035619>)

[Why Feeling Uncomfortable is the Key to Success](<https://www.forbes.com/sites/sujanpatel/2016/03/09/why-feeling-uncomfortable-is-the-key-to-success/#2ca40d451913>)

[U2 - Get Out of Your Own Way](<https://www.youtube.com/watch?v=_zu53yAoTJE>)

\---

Biography  
 _Amanda Nystrom has been in the Open Source industry since 2009, starting her career as an intern for Command Prompt, Inc. From there she moved to the social media marketing industry, specifically focused on the power of advocacy and influencers in the 21st century. She took the skills she acquired back into the Open Source industry and joined Command Prompt full time as a project manager. Today she is a major stockholder and Senior Operations and Project Manager, moving steadily toward the COO position. Also a Co-Chair of the international Postgres Conference series, she is developing content and managing conferences for the nonprofit world with a focus on People, Postgres, Data. Amanda has a passion for providing tools and motivation for people in order to help them succeed professionally and personally._

---
[View this page online](https://www.commandprompt.com/blog/keys_to_moving_forward_get_out_of_your_own_way/)

---

# Hacking on PostgreSQL snap at Snapcraft Summit 2018

> As you may know, Command Prompt, Inc. develops and maintains PostgreSQL snap packages as a service to community. If you used it, you also know that unfortunate…

As you may know, Command Prompt, Inc. develops and maintains PostgreSQL snap packages as a service to community. If you used it, you also know that unfortunately it is not yet a drop-in replacement for DEB builds distributed via PGDG APT repository.

PostgreSQL is one of the major open source projects out there that is extremely popular with all sorts of crowds: from enthusiasts to unicorn startups. And as the [Snapcraft](<https://snapcraft.io/> "Snapcraft") ecosystem matures more and more, a fully-functional PostgreSQL snap package becomes absolutely necessary for reasons ranging from developers being able to easily run PostgreSQL in strictly isolated test environments, to providing more complex software solutions that build on PostgreSQL (e.g. Travis CI people expressly stated they were very much interested in getting their hands on it) to Canonical running their infrastructure on PostgreSQL packaged as a snap.

[Canonical](<https://www.canonical.com/> "Canonical"), the company behind [Ubuntu](<https://www.ubuntu.com> "Ubuntu") and the snap packages, invited us to Snapcraft Summit, a 3-day hackathon that took place in central London, United Kingdom in the beginning of November. It is a forward-thinking software workshop attended by major software vendors and Snapcraft engineers working at every level of the stack.![](../../../../_versions/img_5394_medium.jpg)

![](../../../../uploads/images/img_5394.jpg)

![](../../../../uploads/images/img_5389-cropped.jpg)

The lineup was excitingly diverse. Among the projects that I can remember there were representatives of KDE, Transmission, Ruby, Travis CI, keepalived, Postman, Volumio as well as Microsoft, IBM and others.

The goal was to get all together in one big room, sit down with Snapcraft and snapd engineers and hack together on snap packages.

In our case, the PostgreSQL snap package.

We kicked off day 1 with basics of how snap packages work and how to create them, as some of the attendees had no prior experience of working with Snapcraft and snap packages. Our case, in some ways similar to keepalived, was all about adding new features as well as general polish.

![](../../../../uploads/images/img_5383.jpg)

I worked primarily with Evan Dandrea, an Engineering Manager at Canonical, responsible for the Snapcraft ecosystem. After the initial orientation, we discussed and laid out a plan of changes:

  * move to tracks and use a single snap package to distribute all major and bugfix versions of PostgreSQL
  * confirm parallel installation is possible, which would allow to run multiple instances of PostgreSQL, including exact same version of PostgreSQL.
  * set up global aliases that would allow to call binaries in a familiar way (e.g. psql vs postgresql.psql)
  * turn PostgreSQL snap package into a proper daemon (specifically, systemd service)
  * and see if we can do away with wrappers, that we had to use to get PostgreSQL working correctly as a snap.



In fact, since the PostgreSQL snap package already exists and works, certain limitations and oddities notwithstanding, we spent quite a bit of time just wrapping our heads around where we are at now, where we want to go with all this and how to get there.

![](../../../../uploads/images/img_5423-cropped.jpg)

At some points we had various Snapcraft engineers and CTO of the Snapcraft team, Gustavo Niemeyer, join the discussion. We discussed in detail how people use PostgreSQL, what their expectations are of what they can do with it as a snap package and many other things. Eventually, we came out with an understanding of both the needs of PostgreSQL and people who use it as well as problems that Snapcraft aims to resolve in software packaging world. One of the biggest issues which is, lots and lots of outdated software that creates unnecessary security problems at a very large scale. Canonical's hope apparently is to get it under control in a way that helps less proficient users maintain higher levels of security of their systems while allowing more experienced ones to decide how exactly they want to manage their software (e.g. whether to update automatically a PostgreSQL snap package installed in the system).

The results of the 3-day hackathon are a mixed bag of success and realization that snapd and snapcraft need to improve in certain areas to support typical use cases of PostgreSQL and traditional RDMS in general.

Unfortunately, even working shoulder-to-shoulder with core snapd developers we were not able to find a quick fix that would allow us to run PostgreSQL as a daemon. Similarly, getting rid of wrappers that are currently necessary to make a locale available in the strictly confined snap environment is not an easy feat either. On the bright side, Snapcraft team had a chance to consider these issues and promised to resolve them in the near future.

That said, we successfully moved to tracks which allows us to have a single snap package that can be used to install any major or bugfix version of PostgreSQL. We also tested and confirmed that parallel installations work with PostgreSQL. This particular feature requires latest version of snapd (> 2.36) and allows one to run multiple instances of PostgreSQL on the same system, including multiple instances of the exact same version of PostgreSQL. Aliases, another useful feature, are also available now. Combined with tracks and single package design, this makes sure that psql, pg_dump and other common utilities can not only be called in a familiar way (i.e. no need for snap package name prefix, like postgresql.pg_dump) but also ensures that psql, pg_dump and other aliases always point to the most recent version of these tools.

Throughout the event, from welcome drinks in a local pub in Southwark to the farewell dinner and beers (and a cup of tea in my case), I couldn't help but think all the time how welcoming and friendly everyone was. The Snapcraft team felt just as if I had been part of it for many years. All great people. Incredibly passionate about what they do. Hilarious jokes bursting here and there all the time. Good laughs. Good food. Good times.

![](../../../../uploads/images/img_5431.jpg)

Most excitingly, you sit in a room with the very same people who created the technology that you use to package PostgreSQL and you have this privilege of asking them directly any questions you might have. You can pull in anyone to help you figure out this or that problem. It was an incredibly empowering feeling and experience. But the truth is, at the end of this 3-day massively multivendor offline collaboration we went back to our homes having made plans to continue working together on snap packages.

In fact, the very next week after the summit I joined what would otherwise be an internal Snapcraft team's online meeting to discuss Canonical's production requirements for PostgreSQL. Same engineers we worked shoulder-to-shoulder with carry on today with conversations in Snapcraft forum we had started during hackathon.

I hope Canonical gained just as much valuable feedback and insight from this collaboration. It certainly felt like they were there to eagerly listen and I made sure they receive plenty of it. It was kind of eerie in most positive way, because you don't really get this feeling in offline world that often.

And that, in my opinion is why Snapcraft Summit is such a great event that really helps develop strong bonds in open source community.

---
[View this page online](https://www.commandprompt.com/blog/hacking-on-postgresql-snap-at-snapcraft-summit-2018/)

---

# Command Prompt Inc. Invites You to Attend InnoTech Houston

> 
One of my favorite annual technology events takes place each October in my hometown of Austin, Texas -- Innotech Austin. I&#x27;ve attended for several years in s…

![](../../../../_versions/images/innotech_big.png)![](../../../../uploads/images/innotech.png)

One of my favorite annual technology events takes place each October in my hometown of Austin, Texas -- [Innotech Austin](<https://www.innotechaustin.com/>). I've attended for several years in support of local nonprofit groups including Chick Tech Austin and Austin Women in Technology, as well as for Command Prompt Inc. I thoroughly enjoy the networking opportunities and the professional yet relaxed atmosphere of this event. While attending and exhibiting at Innotech Austin earlier this month, I met several potential partners in supporting PostgreSQL not only for users, but also for students aspiring to a career in full stack and open source development.

This year Innotech has expanded to three other major metroplexes and tech hubs in Texas -- San Antonio, Dallas/Fort Worth, and Houston. Our company founder Joshua D. Drake spoke on "Postgres: The Center of Your Data Universe" earlier this year at the Dallas event. This great opportunity allowed us to connect with the regional tech community and business leaders, as well as [our AWS Partner Network](<https://aws.amazon.com/partners/find/partnerdetails/?n=Command%20Prompt&id=0010L00001oC8WwQAK>) Business Development Manager, Sai Reddy.  

Command Prompt is pleased to support InnoTech in connecting and collaborating, which brings us to:

**InnoTech - Houston's Premiere Technology Innovation**

Be our guest at [InnoTech Houston](<http://www.innotechhouston.com>) at NRG Center on November 6, 2018. This annual event will include all new topics and speakers for a fresh and exciting conference packed with great networking, education and more!

As a supporter of this local technology conference, we encourage you to attend as our guest to benefit professionally and personally from the conference. Please use discount code **"COMMAND8C"** to register for the main InnoTech event for FREE and/or all special events (listed below) at a discounted price. Please note, the free pass does NOT include admission to those special events.

[CLICK HERE](<https://events.thepulsenetwork.com/Attendee/Default.aspx?C=70000088&M=30000123&Mode=HTML>) to register now.

InnoTech Houston is a valuable regional event featuring:

  * Full-day tracks on the following topics:
  * Data & Analytics
  * Disruption & Innovation
  * IT Leadership & Strategy
  * IT Security
  * Morning Keynote and Networking Events
  * And more!



InnoTech Special Events Include:

  * ShareCloud Summit & Lunch
  * Women in Tech Summit & Lunch



For more information or to register, visit [www.innotechhouston.com](<http://www.innotechhouston.com/>).

Stop by and visit with us at Booth 17 to discuss how Command Prompt can help with your data needs!

---
[View this page online](https://www.commandprompt.com/blog/cmdatinnotechhouston/)

---

# Is it time for a newbie-hacker mentor for PostgreSQL.org?

> At PostgresConf US 2018, Bruce Momjian, Grant Zhou, and I had a meeting to discuss potential opportunities for the Chinese PostgreSQL community to participate …

At [PostgresConf US 2018](<https://postgresconf.org/>), Bruce Momjian, Grant Zhou, and I had a meeting to discuss potential opportunities for the Chinese PostgreSQL community to participate in the wider International community, including submitting patches to PostgreSQL.Org. Then at [Postgres Open China](<http://postgresqlchina.com/aboutPGOpen>) the International Consultants Committee had a meeting to discuss more opportunities in depth. Between the two meetings there were a lot of ideas but one opportunity that was considered needs further discussion:

There are many volumes within the PostgreSQL community. Email volume (over 3000 emails to -hackers alone in the first 6 months of 2018), side channel volume, idea volume, and, arguably most important, code volume. The investment someone has to make in order to submit a feature to the community is large. In man hours you could burn months (sometimes years) trying to get a major feature accepted into the code base. The upside is that PostgreSQL as a whole has a quality of software that is higher than most, if not all, other competing projects. The downside is that the investment can be draining to the point where you sometimes ask yourself if it is worth it. ( **Tip:** It usually is.)

We have a commitfest manager, we have a release committee, we have a funds group, a core team, and a sysadmins teams. It seems the next logical step for maturing the community is to remember that it is _people_ that make the community and people need leaders, coordinators, and mentors. So why don’t we have official mentors?

A newbie-hacker mentor could be rotational, which is similar to how the commitfest manager works. How would it work? Do we have a team that signs on for a major release and guides new hackers through the process? Perhaps it is just one person that signs on for each year in a similar manner to the [GSOC](<https://summerofcode.withgoogle.com>) process? What does the community think? Could we work through a process to submit a proposal to -hackers?

I am not sure what the answer is but I know that [Silicon Valley Postgres](<https://www.meetup.com/Silicon-Valley-Postgres/events/252951081/>) is holding a workshop on August 15th addressing some of these exact concerns. It is 100% free and a large team of people is going to be available to help anyone interested in learning how to get through (some may say “survive”) the rigorous PostgreSQL patch review and submission process.

Image Copyright: <https://www.flickr.com/photos/mikelao/> (CC: Attribution)

---
[View this page online](https://www.commandprompt.com/blog/time_for_a_newbie-hacker_mentor_for_postgresql/)

---

# Went to Bejing for Postgres Open China and China Open Source, Open Source World

> I spent the week of June 25th in Bejing, China with the outstanding Chinese Open Source and Postgres Communities. I was there to speak atboth Postgres Open Chi…

I spent the week of June 25th in Bejing, China with the outstanding Chinese Open Source and Postgres Communities. I was there to speak atboth Postgres Open China and the China Open Source World conferences as well as participate in a Chinese Open Source panel and the International Consultants committee meeting, of which I am the President. This was my first trip to Asia and it was amazing. The Chinese culture, hospitality, and friendliness was unparalleled, as was their drive to be more influential and helpful to the International Open Source and Postgres communities.

The entire week was spent trying to answer the question, “How can China participate more thoroughly in the International Open Source and Postgres communities?” We had a lively panel that included the COPU (Chinese Open Source Promotion Union), and representatives from local universities, George Neville-Neil, Alibaba, Stephen Walli of Microsoft, the President of the FreeBSD Foundation, and others. The panel was of particular interest as I was able to hear some of the struggles the local community has had, including respecting copyright, language and cultural barriers, and ensuring economic viability.

I look forward to continuing to assist the Chinese community in being more productive with not only Postgres but also Open Source. There is a wealth of culturally rich, intelligent, and inventive talent available that the PostgreSQL Global Development Group has yet to tap. It will be an exciting few years as both cultures adapt to work together, the contributor list grows, and we start seeing prominent Chinese developers assisting in the growth of PostgreSQL.

---
[View this page online](https://www.commandprompt.com/blog/postgres_in_china_with_Oleg/)

---

# The 401 on Silicon Valley Postgres

> August 2017We launched the Silicon Valley Postgres Meetup.March 6th, 2018We have reached 401 members in what is proving to be one of the fastest growing Postgr…

## August 2017

We launched the Silicon Valley Postgres Meetup.

## March 6th, 2018

We have reached 401 members in what is proving to be one of the fastest growing Postgres meetups in the United States. We launched the meetup along with Vancouver B.C., Denver, Salt Lake City, and Phoenix.

Between these and other meetups we help organize such as New York, Philly, and Dallas, we are reaching more people than ever in education, advocacy, and applicability of Postgres!

## The increase of professional contribution

Why is this important? The majority of potential Postgres contributors are not part of the internal network of [PostgreSQL.Org](<https://postgresql.org/>) and other international organizations. They are developers, users, consultants, companies, project managers, documentation writers, etc. These professionals are potential contributors.

Wouldn’t it be great if we had a team of consultants from different disciplines, companies, and backgrounds creating, “10 Steps on How to Perform your Needed Postgres $task,” that included a professional documentation writer?

Wouldn’t it be great if we had a series of professional consultants and speakers that willingly took the time to give a mini-conference such as the [PostgresConf](<https://postgresconf.org/>) Mini Series where you can get 3-4 hours of free training on Postgres?

## Greatness is achieved

When you encourage, grow, support, and educate the entire community.

 **People, Postgres, Data**

---
[View this page online](https://www.commandprompt.com/blog/the_401_on_silicon_valley_postgres/)

---

# December 2017 Update and News

> PostgreSQL V10: An Amplified Version Of PostgreSQLFor more than a decade, the Postgres community has released new major versions almost annually to meet the ev…

**PostgreSQL V10: An Amplified Version Of PostgreSQL**

For more than a decade, the Postgres community has released new major versions almost annually to meet the evolving needs of the Database Industry. The first great release of Postgres was 8.3 in 2008, with a clean and evolutionary release of 8.4 eighteen months later.  
The 2017 v10 release of Postgres is the first version that Command Prompt Inc. founder and lead consultant Joshua D. Drake would consider truly, “Enterprise Ready.” [Read more](<../../../../blog/postgresql_v10_an_amplified_version_of_postgresql/>)

  
 **Command Prompt Inc. Joins the AWS Partner Network**

With the recent advancements of AWS PostgreSQL instances and their Database Freedom initiative alluded to in [Andy Jassy’s AWS re:Invent 2017 Keynote](<https://www.youtube.com/watch?v=1IxDLeFQKPk&feature=youtu.be&t=37m08s>), more and more AWS customers are embracing PostgreSQL through RDS and Aurora.

As an official AWS Consulting Partner, Command Prompt is positioned to support any new and existing customers exploring the AWS offerings.Command Prompt Inc. has been recognized by CIOReview magazine as one of the 20 Most Promising AWS Solution Providers 2017. Check out the [CIOReview profile](<http://bit.ly/2hPkcYg>) on Joshua D. Drake and his viewpoints on "Navigating PostgreSQL Deployments in the Cloud."

 **Migrations from Proprietary Databases to PostgreSQL**

Proprietary databases can be costly, whether for SMBs or Enterprise companies. Open source platform PostgreSQL can provide the affordability and durability needed to meet your company's data needs.  
  
Looking to migrate from Oracle to Postgres? Command Prompt supports On-Prem, Google Cloud, AWS RDS and Aurora PostgreSQL edition? We are here to help! Check out our [Migration Services](<../../../../services/oracle_to_postgres_migrations/>).

 **PostgreSQL is hip again**

As indicated by the chart above from the [October 2017 Hacker News Hiring Trends](<https://www.hntrends.com/2017/october-bounce-react-extends-streak.html?compare1=Postgresql&compare2=MySQL&compare3=SQL+Server&compare4=Oracle>), the percentage of job postings for PostgreSQL related jobs has increased and exceeds other database platforms.  
  
A [recent article](<https://www.infoworld.com/article/3240064/sql/why-old-school-postgresql-is-so-hip-again.html>) by InfoWorld columnist Matt Asay highlights just a few of the reasons why PostgreSQL is increasing in popularity. Asay cites native JSON support in PostgreSQL 9.2 and JSONB in 9.4 as innovations, as well as improved scalability via open source extension Citus.  
  
Asay recently [asked via Twitter](<https://twitter.com/mjasay/status/937781376467603456>),“What would an enterprise give up moving from Oracle to Postgres? Why do you think more haven't made the shift?” which resulted in insightful dialogue. Responses ranged from “its focus first on data integrity and correctness, ability to extend the database through runtime extension hooks, and the opportunity to query other systems within PostgreSQL through foreign data wrappers.”  
  
Joyent Director of Solution Engineering Elijah Zupanic stated that “From a developer perspective it is a pleasure to use. The documentation is wonderful, the data types reflect the types developers work with and there is little surprising.”

  
 **Meet Our New Team Member**

Debra Cerda joined our Command Prompt team as Director of Business Development in May 2017. Debra has long been a PostgreSQL advocate as organizer of the Austin PostgreSQL User Group. Debra also volunteers with the [Postgres Conference Series](<https://pgconf.org/>).  
  
Learn more about Debra, how did she get here, why she's a data geek, and why Postgres is her "databae".  
Read More

---
[View this page online](https://www.commandprompt.com/blog/december2017newsletter/)

---

# Connection Initiation Overhead is Killing Your Web App - Use a Connection Pool

> Customers often ask us what is the correct setting for max_connections on their PostgreSQL cluster?  There is a short answer to this question, and there is a v…

Customers often ask us what is the correct setting for `max_connections` on their PostgreSQL cluster?  There is a short answer to this question, and there is a very, very long answer. The short answer is: accept the default if that works for you, or try 10 times the number of CPU cores and see if that works ok.

There is another short answer which is: **you may be asking the wrong question**.

The original implicit assumption is " _more connections will get me more throughput_ ". This is often false. A question usually worth pursuing is " _How can my existing set of connections be used efficiently?_ "

If you think that your application wants more connections and you are considering raising `max_connections`, then you need to understand that connections carry overhead. This is a generalization: there is overhead of initializing each connection, there is overhead of maintaining an open connection, there is overhead of process concurrency in the OS, and there is overhead of concurrency in the database. Each connection corresponds to a separate operating system process and a separate TCP or Unix socket, and those things have their own hard and de facto limits in the OS as well.

Connection initiation overhead can seriously impair common kinds of web applications that make database connections for each web request. In this common scenario, each connect-query-disconnect cycle is so slow that the architect solves the problem by increasing the number of concurrent connections. As mentioned above, concurrency brings its own problems. If you have a lot of these connect-query-disconnect cycles then you can probably dramatically speed things up by using a connection pooler and forget about raising `max_connections`.

## Demonstration of Connection Initiation Overhead

Here I share some simple benchmark results that illustrate connection initiation overhead. I did this by running a simple pgbench benchmark with and without [pgbouncer](<https://pgbouncer.github.io/> "pgbouncer"), a connection pooler.

Connection poolers are another subject of frequent confusion. Contrary to frequent first impressions, connection poolers do NOT allow a greater number of concurrent connections. Instead, they manage a pool of open connections that clients _take turns_ using. The benefit is near elimination of connection initiation overhead, and this really speeds things up.

[pgbench](<https://www.postgresql.org/docs/10/static/pgbench.html> "pgbennch documentation") is a simple benchmarking program that ships with PostgreSQL. I used it to initialize a benchmark database with the default options. This creates a database only 22MB in size: that means the entire database will quickly be cached in memory after a few benchmark test runs.

I configured both the pooled and direct-connected benchmark clients to both connect to PostgreSQL via TCP sockets on the localhost and I specified that it run only a single client at a time. I specified the --select-only option of pgbench, causing it to only issue SELECT statements: this eliminates disk I/O, locking, dirty cache, and vacuum from consideration. Lastly, I specified the --connect option of pgbench, which, as its documentation explains, "Establish a new connection for each transaction, rather than doing it just once per client session. This is useful to measure the connection overhead." Each benchmark simply does:

  1. Connect to PostgreSQL.
  2. Run a single SELECT query.
  3. Disconnect.



This cycle repeats as fast as it can for the single client process. I ran each benchmark for 60 seconds and recorded system performance metrics with [sar](<http://sebastien.godard.pagesperso-orange.fr/> "sysstat home page") on a five second interval. I ran pgbench three times using direct PostgreSQL connections and three times connecting via the pgbouncer connection pooler.  This all ran on PostgreSQL 9.6 on my desktop system with Intel i3 cpu. The three repetitions produced very similar results but the difference between direct and pooled connections was dramatic:

## Benchmark Results

![bar graph of transactions with direct and pooled connections](../../../../uploads/images/connection_overhead_tps.png) ![bar graph of cpu usage with direct and pooled connections](../../../../uploads/images/connection_overhead_cpu.png)

The benchmarks with connection pooling produced eight times more transactions while using _less_ cpu time!

Yes, connection initiation carries significant overhead, and a connection pooler is the solution.

---
[View this page online](https://www.commandprompt.com/blog/connection-initiation-overhead-pgbouncer/)

---

# Speaking and training at PGConf Austin

> I leave this Sunday for beautiful and ecclectic Austin, Tx. I will be providing the training Postgres Performance and Maintenance as well as speaking on The Po…

I leave this Sunday for beautiful and ecclectic Austin, Tx. I will be providing the training Postgres Performance and Maintenance as well as speaking on The Power of Postgres Replication. The training is one that I give several times a year but the Replication talk is new. Although I have spoke on replication before, this new presentation is all about the power of Logical Replication. If you would like to learn more,[ pick up a ticket](<https://pgconf.us/conferences/Austin2017>) and let's have some fun. If you can't make it to Austin, perhaps you can make it to the [PGConf Mini: NYC on December 14th.](<https://www.meetup.com/postgresql-3/events/245170896/>) I will be presenting the same Replication presentation at that event. Let's bring about the new year with a strong showing of [@amplifypostgres](<https://twitter.com/amplifypostgres>)!

---
[View this page online](https://www.commandprompt.com/blog/speakling_and_training_at_pgconf_austin/)

---

# PostgreSQL v10: An Amplified Version of PostgreSQL

> For more than a decade, the Postgres community has released new major versions almost annually to meet the evolving needs of the Database Industry. The first g…

For more than a decade, the Postgres community has released new major versions almost annually to meet the evolving needs of the Database Industry. The first great release of Postgres was 8.3 in 2008, with a clean and evolutionary release of 8.4 eighteen months later. The 2017 v10 release of Postgres is the first version that I would consider truly, “Enterprise Ready.”

PostgreSQL has seen great success in the commercial enterprise for years. However, that success has largely been relegated to departmental success; e.g. the installation is solving a specific problem for a specific department. Often it’s the public facing data source for a larger Oracle instance or to manipulate GIS data. In these roles, PostgreSQL has been a defacto choice for enterprises for a very long time.

As major cloud providers such as [AWS](<https://aws.amazon.com>), [Microsoft Azure](<https://azure.microsoft.com/en-us/services/postgresql/>), and [Google](<https://cloud.google.com/sql/docs/postgres/>) continue to implement and upgrade their PostgreSQL support you can expect to hear more about migrations. The desire to escape Oracle has never been stronger. We will start to see not just small businesses but also large businesses migrating their CRM and ERP systems.

With full ACID compliance, mature parallel scan support, native partitioning, and logical replication, PostgreSQL provides more features and performance for platforms such as [Odoo](<https://www.odoo.com>) and industry specific providers such as [Timescale](<https://timescale.com/>) and [Brytlyt](<http://www.brytlyt.com>). These and other features are why V10 is going to build the ecosystem.

Since August I have presented on v10 several times, most recently to a full room at [PGConf Seattle](<https://pgconf.us/conferences/Seattle2017>). I have also presented at multiple groups in Vancouver B.C. and Colorado. The overwhelming consensus, even among those who don’t currently use PostgreSQL, is that the database is on their list of migration possibilities. V10 is the defining version of PostgreSQL and we are now in a time where we will begin to see mass adoption across many industries.

It is going to be years before a company such as Oracle starts to feel more than pinpricks at the number of migrations companies are performing but each one of those migrations is a pinprick through the heart of a retiring industry. The time of the Open Source, enterprise-wide database choice is here and PostgreSQL is the foundation in which it is built.

Are you considering migrating to PostgreSQL? [Let our humble company help your enterprise.](<../../../../contact>) Our Command Prompt team has been helping people with Postgres longer than any other PostgreSQL professional services vendor.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_v10_an_amplified_version_of_postgresql/)

---

# Speaking at PGConf Seattle, are you going?

> Jim Mlodgenski in attendence at the 9th Annual PGConf.EU and I am working hard on updating my slides for my presentation at PGConf Seattle. PGConf Seattle is b…

Jim Mlodgenski in attendence at the 9th Annual [PGConf.EU](<https://pgconf.eu>) and I am working hard on updating my slides for my presentation at [PGConf Seattle. PGConf Seattle](<https://pgconf.us/conferences/Seattle2017>) is being held at the downtown Seattle Sheraton on November 13th and 14th. I will be speaking on Postgres version 10. I will also be training on [Postgres Performance and Maintenance (you can buy your ticket here)](<https://pgconf.us/conferences/Seattle2017#tickets>). If you are planning on attending my training or any of the others I recommend that you register quickly. There are only half a dozen seats left for mine and only a few more than that for Robert Bernier's.

The Postgres V10 presentation is the same presentation I gave at PGConf Ohio as well as the Vancouver Developers Network. However, the Postgres Performance training is being updated to include proper provisioning for Amazon EC2 and RDS. Whether the community (myself included) likes it or not, the majority of new installations of our great database are being deployed to the cloud and Amazon, right now is the king of cloud. However, the amount of information available on how to actually provision PostgreSQL properly within the AWS infrastructure is slight at best. I wish all of our community members across the pond right now a fantastic conference and I hope to see a few of them join me in Seattle! It's always sunny in Seattle.

Rock on and [@amplifypostgres](<https://twitter.com/amplifypostgres>)!

---
[View this page online](https://www.commandprompt.com/blog/speaking_at_postgres_conference_seattle/)

---

# Postgres is better than MySQL but not because of how long it took to fix a bug

> Many argue which is better: PostgreSQL or MySQL. A recent post by MySQL evangelist and community manager Frederic Descamps prompted some criticism of the amoun…

Many argue which is better: PostgreSQL or MySQL. A [recent post](<http://lefred.be/content/bye-bye-bug-199/>) by MySQL evangelist and community manager Frederic Descamps prompted some criticism of the amount of time that it took for a particular bug to be fixed -- 14.5 years to be exact, from the initial report.

There’s a long list of technical and performance comparisons, but here’s the number one reason to choose Postgres over MySQL.

## Community Drives Change

The PostgreSQL community is different than MySQL. First, MySQL is not a project; it is a product. Yes, they are both Open Source but Postgres is vendor neutral, contributor centric, and not controlled by any single entity. Using a product or project defines the culture you are embracing when you choose to use a particular software. For example, with Postgres you have true contribution capability to a project; with MySQL you support the profits of a single commercial entity (and Oracle's Larry Ellison owns his very own private island).

When you want education, professional development, and live community interaction about Postgres do you want to support a [vendor neutral, community, and volunteer organized non-profit conferences](<https://pgconf.org/conferences/2018>) or do you want to succumb to a brand? Postgres is a feature rich, ACID compliant, extensible database that offers best in class Relational, Document/JSON and High Availability support. It also has a license that allows you to build any product or project you want without hinderance. That’s why Command Prompt uses, supports, contributes to, and recommends Postgres.

Let’s talk honestly about PostgreSQL for a moment. This might sting a bit, but our siloed arrogance doesn't help our community. It hurts it. Here are four things I hate about PostgreSQL and the PostgreSQL community:

## Not a single decent community driven graphical admin tool

PGAdminIV and OmniDB are okay and getting better, but they are nowhere near as performant and professional as some competing products (Navicat, PostgreSQL EMS manager).

## The lack of native partitioning until version 10

Yes, Postgres is a community driven effort and therefore the patches received are the ones the community can consider for inclusion. This is where working with a vendor such as MySQL is better than Postgres. If enough users demand it, MySQL _must_ implement it or they lose customers. When you work with a community it isn't like that. We rely on the will and resources of others.

## Lack of Vision

This is a frustrating one. Postgres has had logical replication for a decade but it was a bolt on (or a fork depending on version). It didn't matter how many people told the Postgres hackers that it needed to be in core. The hackers didn't want logical replication so it didn't happen. A decade later, we have logical replication largely via the resources and efforts of the 2ndQuadrant. A welcome change but it would be nice if it wasn't always such a battle to prove what is already proven (consider how long other competitors have had the feature).

## The community silo

This issue is a big one. There are many in the Postgres community that are of the narrow-minded belief that ["The Community" is on mailing lists and on IRC](<../../../../blog/where_is_the_postgres_community/>). It is a dangerously restrictive view when we have many communities that all but don't participate within the "community channels." Russia, Japan, India, and Brazil are notable ones. Before anyone starts saying, “Well this person does…” yes, there are some participants from these regions, but they are far outweighed by the larger community. The Slack and Telegram channels are both larger than IRC, with almost 1400 members in each of those channels. The idea of the "central portal to community" died a decade ago and has only gotten more disparate. We as the PostgreSQL.Org community only hurt ourselves by continuing to ignore the wider and more inclusive vision.

## The important part: What are we going to do about it?

I can go on and on about this as I live in a hybrid world of users and developers. I see both sides. I hear both sides. [It is very important to be cognisant of the message we are sending](<../../../../blog/indirect_advocacy/>). I have conversations with people every week that want to participate and help grow the community but aren't willing to for reasons related to the community culture:

  * The next generation doesn't use email lists.
  * The next generation doesn't bottom post.
  * The next generation doesn't use plain text.
  * The next generation doesn't use bare metal.



The next generation doesn't want you to tell them why their solution is wrong. **They want you to answer the question they asked.**

Do we want to continue to grow this community and have influence on the next generation to do it right? Or do we want to alienate them through old patterns, “get off my lawn” attitudes, and an inability to do great things because we are tied up in our own ideology? [How do we as a community want to lead?](<https://stevekeating.me/2017/10/12/the-challenge-of-frustration/>) I would like to to think that we would proactively, productively, and positively lead and thereby truly support and grow our community. That is how our Postgres community can be be different than MySQL.

The choice is yours.

---
[View this page online](https://www.commandprompt.com/blog/postgres_better_than_mysql/)

---

# Copy Files Through an SSH Wormhole!

> Here is a fun and useful Linux console hack you might like.
If you use ssh A LOT, maybe you encounter situations where you have a shell that is three or more …

Here is a fun and useful Linux console hack you might like.

If you use ssh A LOT, maybe you encounter situations where you have a shell that is three or more hops removed your local workstation. And maybe you've been in the situation where there is some file that you need to get from "there" to "here" or vice versa. And you really are annoyed by the thought of scp-ing the file over 3+ hops (and not so lucky that all the keys and permissions in the pipeline enable easy piping through ssh).  
  
Lucky you! In a moment of inspiration, I concocted this ultra-unixy hack to copy the file in ONE hop (more or less). Assuming the file you need is named "file.sql", do:
    
    
    < file.sql bzip2 --stdout | base64 --wrap 0

This will dump a pile of base64 characters on your console, hopefully fitting all on one screen. If the file was too big for all the data to fit on one screenful, you can get extra hacky by paging it through "less" or even decreasing the font size on your console.  
  
Now copy all the base64 characters with your nice mouse cursor, or however you usually do it. Then in the console on the other end of your ssh tunnel do:
    
    
    echo "paste here" | base64 --decode | bzip2 -d --stdout > file.sql

Your file has arrived at the other end of the wormhole.

Happy hacking!

---
[View this page online](https://www.commandprompt.com/blog/copy-file-ssh-wormhole/)

---

# London PostgreSQL Meetup

> One of the fantastic characteristics of Postgres leaders is their willingness to serve the community.Yesterday I found out that one of our former team members,…

One of the fantastic characteristics of Postgres leaders is their willingness to serve the community.

Yesterday I found out that one of our former team members, [Devrim Gunduz, has created a new London PostgreSQL user group](<https://people.planetpostgresql.org/devrim/index.php?/archives/93-London-PostgreSQL-Users-Group-First-meetup.html>) and they had their [inaugural meeting](<https://www.meetup.com/preview/London-PostgreSQL-Users-Group>) in October. At the time of this writing there were 123 members in the group. This level of response shows a great demand for Postgres content. I spoke with Devrim yesterday, and he shared that he has a mission to provide the London community with new content each month. It is a bold goal as running meetups that frequently can be daunting, but we believe there is enough support in the area to warrant this frequency. Devrim has even asked me to cross the pond to present at a future meetup, which I plan on doing in 2018. It will be great to see a leader of Postgres provide consistent growth opportunities for the Postgres community in London.

Rock on and [@amplifypostgres](<https://twitter.com/amplifypostgres>)!

---
[View this page online](https://www.commandprompt.com/blog/london_postgresql_meetup/)

---

# PostgreSQL Non-exclusive Base Backups in Bash

> Here I&#x27;m posting a bash script that implements PostgreSQL&#x27;s new (since 9.6) &quot;non-exclusive&quot; base backup.I often find that new customers are shy about binary Po…

Here I'm posting a bash script that implements PostgreSQL's new (since 9.6) "non-exclusive" base backup.  
  
I often find that new customers are shy about binary PostgreSQL backups and only schedule logical pg_dump backups. PostgreSQL provides a brilliantly simple binary backup solution that enables easy point in time recovery, unlike pg_dump backups. So I always try to steer people towards these binary "base backups", as they are called in the PostgreSQL world.  
  
In version 9.6, this base backup feature became more flexible, with an additional option allowing more than one base backup to run at a time. For customers with aggressive (or badly scheduled) backup schedules, this allows both backups to succeed, where they would both fail before version 9.6.  
  
The new option is a boolean argument to sql functions pg_start_backup() and pg_stop_backup(). However the new option isn't so brilliantly simple to use in shell scripts along with its common associates tar or rsync. It requires concurrent processes or threads -- because pg_start_backup() and pg_stop_backup() must be run in the same session -- and it requires parsing text output from pg_stop_backup() and writing out to files backup_label and tablespace_map. I wanted the flexibility of the non-exclusive backup behavior but I also wanted the simplicity of a shell script. Below is the solution I worked out. This is a minimal implementation without proper error handling, but it demonstrates a technique to solve the new problem.

The tricky thing was running the stop and start functions in psql in the same session while running the file backup in between them in a different process. I accomplished it by using both the --command and --file options of psql.  The --command option runs pg_start_backup(), and the --file option listens on a fifo for pg_stop_backup(). After tar/rsync completes, bash echoes the stop command to the fifo then uses bash's "wait" builtin command to wait for psql/PostgreSQL to stop the backup. Then at the end, use awk to parse the output of pg_stop_backup() and write it to files in the backup directory.  
  
If you try it out, please let me know your experience!
    
    
    #!/bin/bash
    #Minimal implementation of PostgreSQL 9.6+ "non-exclusive" base backup API.
    
    set -e
    set -x
    
    TMP_FIFO="/tmp/~tmpfifo_$RANDOM"
    TMP_OUT=$(tempfile -d /tmp)
    BACKUP_DESTINATION=/tmp
    
    if [ -n "$(jobs)" ] ; then
        echo "Background jobs are running. Please run this script in a different (or sub-) shell. Exiting"
        exit 1
    fi
    
    #Make a fifo where psql will listen for the pg_stop_backup() statement:
    mkfifo -m 600 $TMP_FIFO
    
    #psql executes a command then waits in the background for data on the fifo:
    psql --pset=tuples_only=true --pset=format=unaligned --pset=footer=false -c "select pg_start_backup('my backup', true, false)" -f $TMP_FIFO postgres > $TMP_OUT 2> /dev/null &
    
    #Run rsync or tar here. The exact details will depend on your system. For example:
    tar -c --exclude=$PGDATA/postmaster* --exclude=$PGDATA/pg_xlog/* -f $BACKUP_DESTINATION/base_backup.tar $PGDATA
    
    echo "select * from pg_stop_backup(false)" > $TMP_FIFO
    
    #wait for psql to return from background:
    wait -n %1
    
    #Treat the whole file as a single line delimited by pipes. Use sed to strip empty lines:
    awk 'BEGIN { RS = "\x00" ; FS = "|" } { print $2 }' $TMP_OUT > $BACKUP_DESTINATION/backup_label
    awk 'BEGIN { RS = "\x00" ; FS = "|" } { print $3 }' $TMP_OUT | sed -e '/^$/d' > $BACKUP_DESTINATION/tablespace_map
    
    rm -f $TMP_FIFO $TMP_OUT

---
[View this page online](https://www.commandprompt.com/blog/postgresql-non-exclusive-base-Backup-bash/)

---

# Silicon Valley Postgres Meetup: How to Auto-cache Postgres with no code changes

> The first meeting of the Silicon Valley Postgres Meetup was last night. Amazon Web Services sponsored the facilities in Cupertino and Roland Lee from Hemdallda…

The first meeting of the [Silicon Valley Postgres Meetup](<https://www.meetup.com/preview/Silicon-Valley-Postgres-Meetup>) was last night. Amazon Web Services sponsored the facilities in Cupertino and Roland Lee from [Hemdalldata](<https://www.heimdalldata.com>) presented on:

 **How to Auto-Cache Postgres with no code changes.**

There were about 20 people in attendance as well as another half a dozen that participated via [Amazon Chime.](<https://chime.aws>) Debbie Cerda, our Director of Business Development flew out from Austin, Tx to host. When we launched the Silicon Valley Meetup we wanted to ensure that it would not conflict with the well respected San Francisco PUG. Based on initial response, there is not a conflict and we are very happy about that. We attribute the lack of conflict two items:

  1. San Francisco is not part of the Silicon Valley
  2. During the times you would travel to a meetup, it will take you a minimum of 90 minutes to get from SF to SV. This is essentially driving from NYCPUG to PhillyPUG. People typically don't do that (Bruce Momjian excluded).



This has been further supported by the membership. Although the group launched less than a month ago we have over 130 members and less than 10% are members of both SFPUG and Silicon Valley PUG. It is nice to expand the coverage of Postgres people building. [Please join us in continuing to build the community!](<https://www.meetup.com/preview/Silicon-Valley-Postgres-Meetup>)

---
[View this page online](https://www.commandprompt.com/blog/Silico-Valley-Postgres-Meetup-How-to-Auto-cache-Postgres-with-no-code-changes/)

---

# Bridging the PostgreSQL Chasm

> &quot;I&#x27;m not technical enough to even understand what your firm does.&quot;This message from a new LinkedIn connection last week. The message literally stopped me in my…

_" I'm not technical enough to even understand what your firm does."_

This message from a new LinkedIn connection last week. The message literally stopped me in my tracks. I was preparing to spend the day amongst new and seasoned developers at DevDay Austin, a free full-day technical event hosted by [Amazon Web Services](<https://aws.amazon.com/>). Cloud computing, IoT, Containers, Artificial Intelligence, and Mobile application development were just a few of the topics to be covered. 

Ironically, I'd spent some time the day before trimming my LinkedIn profile summary, focusing on my primary career in business development for Command Prompt, Inc. 

I've managed a [portfolio career approach](<https://www.forbes.com/sites/ruchikatulshyan/2016/03/31/how-to-have-two-successful-careers-at-the-same-time/#4e1b7d38382d>) for several years, working in the craft beer and film industries to supplement my technology career. What these careers share in common is that I most often work as a "connector." Not only do I bring people together who can have a mutually beneficial but often translating complex subjects into more easily digestible components.

But back to the LinkedIn connection, and my cause for alarm -- this gentleman has worked for 35 years in a profession that I'd aspired to at the age of 10 years of age. His firm conducts archeological surveys, site testing and mitigation, construction monitoring, historical documentary research, and academic research capabilities. Collecting and cataloguing, meeting compliance -- science is data, and data acquistion, analysis, and management is as critical as the fragile specimens of the past.

#### Where's the Disconnect?

If it's not evident or intuitive how a relational database such as PostgreSQL can support a technical professional's data management and analysis, then there's a disconnect. As someone who's [acquired, managed, and analyzed data extensively](<https://commandprompt.com/blog/introdebracerda/>) in the past, I need to rethink my approach, and take appropriate action. There are plenty of PostgreSQL committers and contributors who can converse and engage within the more technical community, and there are plenty of PostgreSQL conferences including the [PGConf US](<https://pgconf.us/>) series where developers and DBAs can receive valuable training and content. So why aren't we connecting to potential users?

### The Chasm

What I see lacking as a whole with PostgreSQL is effective communication and outreach to engage and onboard new users and developers. Geoffrey A. Moore's book "Crossing the Chasm: Marketing and Selling Disruptive Products to Mainstream Customers" comes to mind. This book which has been updated several times since its initital publication in 1991 addresses the adoption of technology, including marketing and implementation approaches. 

The initial lifecycle seen above from Moore's book indicates a chasm between the innovation stage and adoption stage, and more recent lifecycle indicate chasms occurring between later stages as well.

### Where is Postgres?

I would argue that PostgreSQL is still on the rise of the early majority phase, due to competition from proprietary solutions as well as my observations in much of the technology space. There has been a lot of "white noise" from the NoSQL enthusiasts and an absence of advocacy for PostgreSQL in the Big Data and IoT realm, which is unwarranted. Basic exposure to PostgreSQL teaches that integration between PostgreSQL and NoSQL using foreign data wrappers and other extensions and tools helps to build more robust data management and analytics.

PostgreSQL has long been capable of "deep computing," and as I recently described new features and improvements with PostgreSQL 10 related to a use case to several technologists, they were amazed at the implication towards machine learning. How is this message not getting out regularly?

My primary belief has been that the PostgreSQL community faces inward far too much -- getting out and engaging with users and developers who are unfamiliar with Postgres is the best way to ensure that we are amplifying and advocating for PostgreSQL. With the caveat that I will not claim to be a PostgreSQL evangelist, I am an advocate. An evangelist demands that their beliefs are accepted part and parcel, whereas an advocate can recognize and accept the limitations of their offerings. Without acknowledging the limitations of PostgreSQL, advancements and improvements cannot be made. This is where the global community thrives -- at collaborating and improving on PostgreSQL as a product. But until we as a whole get better at connecting to more users and new developers, then we can't fill and cross the chasms. Especially if MySQL and new developers are intimidated? unfamiliar? with PostgreSQL and don't get to the starting line.

### How am I currently affecting a change?

Starting with Phase 1 (through 3) Deep Dive into AWS and communities. My experiences at AWS Start-up Day and AWS DataDay in Austin have been extremely insightful and engaging, so it seemed like a good starting point. Here's what I'm working on at the moment:

  1. Acquiring my [AWS Business Professional](<https://aws.amazon.com/partners/training/accreditation/>) accreditation, to better relate to users in need of support of their data storage and computing
  2. Attending [AWS User Meetups](<https://www.meetup.com/topics/amazon-web-services/>), to understand the AWS Universe as there's a great need in their customer base for RDBMS solutions, and inherently service and support
  3. Attending [re:INVENT 2017](<https://reinvent.awsevents.com/>) this November -- taking "drinking from the firehose" to a whole new level
  4. Keep powering away within my own local community, from [DevOps](<https://www.meetup.com/austin-devops/>) to [Linux](<https://www.meetup.com/linuxaustin/>), and to various sectors and communities to which I am connected, locally and globally
  5. Supporting the organization and execution of [PGConf US and Locals conference series](<https://www.pgconf.us/>)
  6. Being open to management offers to travel and support relevant user groups, from AWS users to Data, as well as new Postgres groups



To be continued ...

---
[View this page online](https://www.commandprompt.com/blog/postgreschasm/)

---

# Postgres at Seattle Web Developers Meetup, recap

> Postgres: The center of your data universeThis talk is proving to be great content for those who are not necessarily Postgres Users. Last night I presented thi…

Postgres: The center of your data universe

This talk is proving to be great content for those who are not necessarily Postgres Users. Last night I presented this talk at the Seattle Web Developers Meetup. The location was Adobe, next to Google and Tableau. I didn't even know there was a small tech complex on N. 34th in Seattle. There were about 27 people, which falls in line with the 50% rule of Meetups[1]. Here are my observations from the audience:

  1. Surprisingly the majority of developers were Python web developers (as a group)
  2. Many of them do not use Postgres and wanted to hear more about it
  3. There were several government employees that were wondering how to get Postgres deployed
  4. Presenting with two screens next to each other is difficult because I walk when I present
  5. People are still interested in PLphp



I wasn't suprised that there were Python web developers. I was surprised that there were not more Node or Ruby developers. In fact, when asked there wasn't a single Ruby person in the room and Node was only a hobby for one other.

About half the room raised their hand when asked if they used Postgres. However, the rest were very engaged, asked intelligent questions and most were particularly interested in our JSON and FDW support.

The government employee was trying to figure out how to get out of MSSQL. My rseponse was the classic, "Just don't tell them". Obviously I don't want to get anyone in trouble but more often than people like to admit the boss doesn't care if you are using MSSQL, they care that you aren't going to lose data and the application is going to perform well. The spec could just say SQL DB, which MSSQL and PostgreSQL both are. We laughed at the idea but I also informed her of Crunchy's Postgres with Common Criteria and other governmental agencies that are running Postgres.

The two screen things is weird. I do o.k. when the screens are on the left and right of me but both screens were to the left so I ended up cutting off the screen anytime I walked. I might need to figure out how to stand still when I present.

We never should have created PLphp. It refuses to die.

That's all for now, I am taking a break from presenting until [PGConf.US Local: Ohio](<https://pgconf.us/conferences/Ohio2017>).

1\. If 50 people RSVP to a meetup, approximately 25 will show up.

---
[View this page online](https://www.commandprompt.com/blog/postgres_at_seattle_web_developers_meetup_recap/)

---

# Postgres, upcoming community awesomeness

> Upcoming community awesomenessNow that summer is over and we have officially decided never to schedule anything in August again, we need to share a bunch of up…

## Upcoming community awesomeness

Now that summer is over and we have officially decided never to schedule anything in August again, we need to share a bunch of upcoming community goodness!

Never lose sight of the goal

  * Postgres the center of your data universe at the [Seattle Web Developers meetup on September 14th.](<https://www.meetup.com/preview/Seattle-Web-App-Developers-Group/events/242834643>) This is an updated presentation that I gave at Datalayer last May. I am adding some goodies specifically for Web developers.



  * PGConf US and NYCPUG are hosting: [PGConf US Mini: NYC](<https://pgconf.us/conferences/NYCMini2017>) tomorrow! [Bruce Momjian](<http://momjian.us>) will be speaking on Postgres v10. This is the second mini that PGConf US has organized. The first was last May in Austin. It looks like a great lineup and turnout.



  * I will be speaking at [PGConf US Local: Ohio](<https://pgconf.us/conferences/Ohio2017>) in conjunction with [Ohio Linux Fest](<https://ohiolinux.org/>). I will also be [training on Postgres Performance and Maintenance](<https://pgconf.us/conferences/Ohio2017>). It is great to integrate with other communities and finally bring a formal Postgres event to Ohio is exciting. I hope we can continue to grow it.



  * Debbie Cerda will be hosting the [Silicon Valley Postgres Meetup](<https://www.meetup.com/preview/Silicon-Valley-Postgres-Meetup>) on September 19th with speakers Erik Brandsberg of [Heimdall Data](<https://www.heimdalldata.com/>) and Roland Lee on: [How to Auto-cache Postgres with no code changes](<https://www.meetup.com/preview/Silicon-Valley-Postgres-Meetup/events/242906315>) . Hiring Debbie was one of the best decisions Command Prompt ever made. She is allowing us to focus much more on community and business development than ever before. Her ability to connect with people and her willingness to travel has made it a lot easier to meet one of Command Prompt's long term goals: Building out more Postgres community. The Silicon Valley meetup is just one instance. We also launched Denver which has a meeting in November (and possibly October).



  * And last but certainly not least, PostgreSQL version 10 is set to be released very, very soon!



It is easy to forget that although code contribution to an Open Source project is vital, so is building the people within and external to the community. The majority of people that go to meetups do not follow -hackers or -general. They are professionals trying to get a job done. It takes a different approach to continue to grow that side of the community than it does with C developers hacking backend code. Our team looks forward to continue to aggressively address the needs of the professional Postgres community.

---
[View this page online](https://www.commandprompt.com/blog/postgres_upcoming_community_awesomeness/)

---

# Postgres Load Testing with pgreplay

> OverviewUsually we want to test before deploying changes to a production Postgresql cluster. Commonly the test itself is executed in a context that is not very…

Overview

Usually we want to test before deploying changes to a production Postgresql cluster. Commonly the test itself is executed in a context that is not very similar to the production environment. How can you run a test that is **_realistic_** so there are no horrible surprises when you deploy on the production system? Read on! This document describes a procedure where changes can be tested on a system that is running a load that is nearly identical to a production system.

This procedure utilizes [pgreplay](<https://laurenz.github.io/pgreplay/>), which reads postgres' server logs and executes the sql statements found there, with the same timing that they were executed on the production system.

This procedure also uses lvm and its volume snapshot feature for fast testing iteration.

Collect Production Logs

Normally only select sql statements (such as slow queries) are logged to the server log. We will temporarily change the cluster configuration so that ALL sql statements are logged, as well as some other things.

It's convenient to use the "alter system" statement for this, if the Postgresql version is recent enough; if it's not recent enough, the "include" directive in postgresql.conf can be used instead.
    
    
    alter system set log_destination = 'stderr,csvlog';
    alter system set log_filename = 'postgresql-%Y-%m-%d_%H%M%S_verbose.log';
    alter system set log_line_prefix = '%t [%p]: [%l-1] db=%d,user=%u '; --only change if not using csv
    alter system set log_statement = 'all';
    alter system set log_min_messages = error;
    alter system set log_min_error_statement = log;
    alter system set log_connections = on;
    alter system set log_disconnections = on;

Reload postgres.

For a more realistic test, it helps to find a point in time with no open transactions. This point in time will be used later in the replay, and allows the replay to start in a consistent state. Run the following query interactively until it returns a timestamp, and record the timestamp for later:
    
    
    select now()
    from pg_stat_activity
    where
        xact_start is not null
        and query not like 'autovacuum%'
    having count(*) = 0;

Keep the temporary logging settings in effect during a time and for a duration that you judge to be representative of production activity. One hour is a starting point to consider. After that duration, reset the configs:
    
    
    alter system reset all;

or, if you have other configs that you don't want to reset, then reset these individually:
    
    
    alter system reset log_destination;
    alter system reset log_filename;
    alter system reset log_line_prefix;
    alter system reset log_min_duration_statement;
    alter system reset log_min_messages;
    alter system reset log_min_error_statement;
    alter system reset log_connections;
    alter system reset log_disconnections;
    
    

Copy the log file (csv preferably) to the test system.

On the test system, edit the first log file, deleting all lines preceding the timestamp recorded above.

Restore the Test Cluster

You need to restore the test cluster to the exact timestamp determined above. Now write a file recovery.conf using that timestamp:
    
    
    standby_mode = on
    recovery_target_timeline = 'latest'
    recovery_target_inclusive = false
    recovery_target_time = '2017-07-18 15:06:19.348'
    restore_command = 'cp /path/to/archive/%f %p'

Use your base backups to recover a new cluster to a lvm volume using this recovery.conf file. After recovering from WAL archives to the designated timestamp, recovery will pause. At this point you want it to stay paused -- do not "resume" recovery. Instead, simply stop the cluster.

Snapshot the Filesystem

You are going to run these tests multiple times. Recovering from a base backup after each test is time-consuming, and we can use filesystem snapshots as a shortcut.

 **Note:** Running a cluster on a filesystem snapshot creates performance overhead that will differ from your production system. If you need the test system to have equal performance to production, then skip the filesystem snapshot and instead take the long slow route of recovering from base backups after each test.

More typically, it is more important to compare pre- and post- deployment performance to each other, not necessarily compare to production performance. The snapshot volume only needs to be large enough to hold the changed disk pages that your tests will create. Create the snapshot and mount it with something like this:
    
    
    lvcreate --size 10G --snapshot --name pg_testing_snapshot /dev/vg1/existing_cluster_here
    mount /dev/vg1/pg_testing_snapshot /mnt/pg_testing
    
    

Later, pgreplay is going to make lots of connections with usernames from production. You need to set up some loose authentication configurations for that in pg_hba.conf, such as:
    
    
    local      all      all     trust

Start up the cluster whenever you are ready. It will recover to point it time configured before. Promote the cluster with "select pg_xlog_replay_resume()". Check the logs to confirm operation.

Run Workload Test with pgreplay

pgreplay is simple to use. It's also simple to install. If you are using the pgdg repos, just "yum install pgreplay" or "apt-get install pgreplay". pgreplay can read raw log files but you can first test the log file for pgreplay-readiness and simultaneously convert it to binary "replay" format that needs less parsing by pgreplay:
    
    
    pgreplay -f -c -o biglog.pgreplay biglog.csv

Then start your test: execute pgreplay, passing it the "replay" file. Your cluster will start processing sql just like the production system did earlier:
    
    
    pgreplay -r biglog.pgreplay

Rollback the Tests: Drop the lvm Snapshot

Perform any other tests you want on the cluster. When you are done with your test, you can drop the snapshot and start over.

 ** _Caution:_** all data in the snapshot will be lost, ie. you will have just the filesystem that it was snapshot from. Copy any notes, log files, scripts etcetera elsewhere if you want them saved.

Stop the cluster, then:
    
    
    umount /dev/vg1/pg_testing_snapshot
    lvremove /dev/vg1/pg_testing_snapshot

From here, to start with a new test, go back to step "Snapshot the Filesystem". Repeat until everything is just right!

---
[View this page online](https://www.commandprompt.com/blog/postgres-load-testing-pgreplay/)

---

# Postgres v10: An Amplified version of PostgreSQL at VanDev and Vancouver Postgres tonight!

> If you are looking for all the skinny on Postgres v10, I have just the meetup for you. I will be giving my presentation: Postgres V10: An Amplified version of …

If you are looking for all the skinny on Postgres v10, I have just the meetup for you. I will be giving my presentation: Postgres V10: An Amplified version of PostgreSQL tonight at a joint meeting of Vancouver Developers Network and Vancouver Postgres Meetup. Be there or be square.

In this presentation I go over all the major features in Postgres v10 including but not limited to:

  1. BigData
  2. Replication and Scaling
  3. Administration
  4. SQL Features
  5. XML and JSON



Join the meetups, its fun and will make you a better human.

  * [Vancouver Postgres Meetup](<https://www.meetup.com/Vancouver-Postgres-Database-Meetup/>)
  * [Vancouver Developers Meetup](<https://www.meetup.com/VanDev/>)

---
[View this page online](https://www.commandprompt.com/blog/postgres_v10_an_amplified_Version_of_postgresql_at_vandev_and_vancouver_postgres/)

---

# Announce: Denver Postgres User Group

> After much deliberation with the CMD community team we have launched the Denver Postgres User Group! We hope that our community in Denver, Boulder, and Colorad…

After much deliberation with the CMD community team we have launched the [Denver Postgres User Group](<https://www.meetup.com/meetup-group-DTAyXMgo/>)! We hope that our community in Denver, Boulder, and Colorado Springs will join us at upcoming events and submit content. It has been a long time since we have had an active Denver group and Denver is a hot bed for Postgres external development. Our first meeting will be announced soon and should be expected in October. Have ideas on facilities or content? Please contact us on the meetup page. We would love to see 3 - 4 meetings before [PGConf US National](<https://pgconf.us/conferences/National2018>)!

---
[View this page online](https://www.commandprompt.com/blog/postgres_denver_user_group/)

---

# Postgres deferred PRIMARY KEYS, a hidden gem

> Oracle 7.3 supports it!That is how this all started. A gentleman tweeted about a Postgres limitation that Oracle has not had since at least since Oracle 7.3. T…

## Oracle 7.3 supports it!

That is how this all started. A gentleman tweeted about a [Postgres limitation that Oracle has not had since at least since Oracle 7.3](<https://twitter.com/FranckPachot/status/888867529954820097>). 

## The problem

As you can see in the tweet, Postgres by default will not defer a PRIMARY KEY check. Without the check being deferred the following will not work:
    
    
    postgres=# select * from demo;
     id  
    ----
      1
      2
     (2 rows)
    postgres=# alter table demo add primary key(id);   
    ALTER TABLE
     postgres=# begin;
     BEGIN
     postgres=# update demo set id=id-1;
     UPDATE 2
     postgres=# update demo set id=id+1;
     ERROR:  duplicate key value violates unique constraint "demo_pkey"
     DETAIL:  Key (id)=(1) already exists.
    
    

## 

## The solution

The solution, as mentioned, is to use a [DEFERRABLE PRIMARY KEY](<https://www.postgresql.org/docs/9.2/static/sql-set-constraints.html>). A feature that Postgres has had since version 9.0 (7 years).
    
    
    create table demo (id int primary key deferrable initially deferred);
     CREATE TABLE
    postgres=# insert into demo values (1),(2);  
    INSERT 0 2
     postgres=# select * from demo;
     id  
    ----
      1
      2
    (2 rows)
    
    postgres=# begin;
     BEGIN
     postgres=# update demo set id=id-1;  
    UPDATE 2
     postgres=# update demo set id=id+1;
     UPDATE 2
     postgres=# commit;
     COMMIT
     

This is why Jim Mlodgenski's number one piece of advice for Oracle people is: Stop thinking like Oracle people; Postgres isn't Oracle. You are going to have to adjust your thinking on many things, from partitioning, hints, shared_buffers and redo logs. That doesn't mean Postgres can't handle your workload. It means you have to modify your application to work with Postgres, the way Postgres works.

---
[View this page online](https://www.commandprompt.com/blog/postgres_deferred_primary_keys/)

---

# Postgres autovacuum, bloat and tpc-c style workloads

> 
For most workloads the Postgres Autovacuum daemon works just fine. You go about your day with 3 workers that wake up once a minute to make sure that everythi…

![](../../../../uploads/images/vacuum.png)

For most workloads the Postgres Autovacuum daemon works just fine. You go about your day with 3 workers that wake up once a minute to make sure that everything is nice and tidy. If things are dirty enough (around 10%) then one of the workers gets in gear and cleans things up. Unfortunately, if you have an inverted load from the norm, Autovacuum may not be able to keep up and you will suffer increased fragmentation and bloat.

## The norm

The most common workload for Postgres (especially web based apps) includes many reads and some writes. It is usually somewhere around 75-95% reads and 5-25% writes. Assuming an average database, Autovacuum will keep up just fine and with tuning will continue to perform well as a whole even as your TPS increases.

## When Autovacuum fails

A couple of weeks ago I was teaching at [PGConf US Local: Philly](<https://www.pgconf.us/conferences/Philly2017>) on Postgres Performance and Maintenance. While discussing various nuances of Postgres life with Jim Mlodgenski and Jan Wieck (He's the guy that created [Slony,](<http://www.slony.info/>) [PL/TCL](<https://www.postgresql.org/docs/9.6/static/pltcl.html>) and [TOAST](<https://www.postgresql.org/docs/9.6/static/storage-toast.html>)), the issue of Autovacuum not keeping up arose. Under Jan's tests using [BenchmarkSQL](<https://bitbucket.org/openscg/benchmarksql>) he was not able to get Postgres to run under a heavy write/update load for much longer than a week.

# DO NOT FREAK OUT

![](../../../../uploads/images/kevin_marc_face.jpg)

 

Remember that this problem is obscure, special case, and you likely will not run into it. That does not mean it isn't good to talk about and see if we can make it better (which is exactly what is happening [here](<https://www.postgresql.org/message-id/0265f9e2-3e32-e67d-f106-8abde596c0e4%40commandprompt.com>), [here](<https://www.postgresql.org/message-id/8737e9bddb82501da1134f021bf4929a%40postgrespro.ru>) and [here](<https://pgeoghegan.blogspot.com/2017/07/postgresql-index-bloat-microscope.html>)). I expect that some changes (minor) will make it into v10 and of course work will commence for v11. This is one of the great things about the Postgres release cycle; you are not going to have to wait for three years to see improvement. We generally release yearly (give or take) and v10 is set to hit soon.

## Prove it!

I was incredulous at Jan's claims. We have systems that have been running non-stop except for dot release updates for years. How could a system that runs for years without intervention be subject to such an unfortunate limitation? The answer to that question is the workload. As mentioned previously most workloads do not fit into this category. I set out to do some testing because I had not seen anything over at [.Org](<http://www.postgresql.org/>) regarding this problem.

### The machine

  * GCE
  * 16vCPU
  * 59G Memory
  * 10G SSD (/)
  * 500G SSD /srv/main/9.6 (PGDATA) : 240MB Sustained with 15k IOPS
  * Yes, we really got 240MB sustained performance 



### Postgres configuration

General

| 

Autovacuum  
  
---|---  
  
max_connections: 1000 

shared_buffers: 32G 

work_mem: 32M

maintenance_work_mem: 2G

effective_io_concurrency: 1 

synchronous_commit: off

checkpoint_timeout: 1d

max_wal_size: 10GB

random_page_cost: 1

effective_cache_size: 32GB

| 

Autovacuum: on

Autovacuum_analyze_scale_factor: 0.1

Autovacuum_analyze_threshold: 50

Autovacuum_freeze_max_age: 200000000

Autovacuum_max_workers: 12

Autovacuum_multixact_freeze_max_age: 400000000

Autovacuum_naptime: 10

Autovacuum_vacuum_cost_delay: 0

Autovacuum_vacuum_cost_limit: 5000

Autovacuum_vacuum_scale_factor: 0.1

Autovacuum_vacuum_threshold: 50

Autovacuum_work_mem: -1

Log_autovacuum_min_duration: -1

Max_wal_size: 640

Checkpoint_timeout: 86400

Checkpoint_completion_target: 0.5   
  
 

### Benchmark configuration

We used the defaults for weight but ran with 500 warehouses, 128 terminals (connections), and a run time of six hours per test. Here are the results:

![](../../../../uploads/images/test_tps.png)

As you can see with each subsequent test the TPS went down significantly and there is a direct correlation with the TPS drop and the size of the database as it grows (illustrated in the next graph):

![](../../../../uploads/images/diskspace_growth.png)

The drop of disk size after test six is due to a **vacuum full** being performed when the tests were complete. This shows not only the growth of the database but how much of the database was bloat. The next graphs show where the bloat is. The primary culprit is the following table and index:

Relation

| 

Size at test six

| 

After VACUUM FULL  
  
---|---|---  
  
bmsql_order_line

| 

148GB

| 

118GB  
  
bmsql_order_line_pkey

| 

48GB

| 

27GB  
  
  
Although the bloat on bmsql_order_line isn't egregious the bloat on the pkey is rather significant. There is another item at play here, fragmentation within the table, but that is going to have to wait for another post. 

I was reminded to never assume a result but instead prove the result. I never considered that this could be a problem because our clients generally do not have this type of workload but these workloads are not unheard of. It is TPC-C and places like Amazon or Staples could have workloads like this. 

I also learned that GCE really can push 240MB/s on their SSD volumes and it is beautiful. I still remember when we needed [50 spindles to get that level of performance.](<../../../../blog/is_that_performance_i_smell_ext2_vs_ext3_on_50_spindles_testing_for_postgresql/>)

---
[View this page online](https://www.commandprompt.com/blog/postgres_autovacuum_bloat_tpc-c/)

---

# Where is the Postgres community?

> 
A recent poll was conducted @amplifypostgres to determine where the Postgres community should have its interactive communication. Options included were Googl…

![](../../../../media/images/featured_blog/crowd-296520_960_720.png)

A recent poll was conducted [@amplifypostgres](<https://twitter.com/amplifypostgres>) to determine where the Postgres community should have its interactive communication. Options included were Google Hangouts, Slack, [Reddit](<https://www.reddit.com/r/amplifypostgres>) or "Other". 

The results were not surprising, with Google Hangouts beating Slack with 157 votes cast. There were also notable mentions of IRC, and Gitter. A couple of long time Postgresql.Org members asked the inevitable, "What is wrong with IRC?" Of course there is nothing wrong with IRC but when you tell many community users to use IRC, the most common response is "IRWhat?" which is either a sign of disdain or ignorance depending on the user.

The problem and what is driving this post was an additional comment made by a long time community member -- that we need to educate the users because the community (Postgresql) is on IRC and mailing lists.

![](../../../../uploads/images/ccsg-edsg-04.jpg)

**This is not IRC**

This line of thinking ignores the reality that many community spaces have been built up over the years. If IRC and mailing lists were sufficient for the needs of the community, then these additional community silos wouldn't thrive. They are active and serve the needs of many communities that are linked but not directly integrated into Postgresql.Org. 

**Community Space**

| 

**Members**  
  
---|---  
  
[@amplifypostgres](<https://twitter.com/amplifypostgres>)

| 

14000+  
  
[Postgres Professional](<https://www.linkedin.com/groups/51776>)

| 

9400+  
  
[G+ PostgreSQL](<https://plus.google.com/u/2/communities/116371937400081693174>)

| 

9100+  
  
[r/postgresql](<https://www.reddit.com/r/PostgreSQL/>)

| 

5100+  
  
[Facebook Postgresql Server](<https://www.facebook.com/groups/postgres/>)

| 

4500+  
  
Facebook [PostgreSQL в России](<https://www.facebook.com/groups/postgresql/?ref=group_header>)

| 

2500+  
  
[Slack Postgres](<https://postgres-slack.herokuapp.com/>)

| 

1100+  
  
**Notable Mention**  
  
StackOverflow #postgresql

| 

70,000+ Questions  
  
This summary doesn't take into account the many other Postgres communities. The NYCPUG has over 2300 users, yet I guarantee you that at most a small two digit percentage participate on "The mailing lists" or "IRC". Let us also not forget some of the largest Postgres communities in the world such as Japan and Asia. Very few of them participate on the .Org lists, but that doesn't mean they aren't part of the community.

If as a community our goal is not only to build software but also to build people then we have to let go of our "old man, get off my lawn" tendencies and embrace new forms of communication and collaboration. I am a bonafide master of "Good lord, why do I have to use Slack" but guess what? I use Slack. Why? Because that is where you reach and engage a certain and significant number of community members.

## **If we don 't build people, there will be no people to build the software.**

---
[View this page online](https://www.commandprompt.com/blog/where_is_the_postgres_community/)

---

# Why Postgres? (How did I get here?)

> You may ask yourself, how did I get here?  - David ByrneThe journey to this place in my professional career as the newly hired Director of Business Development…

**_You may ask yourself, how did I get here? - David Byrne_**

  
The journey to this place in my professional career as the newly hired Director of Business Development for Command Prompt, Inc. is a long and winding one, and so i'd like to share a couple of stories to enlighten curious folks:

>  ** _“Why Postgres?!”_**

Last September the fledgling consulting firm that I was handling sales and business development for was shuttering, and my best bud and business colleague Jim Nasby and I were on the market for job opportunities. Word had gotten out, and I had an introductory call with a potential employer who asked me this question. An advantage of my former position at Blue Treble was the ability to engage regularly in the PostgreSQL community.

I’d been introduced to PostgreSQL long ago by Nasby, as he’s been at the core of my circle of friends who’ve contributed to my “geek by association” status over the years. Most of them had gotten to know each other as staff and contributors to [distributed.net](<http://www.distributed.net>), the Internet’s first general-purpose distributed computing project.  
  
Half-listening to highly technical discussions over beers at our local favorite watering hole, I absorbed a wealth of knowledge of distributed computing and database architecture through osmosis. I’d join in heated debates, adding my own insight from evolutionary theories that could be applied to software ecosystems.

I was highly active in our #alg IRC channel, where I was encouraged to get out of Windows. Arguments would ensue over Unix versus Linux, and whether to use Debian, Ubuntu, or RedHat.

>  ** _Why Postgres? It’s robust, scalable, high performance. And I’m a data geek!_**

I wasn’t a stranger to databases when I met my distributed.net friends over 13 years ago. I had taken computer math and science courses in high school in the late 70s. My uncle Ronnie who’d worked at Sperry Univac -- and later had his own computer consulting company for over 20 years -- encouraged me to take computer courses at Houston Area League of PC Users, Inc. (HAL-PC) where he was an instructor. I took courses in MS-DOS, Lotus 1-2-3 and dBase III at HAL-PC in the mid-80s.

Fast-forward to December 2001, when I began working at a state regulatory agency as a drinking water quality specialist. I spent hours with a senior team member, as she taught me how to build queries and create reports in Microsoft Access 97.  
  
For ten years I managed several programs related to the Safe Drinking Water Act and its amendments, with inventory and water quality data residing in various databases. Compliance determination required importing data from the labs into our chemdata database, and then running queries and reports that would output non-compliance letters to the regulated community of public water systems.

>  ** _“But why Data? Why are YOU a geek about data?!”_**

I touched massive amounts of data in that job -- every. single. day. Managing multiple programs wasn’t easy, but not because of the steep learning curve of the RDBMS when I first started -- I absorbed and implemented what I learned from courses that included application development, and "dabbled" with VBA and SQL.  
  
The trouble was with the legacy systems -- historical data in a FoxPro table, with schema that didn’t map to the new data system. Why does it appear that hundreds of groundwater wells drilled on January 1, 1913, in the state of Texas' well inventory?!  
  
Because the drill date could not be left as null, and that date was selected as the placeholder. The significance of this date is that 1913 is the year that sanitary engineer Vic Ehlers introduced chlorination to the state of Texas waters, eradicating typhoid and cholera and decreasing mortality from waterborne diseases.

Data silos existed, because at some point a data project had been spun up and contracted out by another area of the division. Again no standardization of the schema across organizational units.  
  
Worse yet, this fragmented pattern and impact wasn’t only an internal or agency issue – data was required to be migrated quarterly into the EPA’s federal data warehouse, the Safe Drinking Water Information System (SDWIS). I didn’t envy our solo data administrator’s job. It was enough for me to handle the monthly lab data import, nervous as we hit over 1M records in a Microsoft Access database table.

Oh, I forgot to mention – all of this data management was over the network, as databases were being run over a virtual machine.

 ** _"But... your background is water and biology??"_**

The challenges of compliance determination and ensuring QA/QC of sampling and data analysis in my former role as a drinking water program manager taught me to appreciate a robust data platform.  
  
The influence of my education in ecology, evolution, and conservation biology should be a no brainer for any PostgreSQL developer or long-term user. Applying rapid bioassessment methodology for rivers and streams including Devils River (seen above) as a biology undergraduate, as well as later as an environmental field technician for the City of Austin's Watershed Protection Department taught me the value of cost-effective approachies to identify water quality problems, rank sites and monitor trends.   
These experiences fuel my great admiration for the evolution and efficiencies of PostgreSQL, and the adaptations and new features that lend to its robustness, performance, and more.

Needless to say, the above-quoted dialogue was a non-starter for that company, but I believe that I've successfully evolved as a PostgreSQL professional, and navigated into a harbor where I am firmly anchored. I'm excited for the role that I am fulfilling at Command Prompt as Director of Business Development, and look forward to establishing new and fostering existing relationships with both our clients and the PostgreSQL community.

---
[View this page online](https://www.commandprompt.com/blog/introdebracerda/)

---

# PostgreSQL: The Center of your Data Universe @ Datalayer Conference

> You should always be careful of what you ask for. A couple of months ago while I was feeling particularly brave, I submitted to present at the DataLayer Confer…

You should always be careful of what you ask for. A couple of months ago while I was feeling particularly brave, I submitted to present at the DataLayer Conference. The next thing I knew, I was speaking at the [DataLayer Conference](<https://datalayer.com> "DataLayer Conference"). The conference takes place in Austin on May 17th. Conferences like this one are an awesome channel for PostgreSQL advocacy. Of course I am partial to [PgConf US](<https://pgconf.us> "PgConf US") but a conference such as DataLayer allows us to reach people who may be using one of those "other" databases. 

Here is the synopsis of the presentation I will be giving:

**PostgreSQL: The Center of Your Data Universe**

Although there are still battles to be fought, the war has already been won. Find out how PostgreSQL answers all of your data layer needs. PostgreSQL is a one of the longest standing Open Source Database systems with legions of users leading the way to a sane, productive and performance driven data layer. This presentation will cover an overview of PostgreSQL technologies including:

  * NoSQL capabilities
  * Relational capabilities
  * Replication & High Availability
  * Features you can't believe you lived without
  * Community



If you feel like going, you can use the code JDROCKS (I promise, I didn't pick it) for a 15% discount. Let's have a large PostgreSQL contigent at the conference and show those "other" technologies what real community feels like!

---
[View this page online](https://www.commandprompt.com/blog/postgresql_the_center_of_your_data_universe/)

---

# Generate Phone Calls For Redmine Emergency Tickets Using Twilio

> We use Redmine here at CMD for all our project management needs. In fact, this Open Source solution is at the heart of our day-to-day operations. Over the time…

We use Redmine here at CMD for all our project management needs. In fact, this Open Source solution is at the heart of our day-to-day operations. Over the time, [we have made a number of contiributions to the project](<https://github.com/commandprompt?utf8=%E2%9C%93&tab=repositories&q=redmine&type=&language=>) and extended, or modified, Redmine's behavior to suit our needs.

For example, one of the things we did was integrate Zabbix-based PostgreSQL monitoring system with Redmine. This allows us to keep track of all monitoring alerts in a centrally managed place, turn them into actionable tickets when necessary, discuss and work out specific problems either internally or with a customer.

Per our [SLA](<../../../../support/>), we're often expected to respond in a swift fashion to emergencies that do occur from time to time. In most cases our systems work very reliably and an e-mail notification about a Disaster-level monitoring event reaches one of our employees quickly enough, which allows us to provide service that meets the requirements outlined in the SLA.

However, we felt that we also needed to make sure that each Disaster-level monitoring event results in a phone call. Just in case e-mail fails.

As a matter of fact, same applies to emergency Redmine tickets. These tickets are basically normal tickets that were assigned a custom "Emergency (Critical)" priority. Either when a new ticket was created or when an existing ticket was promoted to the "Emergency (Critical)" priority, a way for our customers to let us know that they're in an urgent need of our help.

We tried a couple of approaches and eventually ended up using Twilio, which has worked for us really well so far.

[Twilio](<https://www.twilio.com/>) is a cloud communications platform. A programmable phone, if you will. Something that we use to call our on-call employees and inform them about an emergency.

In this post we wanted to show you how you could use Twilio to generate phone calls for Redmine emergency tickets.

## procmail-twilio Overview

As an example, we'll take a look at a solution we created and use ourselves here at CMD.

It is called procmail-twilio and is basically a combination of Redmine, procmail, a simple BASH script that calls another Python script that leverages [Twilio Python REST API Client](<https://www.twilio.com/docs/api>) and a HTTP server.

It all works together rather simply.

  * All e-mail generated by Redmine goes through a procmail filter
  * which looks for an Emergency priority ticket
  * and, when found, parses it
  * and extracts key information about the ticket: ticket number, project name, who created or updated the ticket,
  * generates a TwiML file based on the extracted information,
  * executes a BASH script that initializes a Python virtual environment
  * and then runs a Python script that makes an actual call.
  * The HTTP server is required to serve the TwiML file to Twilio via a REST call.



That's it in a nutshell.

Now, let's take a closer look at each stage of this process to get a better idea of how it really works.

## Redmine

Assuming Redmine is already configured to deliver e-mail notifications for all ticket updates, all you need is a dedicated Redmine user, e.g. procmail-twilio@yourdomain.com, with a corresponding e-mail account (in this example procmail-twilio) on a server where all Redmine e-mail notifications are delivered.

This user must be a member of a group that gives it access to all Redmine projects. This ensures that the user receives all e-mail notifications generated by Redmine ticket updates in any of the existing projects.

## procmail

In procmail-twilio user's home directory on your e-mail server, there will be a ~/procmailrc file with three recipes that look for two distinct types of Emergency priority tickets.

First, existing tickets that were escalated to Emergency priority:
    
    
    :0B
    * ^Priority changed from [A-Za-z]* to Emergency \(Critical\)$
    {
      :0B
      {
       WHO=`sed -e '1,/^$/ d' | grep -m 1 "Issue \#[0-9]* has been \(updated\|reported\) by" | cut -d " " -f 7,8 | sed -e "s:\.$::g"`
       PROJECT=`formail -xX-Redmine-Project: | sed -e 's/^\s*//g' -e 's/\s*$//g'`
       ISSUE=`sed -e '1,/^$/ d' | grep -m 1 "Issue \#[0-9]* has been \(updated\|reported\) by" | cut -d " " -f 2 | sed -e "s:#::g" -e "s/./& /g;s/ $//"`
       GOODLUCK=`shuf -n 1 ${GOODLUCKFILE}`
       TWLMSG="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Response>\n\t<Say voice=\"woman\" language=\"en\" loop=\"3\">Hello! Issue number, ${ISSUE}, has just been escalated to Emergency status, by user, ${WHO}. Please, respond immediately. This is issue, number, ${ISSUE}. Project is, ${PROJECT}. The contact is, ${WHO}. Oh, and one more thing... ${GOODLUCK}!</Say>\n</Response>\n"
       :0w:procmail-twilio-existing.lock
       | echo "${TWLMSG}" > "${TWLMSGFILE}" && bash ${CALLSCRIPT}
      }
    }

Then, new Emergency tickets:
    
    
    :0H
    * ^Subject:.*\(New\)
    {
      :0BA
      * ^\* Priority: Emergency \(Critical\)$
      {
        WHO=`sed -e '1,/^$/ d' | grep -m 1 "Issue \#[0-9]* has been \(updated\|reported\) by" | cut -d " " -f 7,8 | sed -e "s:\.$::g"`
        PROJECT=`formail -xX-Redmine-Project: | sed -e 's/^\s*//g' -e 's/\s*$//g'`
        ISSUE=`sed -e '1,/^$/ d' | grep -m 1 "Issue \#[0-9]* has been \(updated\|reported\) by" | cut -d " " -f 2 | sed -e "s:#::g" -e "s/./& /g;s/ $//"`
        GOODLUCK=`shuf -n 1 ${GOODLUCKFILE}`
        TWLMSG="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Response>\n\t<Say voice=\"woman\" language=\"en\" loop=\"3\">Hello! New Emergency issue, number, ${ISSUE}, has just been reported, by user, ${WHO}. Please, respond immediately. This is issue, number, ${ISSUE}. Project, ${PROJECT}. The contact is, ${WHO}. Oh, and one more thing...  ${GOODLUCK}!</Say>\n</Response>\n"
        :0w:procmail-twilio-new.lock
        | echo "${TWLMSG}" > "${TWLMSGFILE}" && bash ${CALLSCRIPT}
      }
    }

This particular order is important.

When an Emergency ticket e-mail notification is encountered, it is parsed and the most relevant information is extracted, which then is used to generate a [TwiML](<https://www.twilio.com/docs/api/twiml>) file - essentially a voice message that is played during a call.

Otherwise, e-mail is discarded by redirecting it to /dev/null.
    
    
    :0
    /dev/null

This procmail recipe file won't keep any copies of e-mail on disk. However, by default it will log its actions to a logs/procmail.log file. It is optional and can be disabled if desired. Just comment out LOGFILE= variable in ~/.procmailrc file.

## Twilio Call Scripts

procmail will eventually execute a simple BASH script procmail-twilio.bash that initiates a Python virtual environment and runs procmail-twilio.py:
    
    
    #!/bin/bash
    
    set -e
    
    twldir="{{virtualenv_path}}"
    phones="{{phonesdir}}/phones.sh"
    
    source "$phones"
    
    # Change directory to our python virtualenv
    cd $twldir
    
    # Activate the virtualenv
    source bin/activate
    
    # Execute the python script that makes the call
    python procmail-twilio.py $oncall $backup $tertiary

In our setup, the BASH script relies on phones.sh file to look up on-call, backup and tertiary numbers. It is part of a larger Twilio-based solution that we also developed, and you don't really have to use it. You could use a similar file, if you prefer to keep phone numbers separate from the script, or you could define those numbers directly in procmail-twilio.bash:
    
    
    #!/bin/bash
    
    set -e
    
    twldir="{{virtualenv_path}}"
    
    oncall="+1xxxxxxxxxx"
    backup="+1xxxxxxxxxx"
    tertiary="+1xxxxxxxxxx"
    
    # Change directory to our python virtualenv
    cd $twldir
    
    # Activate the virtualenv
    source bin/activate
    
    # Execute the python script that makes the call
    python procmail-twilio.py $oncall $backup $tertiary

The procmail-twilio.py script makes an actual call, handles call tree logic, call status and provides simple logging of call events. We make several attempts to reach primary on-call and if that fails, we call backup on-call and if that somehow falls too, the call goes out to a third person, usually our boss. We wait 5 minutes between initiating a call and polling for a call status.

Consider this abridged version of the script:
    
    
    #!/usr/bin/python
            
    # Tested with Python 2.7
    # Requires TwilioRestClient
    
    # Download the library from twilio.com/docs/libraries
    from twilio.rest import TwilioRestClient
    import sys
    import time     
    import datetime 
    
    # Get these credentials from http://twilio.com/user/account
    account_sid = "BZ62270014z14e1354aej1d66d5ea932v6"
    auth_token = "57f3e13321841e31cefd4c137f5baeff1"
    # Twilio phone number
    from_="+1xxxxxxxxxx"
    # oncall, backup and tertiary call recipient numbers
    # are passed down as arguments from the calling BASH 
    # script.       
    oncall=sys.argv[1]
    backup=sys.argv[2]
    tertiary=sys.argv[3]
    
    ...
    
    # Makes the call and returns session id
    def makecall(to_num, from_num) :
        try:        
            call = client.calls.create(to=to_num, from_=from_num,
                                       url="https://yourdomain.com/procmail-twilio/twiml.html")
            return call.sid
        
        except TwilioRestException as e:
            logerror(e)
    
    # Uses session id returned by makecall() to obtain call status
    def callstatus(sid) :
        try:
            callinfo = client.calls.get(sid)
            return callinfo.status
            
        except TwilioRestException as e:
            logerror(e)
    
    ...
    
    #
    # Actual program starts here
    #
    
    client = TwilioRestClient(account_sid, auth_token)
    
    count = 0
    status = "nothing"
    
    while count < 7 :
    
            count = count + 1
    
            if status in ['completed', 'in-progress'] :
    
                    break
    
            if count == 1 :            
                    to=oncall
                    sid = makecall(to, from_)
                    time.sleep(300)
                    status = callstatus(sid)
                    logcall(sid, count, status, to)
    
    ...
    
            elif count == 4 :
                    to=backup
                    sid = makecall(to, from_)
                    time.sleep(300)
                    status = callstatus(sid)
                    logcall(sid, count, status, to)
    
    ...
    
            elif count == 7 :
                    to=tertiary
                    sid = makecall(to, from_)
                    time.sleep(300)
                    status = callstatus(sid)
                    logcall(sid, count, status, to)
    
            else :
                    logerror("Internal error. Check " + sys.argv[0])

Of a particular interest is the makecall() function:
    
    
    call = client.calls.create(to=to_num, from_=from_num,
                                       url="https://yourdomain.com/procmail-twilio/twiml.html")

The url= parameter is what tells Twilio where to look for the TwiML file. This is where you need a HTTP server.

## HTTP Server

We use Apache, but it could be nginx or some other HTTP server. Requirements are basic. The purpose of having a HTTP server is as simple as to serve the TwiML file to Twilio via a HTTP(S) URL. It essentially comes down to exposing the TwiML file via HTTP. No different than any other normal file.

Apache runs on the same server where Redmine e-mail notificaitons are delivered and processed by procmail.

procmail-twilio is meant to be installed and run as an unprivileged system user. The TwiML file is generated in a directory outside of Apache's DocumentRoot to avoid giving procmail-twilio system user extra permissions to manipulate files in Apache's DocumentRoot. Instead, we use a symlink that can be located in an arbitrary path of the DocumentRoot.

For example, if your TwiML file is /home/procmail-twilio/prctwl-data/twiml.html, Apache DocumentRoot is /srv/vhosts/main/ and you want the TwiML file to be accessible at https://yourdomain.com/procmail-twilio/twiml.html you need to create a symlink /srv/vhosts/main/procmail-twilio/twiml.html that points to /home/procmail-twilio/prctwl-data/twiml.html:
    
    
    admin@http:~$ sudo mkdir /srv/vhosts/main/procmail-twilio
    admin@http:~$ sudo ln -s /home/procmail-twilio/prctwl-data/twiml.html /srv/vhosts/main/procmail-twilio/twiml.html

So, when the makecall() initiates a call basically what happens, is that it tells Twilio to open url=, which is expected to be served by your HTTP server.

## Log Files

By default, ~/.procmailrc file is configured to log all its actions in logs/procmail.log file.

Typically, you will see two types of log entries. This one tells us that an e-mail was discarded, because it doesn't appear to be a an Emergency priority ticket:
    
    
    From projectid@yourdomain.com Sat Apr 1 13:36:48 2017  
     Subject: [Project Name - Support #82795] Restore/Generate Monthly Reports  
     Folder: /dev/null

In this example we can see that a new Emergency ticket was found, a TwiML file was generated and ${CALLSCRIPT} was run to make a call:
    
    
    From projectid@yourdomain.com Mon Mar 27 09:36:16 2017  
     Subject: [Project Name - Support #86855] (New) Our database is down  
     Folder: echo "${TWLMSG}" > "${TWLMSGFILE}" && bash ${CALLSCRIPT} 3558

Each call attempt and its status is logged in a log file logs/procmail-twilio-calls.log:
    
    
    2017-03-27 09:41:19.145112 Session ID: ZBb7xx16d4E1295ctf84e5b25121ea46kk, Call attempt number: 1, Call status: completed, Call recipient: +1**********.

This helps keep a clear history of all calls and whether they were successfull or not.

All log files are managed by logrotate, so they shouldn't take up too much space on disk.

## Download and Install procmail-twilio

If you want to give it a try, or build on top of it something else, procmail-twilio can be [downloaded](<https://github.com/commandprompt/procmail-twilio>) from CMD's github repository as an Ansible playbook.

To install just run this command:
    
    
    admin@workstation:~/playbooks$ git clone https://github.com/commandprompt/procmail-twilio.git
    admin@workstation:~/playbooks$ cd procmail-twilio
    admin@workstation:~/playbooks/procmail-twilio$ ansible-playbook run.yml --ask-vault-pass -K

Before you do so, however, you need to configure your vars file and decide if you need to make changes to any of the template files, etc. This example also assumes the vars file was first encrypted with ansible-vault command (it contains your Twilio account username and password):
    
    
    admin@workstation:~/playbooks/procmail-twilio$ ansible-vault encrypt roles/procmail-twilio/vars/main.yml

You may also want to modify some template files but you don't really have to.

## In Place of Conclusion

An important point to keep in mind is that Redmine here is just an example. It could be JIRA, BugZilla or something else. Even your personal GMail account. Just replace procmail recipes with your own and you're good to go.

And hey, if you use procmail-twilio or used it to build something else, let us know.

We'd love to hear your story.

---
[View this page online](https://www.commandprompt.com/blog/generate-phone-calls-for-redmine-emergency-tickets-using-twilio/)

---

# Indirect Advocacy

> Last week I spoke at the Bellingham Young Professional Group on starting and running a business. It was a well attended presentation. I was nervous at first be…

Last week I spoke at the Bellingham Young Professional Group on starting and running a business. It was a well attended presentation. I was nervous at first because although I do a lot of public speaking, I usually speak to technical people. This was a wholly different crowd and I was pulling from a different set of expertise. The crowd was largely under 30 and wanting to start a business of some sort. The presentation went over well and by far the most common feedback was, "I didn't even consider that, thank you". It is a good feeling to know you are helping people.

**Indirect Advocacy:  not directly caused by a recommendation of a particular cause**

By stepping out of my comfort zone I was able to help people not only with business but also help PostgreSQL. As PostgreSQL (and Open Source) is what I do, presenting on a topic that is not directly related to PostgreSQL allows me to advocate for PostgreSQL and Open Source in new ways. Here are my slides and I will be posting more on Indirect Advocacy in the future.

---
[View this page online](https://www.commandprompt.com/blog/indirect_advocacy/)

---

# PostgreSQL for Oracle people

> Below is the video of the webinar I did recently on PostgreSQL and Oracle. This webinar went very well. This is the first time I had ever performed a webinar t…

Below is the video of the webinar I did recently on PostgreSQL and Oracle. This webinar went very well. This is the first time I had ever performed a webinar that I recall. It was an interesting experience.  

**PostgreSQL for Oracle Developers and DBA's**

 

If you would like more information on this topic or any other topic surrounding PostgreSQL and Open Source, [don't hesitate to contact us](<../../../../contact> "contact us").

---
[View this page online](https://www.commandprompt.com/blog/postgresql_for_oracle_people/)

---

# Do not buy the closed source lie of free videos

> There is a nice lie out there. A lot of people want to believe it. They think by believing this lie it will somehow increase something for them. In some ways t…

There is a nice lie out there. A lot of people want to believe it. They think by believing this lie it will somehow increase something for them. In some ways that is true. If you want what you are doing to be about you. If you are a believer in Open Source, it isn't about you. It is about the community and bettering that community as a whole.

**If we provide the videos of our sessions for free, you won't attend the conference.**

The PgConf US conference grows every year and guess what, they provide their videos for free.

**If you pay for the conference, we will provide the videos for free.**

LinuxFest Northwest which is larger than PgConf US, PgConf EU, Postgres Vision and Char(16) combined also grows every year and provides their videos for free. It is also free to attend.

The next time someone says, "You won't show if we give you videos" or "Maybe if you paid to come", I recommend you attend an Open Source conference that follows Open Source values. 

That isn't to say that it isn't a conference's right to not give free videos. Of course it is. It is also your right to only attend conferences about Open Source that embrace what Open Source is about. There is a reason I only speak at non-profit or community run conferences. I want to contribute to the greater good. That is also the reason why Command Prompt only sponsors community run or non-profit conferences.

That is also not to say that for-profit conferences about Open Source are bad. They aren't and more power to you if you can find a way to make money off a conference about Open Source. It is to say that Open Source conferences should follow Open Source values. If you are going to record and you are an Open Source conference, give the recording away.  

Merry Christmas & Tally Ho!

---
[View this page online](https://www.commandprompt.com/blog/do_not_buy_the_closed_source_lies/)

---

# What should I submit to PgConf US 2017?

> From the title, that is the question. This is the last week of the PgConf US 2017 CFP (you can submit here: http://www.pgconf.us/2017/submit/) and I have no id…

From the title, that is the question. This is the last week of the PgConf US 2017 CFP (you can submit here: <http://www.pgconf.us/2017/submit/>) and I have no idea what to submit.

I am blessed that my talks are very well attended, the audience is engaged and we all have a good time. Many times laughing at me because I have a hard time staying on one specific topic (especially if someone brings a kid into the room). There is the disclaimer I have to put up on my slides because there are some in the community that can't handle humor or PG-13 content but we must all love our neighbor and enjoy them for who they are. I have more than once seen a community member shaking their head at me (Grant, I am looking at you) but that is part of the fun and part of the show. Let's get everyone loving PostgreSQL. That gets me to my point.

**I have no idea what to submit.**

What would you like to see me speak on?

  * Replication? 
    * What type?
  * Backups? 
    * pg_dump, or binary?
  * Data types?
  * Modeling?
  * Deploying with Kubernetes?
  * What about LXC/LXD?
  * What the PostgreSQL Snap packages are?
  * Bare metal to cloud comparison?
  * The constant nagging issue of no PostgreSQL issue tracker?
  * How Steven Universe uses PostgreSQL? (That's a joke but meant to say... insert anything else here)



You tell me. Help me out here. I want to once again have a standing room only party of community that wants to love and learn about PostgreSQL. I just don't know what people want to hear about this year.

---
[View this page online](https://www.commandprompt.com/blog/what_should_I_submit_to_PgConf_US_2017/)

---

# Install LAPP in Containers

> Install LAPP in Containers(Linux Containers and Linux, Apache, PostgreSQL, PHP)
In this blog post I will detail how to install Apache, PHP, PostgreSQL in Linu…

## Install LAPP in Containers  
(Linux Containers and Linux, Apache, PostgreSQL, PHP)

  
In this blog post I will detail how to install Apache, PHP, PostgreSQL in Linux containers on Ubuntu 16.04 LTS.

  
It can be desirable to isolate certain software from the rest of a system for a variety of reasons. These reasons can range, but one of the most common is security. There are a multitude of methods for isolation ranging from process sandboxing to full hardware virtualization. Regarding the former, we have a tool called chroot.

  
Change root, or chroot for short, has been a UNIX utility for "sandboxing" processes since 1982. Sandboxing is a general term to describe the act of executing processes outside of the root installation. As the name chroot suggests, it is method of changing the root of a process to one other than the originating host system. Chroot-based sandboxing shares the host kernel and related resources and as such if you have UID 0 (root) in a chroot you can access the host. You should keep that in mind as it means it is possible to do things that may be undesirable, such as rebooting the host system, from within a chroot.

  
Taking the idea of a chroot but making it a little bit more secure we enter the arena of Linux containers, or LXC for short. LXC takes a chroot and couples it with kernel cgroups and namespaces. This allows finer control of system resources such as CPU, network, disk, memory, etc.

  
So what we want to gain from all of this is the ability to stick a database in one container and a web server in another all while allowing full interoperability between a web application and the database server.

  
We will begin with an amd64 (x86_64) host system that has Ubuntu 16.04 LTS installed. Once you have your host installation of Ubuntu complete, we need to perform a few maintenance operations.

  
First, we want to make sure everything is up-to-date:
    
    
    sudo apt-get update && sudo apt-get dist-upgrade

  
Next, we will install LXC:
    
    
    sudo apt-get install lxc

  
Now, before we create our containers, we need to modify our LXC configuration to ensure our containers get static IP addresses.

  
First edit /etc/default/lxc-net and uncomment this line:
    
    
    LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

  
Next, create /etc/lxc/dnsmasq.conf with the following contents:
    
    
    dhcp-hostsfile=/etc/lxc/dnsmasq-hosts.conf

  
Then we need to create /etc/lxc/dnsmasq-hosts.conf with this line inside:
    
    
    www,10.0.3.196
    db,10.0.3.143
    

  
To ensure that our changes take affect, we need to restart the lxc-net service:
    
    
    sudo service lxc-net restart

  
Now we can continue and create our containers for our project.

  
Our first container will be for Apache and PHP:
    
    
    sudo lxc-create -t download -n www -- -d ubuntu -r xenial -a amd64

  
Once we have created the container we need to start (run) it:
    
    
    sudo lxc-start -n www

  
To enter the container we can use a command such as:
    
    
    sudo lxc-attach -n www

  
This would be a good time to install Apache and PHP:
    
    
    sudo apt-get install apache php

  
To quit out of the container you may type 'exit' just like you would with a normal login shell.

  
Now that we have a www container, we will create a container for PostgreSQL:
    
    
    sudo lxc-create -t download -n db -- -d ubuntu -r xenial -a amd64

  
Then we will start the container:
    
    
    sudo lxc-start -n db

  
Again, you can enter the container with a similar command:
    
    
    sudo lxc-attach -n db

  
While still in the db container, we will install wget
    
    
    sudo apt-get install wget

  
Next we will add the PostgreSQL package signing key:
    
    
    wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

  
Then we will add the PostgreSQL package repository to our apt sources by inserting "deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main" to a newly created file in /etc/apt/sources.list.d/pgdg.list

  
Now that we have a new repository added, we need to instruct apt to update its local repository information:
    
    
    sudo apt-get update

  
Now we are ready to install PostgreSQL 9.6:
    
    
    sudo apt-get install postgresql-9.6

  
In order to enable access to PostgreSQL from a location other than localhost, we will need to make a few modifications to its configuration.

  
First we need to tell PostgreSQL to listen on all interfaces and not just on localhost by editing /etc/postgresql/9.6/main/postgresql.conf and changing listen_addresses to:
    
    
    listen_addresses = '*'

  
Next, we need to enable our www container access by editing /etc/postgresql/9.6/main/pg_hba.conf and inserting something along the lines of:
    
    
    host all all 10.0.3.196/24 md5

  
Finally, we need to restart PostgreSQL:
    
    
    sudo service postgresql restart

  
Now you can exit the db container so we can continue with some additional configuration items such as autostart and start order.

  
Edit configuration for www by modifying /var/lib/lxc/www/config to include this to the end of the file:
    
    
    # Autostart
    lxc.start.auto = 1
    lxc.start.delay = 5
    lxc.start.order = 200

   
Edit configuration for db /var/lib/lxc/db/config and add this to the end of the file:
    
    
    # Autostart
    lxc.start.auto = 1
    lxc.start.delay = 5
    lxc.start.order = 100

  
At this point we have two LXC containers running. One with Apache and the other with PostgreSQL 9.6. However, these containers use internal IP addresses and are not accessible from outside of the host machine. There are a few options for getting outside access to these containers ranging from fully routable configurations to port forwarding. In our case we do not wish to have the entire container to be fully accessible so we will use port forwarding to allow access to only the daemons we specify. In order to configure port forwarding we are going to need to know (verify) the private IP address of each LXC container.

  
Verify the IP address for each container:
    
    
    sudo lxc-attach -n www
    ifconfig eth0 | grep "inet addr" | awk '{print $2}' | sed 's/addr://'
    

example:10.0.3.196
    
    
    sudo lxc-attach -n db
    ifconfig eth0 | grep "inet addr" | awk '{print $2}' | sed 's/addr://'
    

example: 10.0.3.143

  
While we are talking about port forwarding we should probably mention firewalls. If you don't have one, you probably should. So let's get started by creating /etc/iptables.up.rules with the following contents:
    
    
    *filter
    # Accepts all established inbound connections
    -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    # Allows all outbound traffic:
    -A OUTPUT -j ACCEPT
    
    # Allow all outbound traffic from Linux containers:
    -A FORWARD -i lxcbr0 -j ACCEPT
    # Allow HTTP traffic (to be forwarded to the Linux container hosting the server) :
    -A INPUT -i ens3 -p tcp --dport 80 -j ACCEPT
    -A FORWARD -i ens3 -p tcp --dport 80 -j ACCEPT
    
    # Allow PostgreSQL traffic (to be forwarded to the Linux container hosting the server) :
    -A INPUT -i ens3 -p tcp --dport 5432 -j ACCEPT
    -A FORWARD -i ens3 -p tcp --dport 5432 -j ACCEPT
    
    # Allows SSH to the host:
    -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
    
    # Allow ping
    -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
    
    # Reject all other inbound - default deny unless explicitly allowed policy:
    -A INPUT -j REJECT
    -A FORWARD -j REJECT
    
    COMMIT
    
    *nat
    # Forward HTTP traffic to the Linux container running it:
    -A PREROUTING -i ens3 -p tcp -m tcp --dport 80 ! -s 10.0.3.0/24 -j DNAT --to-destination 10.0.3.196:80
    
    # We need the '! -s 10.0.3.0/24' to allow the containers to access http on other servers, needed for apt-get update/upgrade/etc
    
    # Forward PostgreSQL traffic to the Linux container running it:
    -A PREROUTING -i ens3 -p tcp -m tcp --dport 5432 -j DNAT --to-destination 10.0.3.143:5432
    
    # Allow LXC subnet net access.  
    -A POSTROUTING -s 10.0.3.0/24 -j MASQUERADE
    
    COMMIT

  
Next we need to have our firewall and port forwarding rules loaded automatically whenever the network is brought up by creating /etc/network/if-up.d/iptables:
    
    
    #!/bin/bash  
    /sbin/iptables-restore /etc/iptables.up.rules

Now, make the script exacutable:
    
    
    sudo chmod +x /etc/network/if-up.d/iptables

  
You can enable the rules by running '/etc/network/if-up.d/iptables'.

  
Now web apps (Apache + PHP) in our www container will be able communicate with our database (PostgreSQL) running in our db container, the containers will be able to access the Internet, and web clients will be able to access our web server.

  
You can test the setup by opening "http://IP-of-your-host" in your client web browser. You should be greeted by the default Ubuntu Apache welcome page. The rest is up to you, but the possibilities are nearly endless.

  
Further reading:  
<https://help.ubuntu.com/lts/serverguide/lxc.html>

---
[View this page online](https://www.commandprompt.com/blog/ubuntu_lxc_apache_postgres/)

---

# Snap packages for 9.3.15, 9.4.10, 9.5.5 and 9.6.1 available

> The snap packages for 9.3.15, 9.4.10, 9.5.5 and 9.6.1 are now available. To install them:

sudo snap install postgresql$version

Where $version is one of 9…

The snap packages for 9.3.15, 9.4.10, 9.5.5 and 9.6.1 are now available. To install them:

> **sudo snap install postgresql$version**

Where $version is one of 93, 94, 95 or 96.

The snap packages for PostgreSQL are a community project being lead by Command Prompt. You can visit the repo at [github](<https://github.com/commandprompt/postgresql-snap> "The github page for postgresql snapcraft").

To learn more about snap packages please visit [the Ubuntu snapcraft developer FAQ](<https://developer.ubuntu.com/en/snappy/support/faq/>).

---
[View this page online](https://www.commandprompt.com/blog/ubuntu_snap_packages_postgresql/)

---

# Can I make initdb quiet?

> A #postgresql user today asked:

noob question - trying to write a Dockerfile that runs postgres... how do I get the effect of a non-interactive `service pos…

A #postgresql user today asked:

> noob question - trying to write a Dockerfile that runs postgres... how do I get the effect of a non-interactive `service postgresql initdb` call?

 

While several other community members provided the truthful but not helpful answer of, "Just throw Docker in the Trash", I worked out the following hack/trick/snipe hunt. The answer is, you can't. You have to call initdb directly. This took a few tries because PostgreSQL does not ship -q (quiet) flag with initdb. It will always make noise even when you don't want it to. However, if you call initdb directly, pass a few flags that have nothing to do with actually being quiet and redirect STDERR then you are golden. For example:

 
    
    
    /usr/lib/postgresql/9.5/bin/initdb data -A md5 --pwfile=pwfile 2>&1 > /dev/null

The above says:

  1. Initialize a new data directory called data.
  2. Use the auth method of md5 to start
  3. Tell initdb to get the password for md5 from the password file of pwfile
  4. Redirect STDERR to STDOUT and then write that output to /dev/null



This will produce zero output on execution. You could still have for a RETVAL to see if it suceeded or change /dev/null to a log file.

---
[View this page online](https://www.commandprompt.com/blog/can_i_make_initdb_quiet/)

---

# psql tips: Change the location and filtering of the history file

> Anyone who uses PostgreSQL knows of the best client available: psql. This is the client that ships with PostgreSQL. Yes it is a command line client (which turn…

Anyone who uses PostgreSQL knows of the best client available: **psql**. This is the client that ships with PostgreSQL. Yes it is a command line client (which turns some people off) but that also means that it is the most efficient at everyday tasks for a DBA. What a lot of people don't know is that psql is rather configurable. Here is an example:

**Problem 1:** I want my history file in a place other that ~/.psql_history

**Problem 2:** I want my history file to be per database not global

**Solution 1:  **Edit the .psqlrc file and change the history file settings

\set HISTFILE ~/psql_history/.psql_history  
  
This will put your .psql_history file into the directory psql_history under your home directory.

**Solution 2:  **Edit the .psqlrc file again to:

\set HISTFILE ~/psql_history/.psql_history- :DBNAME

This will not only put all your history files within the psql_history directory, it will separate the history files into a file per database. For example:
    
    
    postgres@jd-laptop:~$ ls -l psql-history  
    total 4  
    -rw------- 1 postgres postgres 33 Oct 24 09:33 psql_history-tut  
    [postgres@jd-laptop:~$ ](<mailto:postgres@jd-laptop:~$>)

Where tut is the name of a tutorial database I use for teaching.

---
[View this page online](https://www.commandprompt.com/blog/psql_tip_change_history_location/)

---

# Will Postgres use the second element of an index if it is the only element in the WHERE clause?

> This is a test table from an Oracle to Postgres migration. The table has had a dozen or so columns removed for the illustration of this test case. I did not de…

This is a test table from an Oracle to Postgres migration. The table has had a dozen or so columns removed for the illustration of this test case. I did not design this table but the customer is fixing it (adding proper primary key, changing to boolean and integer where appropriate etc...).

### Table "public.costcenter"  
  

    
    
           Column       |            Type             |     Modifiers
    -------------------+-----------------------------+--------------------
      costcenterid      | numeric                     | not null
      costcenterno      | character varying(100)      | not null
      amount            | numeric(18,2)               |
      closed            | boolean                     | not null
      enteruser         | integer                     |
      phonelines        | numeric                     |
      cckeyid           | character varying(100)      |
      country           | character varying(2)        |
      level4            | character varying(100)      |
      level5            | character varying(100)      |
      level6            | character varying(100)      |
      level7            | character varying(100)      |
      level8            | character varying(100)      |
      level9            | character varying(100)      |
      latitude          | character varying(20)       |
      longitude         | character varying(20)       |
      lastactiondate    | timestamp without time zone |
      lastactionuserid  | numeric                     |
      countryid         | numeric(3,0)                |
      stateid           | numeric(4,0)                |
    

###  

### Indexes:
    
    
    "costcenter_idx" PRIMARY KEY, btree (costcenterid)
    "enteruser_cost" btree (costcenterid, enteruser)

###  

### General settings

  * PostgreSQL 9.5.4 
  * Linux (because there is only Linux)
  * random_page_cost and seq_page_cost both = to 1.0
  * Standard (100) default_statistics_target
  * 8392 rows



###  

### Distribution of column costcenterid,enteruser:
    
    
    costcenterid | enteruser
    --------------+-----------
               109 |        43
                 3 |        46
                12 |       623
              1287 |        44
              6936 |         2
                 3 |       848
                 2 |         1
                40 |        50
    

###  

### Query Plan Examples:
    
    
    cs=# explain analyze select count(*)
    	from costcenter where enteruser = 43;
                                                                      QUERY 
    PLAN
    --------------------------------------------------------------------------------------------------------------------------------------------
      Aggregate  (cost=181.99..182.00 rows=1 width=0) (actual 
    time=0.299..0.299 rows=1 loops=1)
        ->  Index Only Scan using enteruser_cost on costcenter 
    (cost=0.29..181.72 rows=109 width=0) (actual time=0.150..0.289 rows=109 
    loops=1)
              Index Cond: (enteruser = 43)
              Heap Fetches: 109
      Planning time: 0.095 ms
      Execution time: 0.319 ms
    
    
    cs=# explain analyze select count(*)
    	from costcenter where enteruser = 2;
                                                         QUERY PLAN 
    
    ------------------------------------------------------------------------------------------------------------------
      Aggregate  (cost=290.24..290.25 rows=1 width=0) (actual 
    time=2.052..2.052 rows=1 loops=1)
        ->  Seq Scan on costcenter  (cost=0.00..272.90 rows=6936 width=0) 
    (actual time=0.008..1.717 rows=6936 loops=1)
              Filter: (enteruser = 2)
              Rows Removed by Filter: 1456
      Planning time: 0.062 ms
      Execution time: 2.079 ms
    
    
    cs=# set enable_seqscan to false;
    cs=# explain analyze select count(*)
    	from costcenter where enteruser = 2;
                                                                       QUERY 
    PLAN
    ----------------------------------------------------------------------------------------------------------------------------------------------
      Aggregate  (cost=352.71..352.72 rows=1 width=0) (actual 
    time=3.355..3.355 rows=1 loops=1)
        ->  Index Only Scan using enteruser_cost on costcenter 
    (cost=0.29..335.37 rows=6936 width=0) (actual time=0.020..2.982 
    rows=6936 loops=1)
              Index Cond: (enteruser = 2)
              Heap Fetches: 6936
      Planning time: 0.082 ms
      Execution time: 3.388 ms
    

 

As you can see, with a proper data distribution the planner will chose to use the second column within an index. It will also choose the proper plan (seq_scan) when it is cheaper to sequential scan than use an index. However, keep in mind that it very much does depend on the amount of data that is being accessed, and the data distribution of that data as to whether using a second element in the index as the primary index for that column is the most efficient.

---
[View this page online](https://www.commandprompt.com/blog/second_element_index_usage_postgres/)

---

# Rich in the Jungle: A AWS to Softlayer comparison for PostgreSQL

> I have updated my Rich in the Jungle presentation with new pricing for AWS vs. Softlayer. Things haven&#x27;t changed much, in terms of raw performance per dollar (…

I have updated my Rich in the Jungle presentation with new pricing for AWS vs. Softlayer. Things haven't changed much, in terms of raw performance per dollar (which is not the only qualifier). Softlayer is clearly the winner.

---
[View this page online](https://www.commandprompt.com/blog/aws_compared_to_soflayer/)

---

# The fall of Open Source

> Once upon a time FOSS was about Freedom. It was about exposing equality within source code. It allowed everyone equal rights and equal access to the technology…

Once upon a time FOSS was about Freedom. It was about exposing equality within source code. It allowed everyone equal rights and equal access to the technology they were using. An idea that if you were capable, you could fix code or pay someone to fix code. An ideology that there was something greater than yourself and that there was an inherent right built into what it is to be human with software. 

## **Leaders to lemmings**

I sat in a bar slowly nursing beers with other community members over a period of hours. We spoke of many things. We spoke of the never-done new PostgreSQL website. We spoke of my distaste for Amazon Web Services since reformed, with the exception of S3. We spoke of life. We argued, we had honest discourse and that is excellent. There was nobody complaining of political correctness. There was nobody claiming to be "offended". There was nobody leaving because their feelings were hurt. There was a community member who passed out in his chair and dropped his phone. We walked him to his room to make sure he was safe. All was good.

This retrospective has been digging around in my grey matter since that night six months ago. Originally this was going to just be the stuff of legendary and exaggerated stories among community members that are only getting older and a few who are young but will get there someday. That is, until it began to itch, and as with any good community member, I am scratching that itch.

_" My time is precious to me"_

It seems like a harmless thing to say. Of course your time is precious to you. I would say that is probably true of most people. I know that my time is precious to me. I make it a point of working part time from May - September so I can take time for my family. (Don't worry, I more than make up for it the rest of the year). 

The problem with the statement is the context. The statement came from a well known contributor and a very smart guy. The reference was in relation to why someone would use software as a service and the general idea was: Software as a Service is awesome because it allows me to have more time for me.

## **The great compromise**

A lot of companies have come up through the ranks to become dominant players in the Open Source industry: Meetup.com for user groups, Github for development, Heroku for software as a service and Slack for communications. When considered independently there is nothing wrong with these services. They offer a great value, they increase productivity, more code gets developed, more software gets released and communities grow. 

The problem is that not a single one of these services are open source. The use of these services creates an intrinsic advocate position for closed source software. In turn you will see the use of these services increase whilst the use of open source alternatives decrease.

Consider Slack, which is widely considered the hot new collaboration tool. Yet, it does not adhere to open standards, its network is closed as is its software. Yes, you can interoperate with it using open source tools as well as standard protocols but in no way is it actually open in the sense of our community or our licensing. The argument is, "I use slack because there are no other tools like it". 

XMPP (Jabber) which is Open Source and a standard IETF protocol (RFC 3920) can provide a similar environment as Slack. It supports Video, Voice, Plugins, External protocols and bridges, Image embedding, Video sharing, File sharing and yes, Chat. It also supports federation which allows any community to communicate with any other community using XMPP.

I appreciate the PostgreSQL community. The PostgreSQL community hosts its own code repositories, website, and mailing lists. We collaborate in the true vision of Open Source and actively reject moving our project to externally hosted facilities controlled by services which are not Open Source. The community does it even though it may be quicker or more convenient to use a service. The community puts forth the effort for the community. There is an ideology that is about fairness, freedom, equality, rights, and the greater good.  

## **And that, was the fall of Open Source**

The moment that Open Source becomes primarily about "my time" is the moment that Open Source is no longer a movement. It is no longer an ideology. It is no longer about fairness, freedom, equality, rights, or the greater good.

---
[View this page online](https://www.commandprompt.com/blog/the_fall_of_open_source/)

---

# Upgrading Ubuntu LTS and PostgreSQL

> If your PostgreSQL instance is running on an Ubuntu LTS system that you need to upgrade to the most recent release, say from precise to trusty – because, well,…

If your PostgreSQL instance is running on an Ubuntu LTS system that you need to upgrade to the most recent release, say from precise to trusty - because, well, sooner or later you must - you need to consider what is going to happen to your database.

**Note**  
 _The upgrade process described in this article is similar to what you would have to do if you were upgrading from Trusty to Xenial, the newest Ubuntu LTS release._

Ubuntu attempts to make the process of upgrading to the newest distribution release easy and hassle-free. In fact, it is the case in many situations but not when there is PostgreSQL running in the system. If you just go ahead and try to run do-release-upgrade command, which is the officially recommended way to upgrade your Ubuntu LTS distribution to the newest release, you will end up seeing this error message: 
    
    
    ...  
      
    Get:72 [http://us.archive.ubuntu.com](<http://us.archive.ubuntu.com/>) trusty-backports/universe Translation-en [34.6 kB]   
    Fetched 23.3 MB in 6s (0 B/s)  
      
    Checking package manager  
    Reading package lists... Done  
    Building dependency tree  
    Reading state information... Done  
    Building data structures... Done  
    Calculating the changes  
    Calculating the changes  
    Could not calculate the upgrade  
      
    An unresolvable problem occurred while calculating the upgrade.  
      
    This can be caused by:  
      
    * Upgrading to a pre-release version of Ubuntu  
    * Running the current pre-release version of Ubuntu  
    * Unofficial software packages not provided by Ubuntu  
      
    If none of this applies, then please report this bug using the  
    command 'ubuntu-bug ubuntu-release-upgrader-core' in a terminal.

Not very helpful, is it? Well, clearly you need to troubleshoot. Where do you start?

Examine /var/log/dist-upgrade/main.log and look for ERROR messages. This is what you will see: 
    
    
    ...  
    2016-02-09 07:19:01,392 DEBUG blacklist expr '^postgresql-.*[0-9]\.[0-9].*' matches 'postgresql-plperl-9.3'  
    2016-02-09 07:19:01,393 DEBUG The package 'postgresql-plperl-9.3' is marked for removal but it's in the removal blacklist  
    2016-02-09 07:19:01,462 ERROR Dist-upgrade failed: 'The package 'postgresql-plperl-9.3' is marked for removal but it is in the removal blacklist.'  
    ...

That's more specific. Basically, it says if any postgresql-* package is installed abort the mission. This means that what was supposed to be an easy and hassle-free, one-command-only upgrade has become your duty to figure out how to do it. Yeah, the promise of simplicity that Ubuntu broadcasts far and wide in its marketing campaigns clearly has its terms and conditions that may apply. Anyway, roll up your sleeves. We gotta do some manual work here.

It is not a problem with do-release-upgrade per se. APT itself is configured on Ubuntu LTS to not do anything with PostgreSQL packages, like, for example, automatically removing postgresql-* packages:
    
    
    /etc/apt/apt.conf.d/01autoremove-postgresql  
    // File installed by postgresql-common. Currently not updated automatically,  
    // but might be in future releases.  
    //  
    // We mark all PostgreSQL packages as NeverAutoRemove because otherwise apt  
    // would remove the old postgresql-x.y package when the "postgresql" meta  
    // package changes its dependencies to a new version, rendering the old  
    // database cluster inaccessible. As access to the cluster might depend on  
    // other modules (like datatypes), we use a pretty wide pattern here. We might  
    // tighten this to match only actually used PostgreSQL versions in the future.  
      
    APT  
    {  
     NeverAutoRemove  
     {  
       "^postgresql-";  
     };  
    };

It's a good thing, if you think about it. You don't want a OS upgrade tool, or even a package manager to mess with your database.

So, before you even attempt to run do-release-upgrade and hope it lives up to Ubuntu's promise of making your life easier, you need to plan upgrade of your PostgreSQL. As a new Ubuntu LTS release will most likely mean a new version of PostgreSQL, you need to carefully put together a plan for the upgrade.

It means you should really start by reading release notes of the new PostgreSQL version (available on the main page of [postgresql.org](<https://www.postgresql.org>)) and see if you will need to do anything special to make sure your data isn't lost during the upgrade, and that any other requirement is met.

Once you have an idea of what's coming in the new version and what actions you may need to take to ensure that your upgrade is completed successfully, you can start working on getting your PostgreSQL server ready for the do-release-upgrade.

In most simple cases that don't require you to do anything special about PostgreSQL itself, it will come down to a number of steps:

  * Back up your data
  * apt-get remove postgresql-*
  * do-release-upgrade
  * Update PGDG repository configuration (precise->trusty)
  * apt-get update
  * apt-get -s dist-upgrade
  * Restore your data 



## Back Up Your Data

You need to back up your cluster/databases and globals. You can [read more about backups here](<../../../../blog/a_better_backup_with_postgresql_using_pg_dump/>). This time we're taking a look at how to use **pg_dump**. You can also upgrade by using **pg_upgrade** utility which we'll cover next time. For example, using **pg_dumpall**  something like this will create a backup for globals and for every database in your cluster:

 
    
    
    /usr/lib/postgresql/9.3/bin/pg_dumpall -g -Upostgres -p 5434 --file=globals.sql;  
    /usr/lib/postgresql/9.3/bin/psql -p 5434 -AtU postgres -c "SELECT datname FROM pg_database \  
                             WHERE NOT datistemplate"| \  
    while read f;  
      do /usr/lib/postgresql/9.3/bin/pg_dump -Upostgres -p 5434 --format=c --file=$f.sqlc $f;  
    done;

 

In this example, we use PostgreSQL 9.3 that was installed on Ubuntu Precise from PGDG repository. Upon successful completion of do-release-upgrade Ubuntu Trusty will have PostgreSQL 9.3 installed as its default PostgreSQL version from official Ubuntu repositories. In our simple test setup all data survived do-release-upgrade just fine and PostgreSQL works as expected, without any problems, after the upgrade of operating system. However, in most real-life scenarios you will probably be making a transition from a lower to a higher PostgreSQL version. In which case you would need to upgrade by dumping and reloading your data.

## Remove PostgreSQL Packages

This must sound kinda scary, but the way to successfully run do-release-upgrade is by making sure PostgreSQL doesn't get in its way. You literally need to remove PostgreSQL packages before attempting to run do-release-upgrade.

Just to be safe, make sure you first back up postgresql.conf, pg_hba.conf and other important configuration files. In fact, create a copy of entire /etc/postgresql/9.3/ and /var/lib/postgresql/9.3. This will include data directory, which may be in gigabytes or terabytes. Well, you must have backups of your database anyway. Just make sure the backups are recent, in working state and there's a way to restore them in case APT messes up your data.

Once you're absolutely positive that you have backups of your entire database cluster and configuration, remove all PostgreSQL packages from the system:
    
    
    $ sudo apt-get remove postgresql-* 

Note that apt-get remove will not delete your configuration, or data. At least it shouldn't. That's what apt-get purge does. The only reason we recommend to take backups is because it is a good practice and you don't really want to rely on APT and learn one day that an obscure bug or a change in its policy of doing the 'remove' action results in data loss.

## Run do-release-upgrade

Here's a checklist to go over before running do-release-upgrade:

### Ensure /boot has enough disk space.

If it doesn't, do-release-upgrade will fail and display this error message:
    
    
    "Not enough free disk space  
    The upgrade has aborted. The upgrade needs a total of 54.2 M free  
    space on disk '/boot'. Please free at least an additional 13.9 M of  
    disk space on '/boot'. Empty your trash and remove temporary packages  
    of former installations using 'sudo apt-get clean'. "

### 3rd party software may break do-release-upgrade

PostgreSQL is one example. You will see do-release-upgrade notify you that PGDG APT source list was disabled in a typically non-specific fashion: 
    
    
    "Third party sources disabled  
    Some third party entries in your sources.list were disabled. You can  
    re-enable them after the upgrade with the 'software-properties' tool  
    or your package manager."

### Open additional SSH session on port 1022 before do-release-upgrade starts upgrading packages

If you lose your current SSH session you can retain access to your system in the second window.

### Run do-release-upgrade

When you're ready run: 
    
    
    $ sudo do-release-upgrade

## Update PGDG Repository Configuration

Assuming do-release-upgrade went fine and you're using PGDG repositories, you will need to uncomment a line with repository source in /etc/apt/sources.list.d/pgdg.list and change precise-pgdg to trusty-pgdg. Your pgdg.list file would look then like this:
    
    
    deb [http://apt.postgresql.org/pub/repos/apt/](<http://apt.postgresql.org/pub/repos/apt/>) trusty-pgdg main

## Resynchronize The Package Index Files

At this point you should be running Ubuntu Trusty LTS and you need to run:
    
    
    $ sudo apt-get update

## Install Updates and Upgrades

You will probably realize that postgresql-* packages in PGDG are newer version than those installed during do-release-upgrade. So, in case you want to make sure you're using the most recent PGDG version of PostgreSQl run: 
    
    
    $ sudo apt-get -s dist-upgrade

Drop -s after making sure that proposed changes look good.

## Restore Your Data

Finally restore your data using the newer version of PostgreSQL. For the sake of example let's assume that you wanted to upgrade to PostgreSQL 9.5 once you're running trusty.

Essentially, to start using the new PostgreSQL version you would:

  * apt-get install postgresql-9.5
  * Restore your globals



 Here an example of you could restore globals:
    
    
    /usr/lib/postgresql/9.5/bin/psql -U postgres -p 5435 < /home/admin/do-release-upgrade/db-backups/globals.sql 

  * Restore databases:



Consider this example
    
    
    for i in databaseA databaseB databaseC;do /usr/lib/postgresql/9.5/bin/psql -U postgres -p 5435 -c "CREATE DATABASE $i;"; done 
    
    
    for i in databaseA databaseB databaseC;do /usr/lib/postgresql/9.5/bin/pg_restore -U postgres -p 5435 --dbname=$i $i.sqlc;done

Port number may be different on your system and these examples are merely a guideline.

Although it's a complete set of actions required to upgrade your database various factors unique to your setup may introduce other steps that need to be carried out in order to successfully upgrade PostgreSQL. There's no one-size-fits-all upgrade strategy and this post demonstrates just one of the simplest scenarios you may encounter.

If your case is particularly complex to the point where you would rather have us double-check your upgrade plan or actually perform it for you, feel free to [contact us](<../../../../contact/>) and we'll figure out the best path to upgrade your system running PostgreSQL to the latest release.

---
[View this page online](https://www.commandprompt.com/blog/upgrading-ubuntu-lts-and-postgresql/)

---

# What is good for the community is good for the company (profit is the reward)

> As the PostgreSQL community continues down its path of world domination I can&#x27;t help but wonder whether the various PostgreSQL companies are going to survive t…

As the PostgreSQL community continues down its path of world domination I can't help but wonder whether the various PostgreSQL companies are going to survive the changes. Once upon a time there was an undercurrent of understanding that what was good for the community was good for the company. Whatever company that may be. However, over the last few years it seems that has changed. It seems there is more prevalance toward: What is good for the company is good for the community, or in other words, "The goal is profit."

That is a flawed discipline to follow in the Open Source world. A truly beneficial, strong and diverse community has to eliminate that thought entirely. **The goal is not profit; profit is the reward.**

That isn't to say that profit is bad. That would be stupid. It is profit that allows Command Prompt to sponsor my activities with _United States PostgreSQL_ and _Software in the Public Interest_. It is to say that my contributions to the community as a whole drive Command Prompt's profit. It is symbiotic; a constant ebb and flow of the relationship between community and commerce.

![Infinity](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUkAAACZCAMAAACVHTgBAAAAflBMVEX///8AAAD29vb8/Pz5+fna2try8vLu7u62traRkZGGhoZ4eHiMjIyurq7f39/U1NRfX1/JyclxcXHPz8+ampqenp46OjpJSUmlpaUlJSVaWlpkZGRDQ0PBwcESEhKxsbExMTFra2tSUlIfHx9/f388PDwsLCwLCwsaGhpUVFS3M0f/AAAL50lEQVR4nM1dWWLqMAwMBAiUreyUAiWFbve/4GuAtiyxNLIl581vUxCKrXUsJ4kvBqP+9GH8vHpdfK3ybm/WnmTen1UBvsXvdB8Xu8/aN/bzxXO30x8NYkvRXObbWhnex8thbGHkGPS776Xif+Mzn03SSHJsxi4pzlhM/2NtDpaPjPjfeOtMzAUZdnk5Cow35qJ4YPLwgYn/jee25dJ8eYIFqdW69u9VhOFBIPxJmVbLYSaV5GPaMhJFjGyKr8ZL9Ay8qFiPRzz+FwtztPIS/vQLlI1+21uSfV9XEjn6n/56LLBWXA2DeZAo04aeKFKk0zA1nnSptS7FpvoOvbqSKEKkHQU9FnjUsJdDP1t9g4cqdKmxHn/QCZbmQUuUXqzU4QcvWpKfsA3b4pkzrfLATElFECaS2BfDIUCcjbIsbTVFMagDOaEce+8Kh5a9/sOuqakvJ5bqgp/x4idPQDzrRm7vegY7C8FP6HrIk1rJs1RX3TX0d9Il1mJ5WirBTyl2lgXVgb6nucansJiQmUrzYKPFxLc8IIMoSrdVZK32YVMMrq+N5T5BsKda9tKEBGcujOzFPgFelQ07G/mHrbq1VEvHeKC20jCKuMRUVY/1tzhSH7HFUl+TOLIMa8XYchhL6BPeEJl6EQUaaSnSLKtxYczLFM1sH6EUD3GdYwOwvYAIbvsKbwoF9TSmifwF5zEjeRuBRCz8gt/1YbkZDlqNNG1kg+Fm1pW+jg9aKpmRXHXaw+zsxtJs2O54FbMCa20T+Tc+L0trUs3+s+RTckqqJv45i2XpYsracpsVZCzFbc8Hslc4AVkmBShmAdrQ3M6o2LQpdf9ffkosIOzVdIE0dQPnnO6oEtTAnKd5TGQrc+/L1hCsIEHvvQnucmcoNID+/QkLAhuysoxfMV1i1+aS4HXwGiQ15L0EnIq2pFbo43cW+MfvpEwKKK7eOX448K9fsgRvs8d/a0/4U5NEQA3xoZ0hlqP8/QP/KO8cCFzrs+yTU7yD7FkrQZZl2f8B/Q+vIBrvq8wl5IIGTJxaeFNRWrx5KllbDfaf3j1LNy28uIT/5jpcQw0K/HlLfP8/bJ104S8PXhVBuxJ19AMXgZU7dhXceWC2cvEaJBDMd8NWEFxnCWfQcOHQXfrN/dSAFXkEXIlFvAOsSA3KB1fTuQkLuN0yD5cIzXp4mgO6tcO20Q84B3LDJWAcLNi3oIHytVbM56CKlAeo5eDKOtcRDfOwzhEAtB1NN0ka5efT7qB3BoRZZlelrD79rFq7BYwtPwmHm4Jpk2YTmAkr8UfDmcG/QOMh9ybAMpsnVUocs78vFhrtWKGOJIoMXFIur4vl2qGRxi1ob9lFH1Q+6QVmPOW1G6z6Q/YFfMA4ub8HycfUjyaB9eQyj4G9BQPOEW3gf986Wa9R3dsngOHQ/SvMof/TZcmckJLf+Ou9yYTIgjaKFefvUj0s5bThDJOL8vP8EGkELNh531+JeeDroAELoYzOV9CW8hxqkEeArM4cYhbvMk1hYt4zzI7okxX0Nv+jFEPJG2Bsx7/8ATOuajnEHUiLdI6DqEfMBEPX2I8qsVqS5XFyql+4Pz5BpR12S5L54ltVYj7KdJQJbwSpbWZ7DAlTT6FKrCBpOxOGDISOm4FwowDdMggtqKzTSVLoOevhOjnx3UXoRbl381OG2EG0JVSNMxeW8nmFyyGs1ZO1bImIRlGxIknXXGSCRLwb5UC2iLJYqSITih2akNFknJFzKhzxKKedKe/dopbsLoZ0icbEkjiKJGnYTcrhmAaTlwg+3BVHkUlC8D42VGE93si+QFVGGxtJ5N59qjYZS74kUJXx5m8SCe6UOBCt3QshETAoIOIoVmIDH4jVoNV4x+A9BibqPEG3GHmSO/8WbSTNCWAd/QbbuLOx3JzNLyLHiOUQf9DwOJ72FHn4nTv4XhP94/hjOMXpznvsCWPu0PedWK+RhSwgPKakQKBTE3DrtqHMAUcbiPxO1ODiBOIYuVuT8V94AYHf0WFHykBk3m5NVvDGCzTQQzaPVUhH5THOanRFmkSJFurUHwiUJp18v8o0Cc20qEg6anc7e4/V2ElG3D9UMyrdnXjv3ZygT/5zbYA1b6tZlO4qxTzJnX+rRFR87IEFI42Fu9CyIKL2KiSVjAepYny/W1uPhJYruTgoFYx0q0BAd0+sS9jQSm65kVQxVA4JaYnXI/Izz+m+QfgSKNKEbszALcuSMPBxK71HiOaD1OLnOQQ9qU30FrlDb/qQ3y7gM8o5AMSQpyG1YONK6Xd1TNyNQ2RfGUXMiewb/SZIRg0rCbpIQoVIcRs5fn0c+/Hol3CfbyvIaO4wKKoRgscxVKhKQsaiNEVkZ9FETNjjqv+FKomK/tHIuP8c8XLRIBplLFtJUMGOh1fchNl41jzwEpZIHpzIZI/e2X0gMwan94hgNqrNSbYbUD7x+ABRD4y0vRVovdZnCwoQicNpkBlxOsLupotL5KyegOJvhMSRcIpnp0ecLLAXD2FHL5H0x7yITm3uM/OHGLkZoR7Eb+1iuQFk9J1xkY3ieJ4fIZRt73MAG3l8Dihcbm27ZMQ3/857JLy73dnUE4Dw5+T2oPN2lh6SMjC/0xGIwRQ7Q9kSqLL7Y2CgAodhnZ862/9b66HaeaaXwwOZzV/yD7XBzaouVPjw/vcYMV7Usu0NUIAux79BtH6rvIyS9eI7qYHZZvWBOjKD6cofQxMfbGJ0MqK9MM+kOTdickON7RsXAvHY1hbREFWqugpwqLdt08+BqBa3kQN2zvtDv9hPTpq4OihLLl4LKw6Rd+8NCzgMVTt2o+cuXb848mXrR7zQTQZlWT/Yo1A+cplT33WTppLLV50ACPW1ywfFgwSsgNtN7kEXUG7jRPJh3Y5OChXIXRUJ8GKhD718hxnUe/s43bXXnPeHbdCd8//R8xFqMtMv/t6Q0GLp2XCMH7AnQhlUlUolS2bI470TYagkWmfvsAEDH2QQC5M1NNJw5svKEgFGKhW7k4GsPiZagFLwAuFFf84sl6mFm3OmsCrRxcSG1rAq94ELgAsVyi0IlweH0pFTtPMF5CiwKsOWJVvKK39RbHwR5g3hC0mgZE9AbPP3lqxvczk1toAd0FZuwK1YMKMSHBZdeSbifCbm+mCe5TT3TRyxYZM1erz+NSRXEXuRNPjOiDtjAX6vVzljCBPxJWffRYRLcZkVyaWIiQdAHvclXpYZzvpZ8592ARnlUqTLBjKjjPpEqGolK/Bngrlp0qxEeEvyDF7wUK2KbmFjLhEnFAxywS+VO7S6kHZ5gMJL8IJ6JsAGVxC2VTYiWqTXkEYp8XLeZ1xahl5PzL539C0fuJxnILwx2bMfLD3D823p+86oqP4Cvxl+Tghue/ZTtzKHPfBmpV94p3Wym4TPoh/ad9pMJ1P4uukalDyL7mjPl8PbUKA1muJXVf5gF9DBlASWl1iPp/3NZDgcjjbL3jN8pegJUH8DNLh/eO12lv12+6U/6+WS1/qHsKkWmeAArhJAjqHCkFIZgtkJ2G3bikCnkAUS6KVQqNcFTF30AW7UY77jhQpnwtdYekGSMvuZOx9oUaLqgnvRAyHrpsdSpeJsRmH86g1pzzrKBtedROV3GleKckYDBaXh9xTUaa4qU+Zp+PR+g8eMM1gZDDQ1dzzyFVkALnR7wYh3bfv+fXk9hoZnbHZ6ZkBdUxUIfw6cVWjxZDqMyGegBoQgJqnJZjE/2y6f8oIgkIUgKg1B6EYYnd3QXwEKLHHd0GIV6ahzXVmXKiTCibRq68Y64rS2hmJZY6F1CkDJ7rzFnnTYB+9d56B4aKEub5fc4bWK6YEThVRNmf+f5WHijCNOerlCfRa2MB/0j3ZJOAC3mMa9M+QGTX/v07ERvO5nwx9ND+RimPgoc245c2Ej7Ru+LStdjhcYzEQ0g23H2h7V+3jp8nVZybRfJ9JRBythr2dxzHpjA7jyp8Mm/iBdBM3+gSxyrKajqIJn7Qf3Zll1Rv/LnnYgm/Q749erkQzbdd7rTyraRNmkPT3kr/Ononf/+b5ejXvLTfM/V+I10nr2jVZwLeAf2tqr72KQ2B8AAAAASUVORK5CYII=)

I would invite other PostgreSQL companies to consider this. I would challenge them to upend their profiteering motive and focus on community building with profit being the reward. The profit will follow. How do you do this? How do you continue to derive profit from community without sacrificing the community or your standing within the community? Here are some practical ideas:

  * If you aren't going to help, offer to find someone that will help. The answer, "Why would I help you" is never appropriate.
  * If you release something to the community, support it as the community would. Otherwise, keep it to yourself (open source or not).
  * Avoid language such as, "It's free, funding for new features or requirements is welcome." It is embarrassing and arrogant. It doesn't provide a solution and has no place on a community support list. If that is your approach contact the person directly. The community isn't your advertising platform. Instead try something like, "It is Free/Open Source, we are open to patches or feedback." 



Lastly, this isn't a post suggesting that you abandon good business practice. I am not suggesting that you shouldn't contact someone if you are looking for funding, only that you contact them directly. I am not suggesting you take losses every month for the community, that is bad for the community and bad for business. I am only suggesting, nay declaring that community works for business when business puts community first.

---
[View this page online](https://www.commandprompt.com/blog/good_community_is_good_for_company/)

---

# Simpycity 2.0.0 released (An ORM in Python)

> What Simpycity Is

Simpycity is an object-relational mapper. It seamlessly maps PostgreSQL query
and function result sets to Python classes and class attrib…

**What Simpycity Is**
    
    Simpycity is an object-relational mapper. It seamlessly maps PostgreSQL query
    and function result sets to Python classes and class attributes.
    
    It allows for the easy and rapid development of query- and
    stored procedure-based data representations. Simpycity leverages PostgreSQL's
    powerful composite type system, and the advanced type handling of the psycopg2
    database access library.
    
    **What Simpycity is Not**
    
    Simpycity is not a SQL generator and does not attempt to abstract or hide SQL.
    Simpycity is designed for developers who deeply understand SQL and
    desire to write the best possible SQL representations for their database.
    Simpycity also rejects the Active Record paradigm, whose simplistic patterns
    fail in even moderately complex systems.
    
    **Core Philosophy**
    
    The core philosophy behind Simpycity is that the Database and the Application
    are separate entities, each with distinct abilities and design
    representations; this echoes the classic Object versus Relation argument.
    It provides a mechanism where a single business Object can easily represent
    several Relations, and allow the base Relational layer to follow normal forms
    without compromising or complicating application design.
    
    **Usage**
    
    At its simplest, object-relation mapping looks like:
    
    
     --SQL
        create table foo (id int, name text);
        insert into foo (id, name) values (1, 'one'), (2, 'two');
    
        #Python
        class Foo(simpycity.model.SimpleModel):
            pg_type = ('public', 'foo')
            __load__ = simpycity.core.QuerySingle('foo',['id'])
    
        my_foo = Foo(1)
        print(my_foo.name)
        >>>one
    
    
    **License**   
      
    Simpycity is licensed under the LGPL license, and a copy of your rights and   
    permissions is available in the LICENSE file included in your distribution.   
      
    **Contact  
    **  
     The official source repository is <https://github.com/commandprompt/Simpycity>   
    For support, questions, and additional help with Simpycity, please feel free   
    to contact us on github.

---
[View this page online](https://www.commandprompt.com/blog/simpycity_200_released/)

---

# PgConf.US: 2016 Kicking the donkey of PostgreSQL Replication

> My slides from my presentation and PgConf.US 2016:
 


My slides from my presentation and PgConf.US 2016:

---
[View this page online](https://www.commandprompt.com/blog/pgconf_2016_kicking_the_donkey_of_postgresql_replication/)

---

# Spreading the conference love

> The PostgreSQL community has a lot of conferences in the United States:

PgUS United States PostgreSQL Conference 
Citus Data PgConfSV
PgUS SCALE PgDay (wh…

The PostgreSQL community has a lot of conferences in the United States:  


  * PgUS United States PostgreSQL Conference 
  * Citus Data PgConfSV
  * PgUS SCALE PgDay (which as of 2016 is really a conference within a conference)
  * PostgresOpen
  * EDB PostgresVision

And that doesn't come even close to the number of various conferences in Europe.   
  
As [Bruce Momjian pointed out](<http://momjian.us/main/blogs/pgblog/2016.html#May_31_2016> "Lots-Oh-Travel") in his excellent blog this is a good thing. It is true that in the United States there is [the big boy on the block](<http://www.pgconf.us/>) and it will likely hit 600 people in 2017 but other than that the conferences are all small and regional. The exception is PostgresVision which hasn't yet run and therefore we don't know how many people are going to show up. It is the regional conferences that are king and they should embrace that. It is far more important to speak to a region than a nation. When you speak to a region, you can address that regions particular needs and values in regards to Postgres. I look forward to the continued success of the smaller conferences, I think it would be excellent if each region was able to steadily grow to a point where there is the [one national conference](<http://www.pgconf.us/>) that draws the larger corporate ROI and half a dozen regional conferences that focussed on startups, small companies and local industry. Let's rock the next few years shall we?

---
[View this page online](https://www.commandprompt.com/blog/spreading_the_conference_love/)

---

# You are my fellow community member

> I attended the fantastically presented PgConf US 2016 last week. An amazing conference, my training was well attended, my talk was at capacity, the 20th Annive…

I attended the fantastically presented PgConf US 2016 last week. An amazing conference, my training was well attended, my talk was at capacity, the 20th Anniversary Party was phenomenal and the conference raised money for an [excellent cause](<http://www.techieyouth.org/>). There were over 435 attendees, giving our brothers and sisters at [PgConf EU](<http://www.pgconf.eu>) something to work for during their conference in November. 

While attending the hallway track, I was talking to a gentleman whose name escapes me. He asked me how he could contribute to the community. I am always excited to have that conversation because we are able to discuss all kinds of different ways to contribute, whether it be social (user groups, pgday, speaking at alternative conferences), documentation, code, or infrastructure. Bringing people to the community truly inspires me to continue building our community into something special.

Then he said, "I talked to X and he said, 'Why would I tell you that, you are my competitor?'" I was stunned. It is a sad and unacceptable ideology to hold within any open source community. It is an ideal that should be left to bad business practices from past decades. It is a horrible statement to make to any potential community member and speaks to a less than stellar understanding of how our community works.

If any person asks you how they can help with .Org, you should answer them honestly and enthusiastically. If you don't know how they can help, find a contributor and help the new person get connected. You should do this for **any** person looking to contribute, no matter who they work for (even if it is a competitor). Any other way of handling it is taking away from the community and is a testament to a selfishness that has no place here.

We are an inclusive community and that means we recognize something greater than ourselves. We recognize the power of a sustainable, productive .Org that is a collaborative space without the belittling behavior described in this post. I strongly hope that we can eliminate negative behavior such as this and become the most unified, bad-ass, and truly open source project around.

The feature I offered to the individual was to allow pg_basebackup to use multiple connections (jobs) to pull a basebackup. In a similar vein to how pg_dump and pg_restore.

---
[View this page online](https://www.commandprompt.com/blog/you_are_my_fellow_community_member/)

---

# PostgreSQL, FOSS, SCALE, NYCPUG, SPI, LFNW and Ruby oh my!

> Three weeks ago I was in Pasadena for SCALE 14. I had over 100 people in my room as I blistered the behind of PostgreSQL and how it handles backups. If you are…

Three weeks ago I was in Pasadena for [SCALE 14](<http://www.socallinuxexpo.org/scale/14x>). I had over 100 people in my room as I blistered the behind of PostgreSQL and how it handles backups. If you are interested in seeing my considered opinion I will also be [training on the same topic](<http://www.pgconf.us/2016/event/180/elevating-your-confidence-with-postgresqls-restoration-capabilities/>) at [PgConf.US](<http://www.pgconf.us/>). I am also [speaking on PostgreSQL Replication](<http://www.pgconf.us/2016/event/145/kicking-the-donkey-of-postgresql-replication/>) and finally, I was told that I am running the **Lightning Talks**. I have never coordinated something like Lightning Talks before. It should be an interesting experience. 

If that wasn't enough news, I have more! The [Ruby community](<https://www.ruby-lang.org/en/conduct/>) has adopted the draft PostgreSQL Code of Conduct. As one of the primary authors of that document, I am honored to have such a mature project adopt a rational and simple Code that protects all people equally. For those who are concerned about the idea of a Code of Conduct, please remember that even [the IETF](<http://tools.ietf.org/html/rfc7154>) has one. Let's keep the discussion civil and rational.

![](https://pbs.twimg.com/media/Ca-O2CGWIAA0wFv.jpg) | ![](http://photos4.meetupstatic.com/photos/event/1/b/0/c/600_446766924.jpeg)  
---|---  
  
Last week I spoke at NYCPUG on the same topic as at SCALE. It was a great experience with over 80 people attending. It was awesome to be able to see my adopted community and be able to interact with them. While I was there I also spent two days with Software in the Public Interest at the SFLC offices going over long over due board tasks. (For those that don't know I am a Director for Software in the Public Interest). It was a great and interesting time. The SPI board consists of one PostgreSQL person (me) and the rest are Debian or Ubuntu. The nuances of the philosophical differences are something to be explored at a later date.

So what is next? It looks like [Linux Fest Northwest and the PgDay](<http://www.linuxfestnorthwest.org/2016>) there. I am on the organizing committee for both and the amount of content we have had to review is enormous. Linux Fest Northwest is one of the largest FOSS conferences on the West Coast with 2000 people attending. All right here in my home town of Bellingham, WA!

After Linux Fest Northwest my travel will settle into recreational only until September (I hope). Let's see what happens.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_foss_scale_nycpug_spi_lfnw_and_ruby_oh_my/)

---

# .Org developer meeting @ FOSDEM

> A lot of people probably don&#x27;t know this but PostgreSQL does plan. It is true that we take all contributions and they are reviewed based on their merit but it …

A lot of people probably don't know this but PostgreSQL does plan. It is true that we take all contributions and they are reviewed based on their merit but it is also true that the community tries very hard to have a road map of some sort. Those road maps are created by the more prolific contributors in the community. 

In the past there was a yearly Developer Meeting. That meeting would take place at [PgCon](<http://www.pgcon.org/>). PgCon is held in May at the University of Ottawa, Canada. It is a small but great developer conference. 

This year we are going to have two plus probably an informal one for a total of three. The first of which is [taking place now @ FOSDEM.](<http://fosdem2016.pgconf.eu/>) The current list of attendees to that meeting and the [ discussion points are listed there.](<https://wiki.postgresql.org/wiki/FOSDEM/PGDay_2016_Developer_Meeting>)

The informal one will likely happen at [PgConf.US](<http://www.pgconf.us/>) in April. As it is the largest North American PostgreSQL conference, it makes sense that a lot of the developers you will see on the list at the FOSSDEM developer meeting will also be at [PgConf.US](<http://www.pgconf.us/>). Even better, we may see some of the "regrets" that were not able to make FOSSDEM. This allows for a great amount of catch-up. 

The second formal meeting will happen at [PgCon](<http://www.pgcon.org>) per the usual schedule. 

These are invitation only meetings so don't plan to just show up. The way to get invited is to be a prolific developer/contributor to [PostgreSQL.Org](<http://www.postgresql.org/>) and we are always looking for more of those. Without them, we couldn't be the leading and most advanced database in the world! 

I would be remiss if I didn't also mention that [the CFP for PgConf.US 2016](<http://www.pgconf.us/>) is closing this coming Sunday. Get those presentations in!

---
[View this page online](https://www.commandprompt.com/blog/org_developer_meeting__fosdem/)

---

# Scale 14x, PostgreSQL mini-conf, PgConf.US and NYCPUG

> It is really not fair to call it a mini-conf. The Scale 14x, PostgreSQL Day attendance was larger than every conference except PgConf.US  (EDIT: in the United …

It is really not fair to call it a mini-conf. The Scale 14x, PostgreSQL Day attendance was larger than every conference except [PgConf.US](<http://www.pgconf.us/>) ( **EDIT:** in the United States/Canada). It is a great opportunity to integrate with a wider community that is diverse, technologically capable and at the front lines of production installations. 

I spoke on Backups: The Good, the Bad, and the Ugly. I had over 100 attendees in my room. It was obvious throughout the talks that this is going to be the new West coast conference for PostgreSQL. The opportunity for advocacy and integration into alternative technologies is just too great to ignore from either PostgreSQL or the wider FOSS community that attends SCALE. 

This is also the same talk (although slightly updated after some education from Stephen Frost) I will be giving at [NYCPUG](<http://www.meetup.com/postgresql-3/>) on Feb, 11th. Be there, or be square. Be square and be there. We are all accepting. 

Back to [PgConf.US](<http://www.pgconf.us>), do you have your [talk submitted yet?](<http://www.pgconf.us/2016/submit/>). The deadline is the end of this week. You don't want to be the only community member left in the cold because you procrastinated do you?

---
[View this page online](https://www.commandprompt.com/blog/scale_14x_postgresql_mini-conf_pgconfus_and_nycpug/)

---

# 13:58, the sun is shining, the sky is blue, and I just had the best tomatoes -- ever. Welcome to Vienna and PgConf.eu

> I am sitting in a glorious (although not the conference) hotel, writing this article. It is 13:58, at least it is where I am from, the great Pacific Northwest.…

I am sitting in a glorious (although not the conference) hotel, writing this article. It is 13:58, at least it is where I am from, the great Pacific Northwest. I must admit, I miss the trees although I hear there are lots of them if you leave the city. What is there to say about this great city that the European community picked for their latest conference? 

First and probably obvious, it is full of history. Second, don't bother doing anything on a Sunday. Third, smoking is allowed in restaurants (one ridiculous thing I have noted). Fourth, they sell water that has, "Natural Oxygen". Fifth, it feels a lot like Paris but the people seem friendlier. Lastly, this is a fantastic choice of venue. 

This is my third Europe event with the community. I am teaching on PostgreSQL backups. I was also in Ireland as well as Paris years ago. The buzz around the conference this year has been loud. It feels like a fan that you turn on to drown out the traffic downstairs. Everywhere in the community you can hear whispers of this upcoming event. It is exciting and I believe this will be the largest, best executed event in the European community history. I will report more on that after the conference starts. 

If you are here in this beautiful city (especially if you are from the states), full of wonder, history, and culture please don't hesitate to say hi to someone, open a door or even smile (although that is apparently a weird social faux pas). 

Thank you to the European community for having the American heathens present!

---
[View this page online](https://www.commandprompt.com/blog/1358_the_sun_is_shining_the_sky_is_blue_and_i_just_had_the_best_tomatoes_--_ever_welcome_to_vienna_and_pgconfeu/)

---

# PostgreSQL 9.5, Community, Features and More!

> I spoke at the Whatcom PUG meeting last night on PostgreSQL 9.5. This is my fourth time giving this talk. The previous locations were DCPUG, PhillyPUG, and NYC…

I spoke at the Whatcom PUG meeting last night on PostgreSQL 9.5. This is my fourth time giving this talk. The previous locations were DCPUG, PhillyPUG, and NYCPUG last month. The talk was well received and this was Whatcom PUG's best turn out yet! We even had an Open Street Map developer visit from Vancouver B.C. 

The presentation does discuss some of the more popular features of 9.5, but as a whole it discusses the state of PostgreSQL as of 9.5. That includes features, community, and process. I think the most important item is the user interaction. At each presentation location I brought up the fact that PostgreSQL has no bug/issue tracker. This led to the long threads currently being discussed on pgsql-hackers about having an issue tracker. If PostgreSQL 9.5 doesn't land for another 9 months (it will be sooner; we are at Beta) and instead we received proper tracking of issues, I would be plenty happy. 

I used to do a lot more technical speaking, but lately I am finding more satisfaction in engaging users. One of the things that I have found out about the user groups is a lot of the attendees do not subscribe to the lists; they are community members by usage not contribution. However, without our users PostgreSQL is just another once upon a time (remember XFree86?) project. Thankfully, PostgreSQL is very good about listening to its users and knowing that engaging them is going to lead to a better product. 

Good times! I am off to go rock climbing. 

P.S. Another round of thanks to Bruce Momjian; without him the presentation would have taken a lot more time!

---
[View this page online](https://www.commandprompt.com/blog/postgresql_95_community_features_and_more/)

---

# Tip for West side U.S. folks going to PgConf.EU in October

> This tip works very well for me because of my physical location (Bellingham, WA) but it would also work reasonably well for anyone flying from Denver-&gt;West Coa…

This tip works very well for me because of my physical location (Bellingham, WA) but it would also work reasonably well for anyone flying from Denver->West Coast including places such as Houston. It does take a little bit of patience though. 

A normal trip for myself would mean driving down to SEA which is 90 minutes to 2 hours. This year, I decided on whim to see what it would take to fly out of YVR (Vancouver, B.C.) which is only 60 minutes driving. 

Since I would be flying out of YVR on a non-connecting flight, I paid Canadian Dollars. For those that haven't been paying attention, the U.S. dollar has been doing very well lately (even overtaking the euro on some days). For example, the Canadian dollar is 27% cheaper right now than the U.S. dollar and thus my flight was 27% cheaper. 

You can't connect to YVR, you must fly out of YVR. Therefore if you are in the aforementioned areas, you would fly into Seattle or Bellingham and then drive to YVR to connect to a new flight. Be patient and give yourself enough time (to not miss your flight), and you are going to save a lot of money. 

Cheerio and make sure you [register for my class!](<http://www.postgresql.eu/events/sessions/pgconfeu2015/session/959-elevating-your-confidence-with-the-elephants-restoration-capabilities/>)

---
[View this page online](https://www.commandprompt.com/blog/tip_for_west_side_us_folks_going_to_pgconfeu_in_october/)

---

# Elevating your confidence with the Elephant's restoration capabilities

> In the beginning

There was Unix, Linux and Windows. They all run on hardware and that hardware all has bugs. What is the best way to work around hardware bu…

**In the beginning**

There was Unix, Linux and Windows. They all run on hardware and that hardware all has bugs. What is the best way to work around hardware bugs? Backups. 

You haven't had bad hardware, only bad developers? That's o.k., we have a solution to them too. It is called backups. 

You haven't had bad hardware or bad developers, just bosses who still demand to have direct access to the data even though they haven't proven an ability to extract useful information without an extreme amount of hand holding? That's o.k., we have a solution to them too. It is called backups. 

You haven't had any of the above? Lucky you! Can we move to your country or will you share whatever it is that you are putting in your tea? It sounds fantastic. 

Either way, we have a solution to your data confidence, it is called backups and that is what this training is about. 

[See more here!](<http://www.postgresql.eu/events/sessions/pgconfeu2015/session/959-elevating-your-confidence-with-the-elephants-restoration-capabilities/>)

[Register here!](<http://2015.pgconf.eu/registration/>)

---
[View this page online](https://www.commandprompt.com/blog/elevating_your_confidence_with_the_elephants_restoration_capabilities/)

---

# A new user discovers the PostgreSQL public schema

> A new user of PostgreSQL recently discovered that PostgreSQL allows any PostgreSQL user to create objects and data by default.[1] I know you are saying, &quot;What.…

A new user of PostgreSQL recently discovered that PostgreSQL allows any PostgreSQL user to create objects and data by default.[1] I know you are saying, "What... PostgreSQL has some of the most advanced and flexible security in the industry!" and you are absolutely correct, we do. However, once you can connect to PostgreSQL, you have some interesting default capabilities. Consider the following example: 
    
    
    postgres@sqitch:/# psql -U postgres
    psql (9.2.11)
    Type "help" for help.
    
    postgres=# create user foo;
    CREATE ROLE
    postgres=# \q
    

No biggy, we created a user foo as the super user postgres. All is good. However, what can that user foo do? 
    
    
    postgres@sqitch:/# psql -U foo postgres
    psql (9.2.11)
    Type "help" for help.
    postgres=> create table bar (id text);
    CREATE TABLE
    postgres=> 
    

What? Yes. I connected to the postgres database as the unprivileged user foo. I then proceeded to create a table and as I own that table, I can insert data into that table. If we continue the example: 
    
    
    postgres=# \z bar
                              Access privileges
     Schema | Name | Type  | Access privileges | Column access privileges 
    --------+------+-------+-------------------+--------------------------
     public | bar  | table |                   | 
    (1 row)
    

As noted above there are zero access privileges on the table bar. Now let's create a new unprivileged user, baz. 
    
    
    postgres=# create user baz;
    CREATE ROLE
    postgres=# \q
    

Now we reconnect as the user baz and try to insert data into table bar. 
    
    
    postgres@sqitch:/# psql -U baz postgres
    psql (9.2.11)
    Type "help" for help.
    
    postgres=> insert into bar values ('1');
    ERROR:  permission denied for relation bar
    postgres=> 
    

The error represents exactly what should happen but I could just create a new table as user baz and start adding data. As a very simple example of why this could have undesirable results, try this as the user foo: 
    
    
    postgres@sqitch:/#psql -U foo postgres;
    psql (9.2.11)
    Type "help" for help.
    
    postgres=> insert into bar values (generate_series(1, 1000000000));
    

1\. [postgres db permissions](<http://www.postgresql.org/message-id/DM2PR0701MB131214DA4765AF4D61C29B3AE4B50@DM2PR0701MB1312.namprd07.prod.outlook.com>)

---
[View this page online](https://www.commandprompt.com/blog/a_new_user_discovers_the_postgresql_public_schema/)

---

# Let's delete contrib!

> There has been a lot of discussion about the upcoming extension pg_audit and whether or not it should be in contrib. You can read about that here. The end resu…

There has been a lot of discussion about the upcoming extension pg_audit and whether or not it should be in contrib. You can [read about that here.](<http://www.postgresql.org/message-id/6454.1431625129@sss.pgh.pa.us>) The end result of the discussion is that pg_audit is going to be reverted and not in contrib. There were plenty of technical reasons why people didn't want it in contrib but I have a different reason. It is an extension. It doesn't need to be in contrib. In fact, I argue that because of pgxs and extensions we don't need contrib at all. If you don't follow the mailing lists my argument is blow and please feel free to comment here. The discourse is very much needed on this topic. 

> Hello, 
> 
> This is a topic that has come up in various ways over the years. After the long thread on pg_audit, I thought it might be time to bring it up again. 
> 
> Contrib according to the docs is: 
> 
> "These include porting tools, analysis utilities, and plug-in features that are not part of the core PostgreSQL system, mainly because they address a limited audience or are too experimental to be part of the main source tree. This does not preclude their usefulness." 
> 
> It has also been mentioned many times over the years that contrib is a holding tank for technology that would hopefully be pushed into core someday. 
> 
> What I am suggesting: 
> 
> 1\. Analyze the current contrib modules for inclusion into -core. A few of these are pretty obvious: 
> 
> pg_stat_statements   
>  citext   
>  postgres_fdw   
>  hstore   
>  pg_crypto   
>  [...]   
> 
> 
> I am sure there will be plenty of fun to be had with what should or shouldn't be merged into core. I think if we argue about the guidelines of how to analyze what should be in core versus the merits of any particular module, life will be easier. Here are some for a start: 
>
>> A. Must have been in contrib for at least two releases  
>  B. Must have visible community (and thus use case)  
> 
> 
> 2\. Push the rest out into a .Org project called contrib. Let those who are interested in the technology work on them or use them. This project since it is outside of core proper can work just like other extension projects. Alternately, allow the maintainers push them wherever they like (Landscape, Github, Savannah, git.postgresql.org ...). 
> 
> Why I am suggesting this: 
>
>> 1\. Less code to maintain in core   
>  2\. Eliminates the mysticism of contrib   
>  3\. Removal of experimental code from core   
>  4\. Most of the distributions package contrib separately anyway   
>  5\. Some of core is extremely small use case (sepgsql, tsearch2, lo ...)   
>  6\. Finding utilities for PostgreSQL used to be harder. It is rather dumb simple teenage snapchat user easy now.   
>  8\. Isn't this what pgxs is for?   
>  9\. Everybody hates cleaning the closet until the end result.   
>  10\. Several of these modules would make PostgreSQL look good anyway (default case insensitive index searching with citext? It is a gimme)   
>  11\. Contrib has been getting smaller and smaller. Let's cut the cord.   
>  12\. Isn't this the whole point of extensions?   
> 
> 
> Sincerely, 
> 
> jD

---
[View this page online](https://www.commandprompt.com/blog/lets_delete_contrib/)

---

# Updating the .Org docs on backups

> I spent a great deal of time working through the SQL DUMP portion of the 9.5devel docs this past week. Below is the current text of what I have and it would be…

I spent a great deal of time working through the SQL DUMP portion of the 9.5devel docs this past week. Below is the current text of what I have and it would be great if my readers would take a look and offer some thoughtful feedback. What would you like to see added? What would you like to see changed? Please note that this is reference documentation not tutorial documentation. 

This is just the straight HTML dump that is generated from Docbook but since it is inline the links won't work. [The current -devel docs are here](<http://www.postgresql.org/docs/devel/static/backup-dump.html>) and the updated version I am working is below: 

* * *

# 24.1. SQL Dump

PostgreSQL provides the program pg_dump for generating a backup file with SQL commands that, when fed back to the server, will recreate the database in the same state as it was at the time of the dump. The basic usage of pg_dump is:
    
    
    pg_dump _-C_ _-F_ p _-f_ outfile dbname
    

The use of `-C` ensures that the dump file will contain the requisite CREATE DATABASE command within the dump file. The use of `_-F_`` p` ensures that you are using the plain text format and the use of `_-f_` allows you to specify the name of the file the dump will be written to. It is also possible for pg_dump to create files in other formats that allow for parallelism and fine-grained control of object backup or restoration. For more details on all options available to pg_dump please refer to the pg_dump reference page.

The pg_dump application requires read access to all objects within the database that it will be operating with. This generally requires database super-user access. It is possible for any database user to use pg_dump to backup the objects that they own regardless of super-user access. This can be achieved using options such as `_-n_` `schema` or `_-t_` `table`.

The primary advantage of using pg_dump over the other backup methods described is that pg_dump output is architecture independent. A backup made with pg_dump can generally be moved between operating systems and different architectures (32bit, 64bit, Sparc, Intel). Whereas file-level backups and continuous archiving are both server-version-specific.

The text files created by pg_dump are internally consistent, meaning, the dump represents a snapshot of the database at the time pg_dump began running. pg_dump does not block other operations on the database while it is working. (Exceptions are those operations that need to operate with an exclusive lock, such as most forms of `ALTER TABLE`.)

> **Note:** Like any other PostgreSQL client application, pg_dump will by default connect with the database user name that is equal to the current operating system user name. To override this, either specify the `_-U_` option or set the environment variable `PGUSER`.

## 24.1.1. Advanced pg_dump

The pg_dump application provides other formats. The most notable are the use of `_-F_` `c` or `_-F_` `d`. The use of the `custom` format (` _-F_` `c`) is an excellent option for smaller databases when you need fine grained control of the objects you chose to restore. The use of the `directory` format (` _-F_` `d`) allows for parallel connection based backups. If you are performing a backup with many objects and using pg_dump then the `directory` format will be the most efficient. This option also allows for fine grained control of the objects you chose to restore.

If PostgreSQL was built on a system with the zlib compression library installed, the custom dump format will compress data as it writes it to the output file. This will produce dump file sizes similar to using `gzip`, but it has the added advantage that tables can be restored selectively.

**Example 24-1. Backup a single table**
    
    
      pg_dump _-U_ user _-h_ host1 _-F_ c _-f_ outfile _-t_ table1 dbname
      
    

**Example 24-2. Using wildcards with table list**
    
    
      pg_dump _-U_ user _-h_ host1 _-F_ c _-f_ outfile _-t_ table* dbname
      
    

**Example 24-3. Using parallelism and a wildcard table list**
    
    
      pg_dump _-U_ user _-h_ host1 _-F_ d _-f_ outfile _-t_ table* _-j_ 8 dbname
      
    

> **Note:** The use of the `custom` or `directory` pg_dump formats requires the use of pg_restore and will not work with psql. There is more information on using pg_restore in section Section 24.1.3.

## 24.1.2. Restoring the Dump

The psql application is the default client that ships with PostgreSQL. It is also the default application used when restoring text based dumps created by the pg_dump application. For details information on psql please see psql. For the purposes of restoring a dump the basic usage is:
    
    
    psql _-f_ infile _-d_ dbname 
    

> **Note:** If you omitted `_-C_` when executing pg_dump the `CREATE DATABASE` command will not be in the text file. You will need to create the database yourself from `template0` before the executing the restore (e.g., with createdb `_-T_` `template0` `dbname`).

**Warning**  
---  
  
pg_dump does not backup users, roles and other global objects. To properly backup global objects you must use pg_dumpall with the `_-g_` parameter. If you do not restore the globals before the text based dump, the database will implicitly restore all objects as the owner passed by `_-U_` `username`. If `_-U_` is not passed then the operating system user executing psql will be used.  
  
> **Important:** The dumps produced by pg_dump are relative to `template0`. This means that any languages, procedures, etc. added via `template1` will also be dumped by pg_dump. As a result, when restoring, if you are using a customized `template1`, you must create the empty database from `template0`, as in the example above.

After restoring a backup, one should execute ANALYZE on each database so the query optimizer has useful statistics; see Section 23.1.3 and Section 23.1.6 for more information. For more advice on how to load large amounts of data into PostgreSQL efficiently, refer to Section 14.4.

## 24.1.3. Advanced restore

**Example 24-4. Using pipes to restore to new server**
    
    
       pg_dump _-h_ host1 _-d_ dbname | psql _-h_ host2 _-d_ dbname
      
    

If one is using the `custom`, `directory` or `tar` formats the restore command is pg_restore. The pg_restore program has many benefits over the use psql including fine grained object restore and parallelism.

**Example 24-5. Extracting a text dump from a custom format backup**

The following will extract the backup to the standard output. The use of `_-F_` is optional as pg_restore should be able to detect the format.
    
    
       pg_restore _-F_ c infile 
      
    

**Example 24-6. Restoring a single table**
    
    
       pg_restore _-U_ username _-h_ host1 _-d_ dbname _-t_ table infile
      
    

**Example 24-7. Using parallelism to restore databases**

The use of parallelism will normally allow databases to restore much faster than a single connection based restore. The restore will only execute as quickly as it can restore your largest table but for databases with many objects it is the fastest pg_dump based restore.
    
    
       pg_restore _-U_ username _-h_ host1 _-d_ dbname _-t_ table _-j_ 8 infile
      
    

## 24.1.4. Using pg_dumpall

pg_dump dumps only a single database at a time, and it does not dump information about roles or tablespaces (because those are cluster-wide rather than per-database). To support convenient dumping of the entire contents of a database cluster, the pg_dumpall program is provided. pg_dumpall backs up each database in a given cluster, and also preserves cluster-wide data such as role and tablespace definitions. The basic usage of this command is:
    
    
    pg_dumpall > _outfile_
    

The resulting dump can be restored with psql:
    
    
    psql -f _infile_ postgres
    

It is necessary to have database superuser access when using a pg_dumpall dump. The superuser acess is required to restore the role and tablespace information.

pg_dumpall works by emitting commands to re-create roles, tablespaces, and empty databases, then invoking pg_dump for each database. This means that while each database will be internally consistent, the snapshots of different databases are not sychronized.

Cluster-wide data can be dumped alone using the pg_dumpall `--globals-only` option. This is necessary to fully backup the cluster if running the pg_dump command on individual databases.

> **Note:** If you use tablespaces, make sure that the tablespace paths in the dump are appropriate for the new installation.

## 24.1.5. Handling Large Databases

The act of backing up a normal sized database is relatively simple. The act of backing up a large database (>500GB) can be challenging. Fortunately, PostgreSQL is very flexible in its ability to provide a reliable backup. Here is a list of things you might want to consider when backing up a large database.

  1. Use the `directory` format and the `_-j_` `NUM` option. This will ensure the quickest and most flexible pg_dump style backup.

  2. Use `continuous archiving` as described in Section 24.2. You can then backup the replica without putting load on the master.

  3. Use pg_basebackupas described in Section 24.2.2.




**Warning**  
---  
  
The pg_dump methods utilize at least one connection if not many connections (via `_-j_` ). They also utilize long running transactions. This can cause problems with maintenance. If you find that your database contains a lot of growing bloat consider using a backup method on the master that does not require pg_dump.  
  
* * *

Prev | Home | Next  
---|---|---  
Backup and Restore | Up | Continuous Archiving and Point-in-Time Recovery (PITR)

---
[View this page online](https://www.commandprompt.com/blog/updating_the_org_docs_on_backups/)

---

# WhatcomPUG meeting on 04/21. Start date, end date, calculate

> The PUG meeting was good. We now have a consistent if small group that are attending. Before the presentation we spoke about possibly moving the group to meetu…

The PUG meeting was good. We now have a consistent if small group that are attending. Before the presentation we spoke about possibly moving the group to meetup to get a little better visibility. G+ Communities are awesome but Meetup seems to be where the people in the area look. 

The presentation was provided by Eric Worden who happens to be a CMD employee. The talk overall is very good and provided a lot of information that I didn't know about dates. It also lead to the development of a new PostgreSQL extension (more on that at a later time). 

The most interesting part of the talk to me was the use of a dimensions table to make date queries much, much faster. Either he or I will be submitting a blog post on that feature alone. 

If you are interested in seeing what he has to say you can visit us at the Whatcom PgDay being hosted at LinuxFestNorthwest this weekend!

---
[View this page online](https://www.commandprompt.com/blog/whatcompug_meeting_on_0421_start_date_end_date_calculate/)

---

# Reflections on PgConf.US 2015

> Saturday the 18th of April, I woke up to the following:
 

It was one of those moments that you realize just how blessed of a life you have. A moment where …

Saturday the 18th of April, I woke up to the following:  


 

[![](https://lh4.googleusercontent.com/-yLFj5rFVNgI/VTPrxXjXB9I/AAAAAAAAShU/Xm-PDGFF1gw/w1524-h857-no/IMG_4973.JPG)  
](<https://lh4.googleusercontent.com/-yLFj5rFVNgI/VTPrxXjXB9I/AAAAAAAAShU/Xm-PDGFF1gw/w1524-h857-no/IMG_4973.JPG>)

It was one of those moments that you realize just how blessed of a life you have. A moment where you stop and realize that you must have done something right, at least once. I was with my all of my ladies, there were no other people at the camp site, the weather was clear and it was set to hit 68F. The only sound was the gentle lapping of water and the occasional goose.

It was at this time that I was able to finally take a step back and reflect on [PgConf.US](<http://www.pgconf.us/>). This conference meant a lot to me professionally. I didn't organize it. I only spoke at it, Command Prompt sponsored, and I occasionally offered feedback to the conference committee (as it is run by PgUS) via PgUS board meetings. This conference has become everything (and more) I tried to make the United States PostgreSQL Conference series. It is a conference of the best, the brightest and most importantly the users of our beloved elephant. In the United States, it is "The" PostgreSQL Conference.

That isn't to say there aren't other PostgreSQL conferences in the states. There are at least two others that run, but somehow after this latest conference I feel they are destined to niche attendance. There is nothing wrong with that and frankly we need the niche conferences. They fill a hole, else people wouldn't attend. It is just that experiencing the level of effort and greatness that was created by Jonathan and Jim was truly something awesome to behold.

They aren't paid to run these conferences. They do it because they want to help our community. They do it for free and speaking as somebody who has run more PostgreSQL conferences than any other current PostgreSQL conference organizer in the U.S., it is a thankless job. It is a volunteer effort that everyone should take a moment to thank them for. Jonathan, Jimmy: Thank you for all your efforts. The community could not have had such a great conference without you.

I have only two constructive feedback points for the organizers:

  1. Do not allow tutorials based on sponsorship. Allow them based on merit. You will get a much more positive return from them.
  2. Move the cocktail party offsite where there will be full food available at a more reasonable price.



I have three constructive feedback points for other sponsors:

  1. Plan your events in conjunction with the conference. Don't take attendees away from a conference for your invitation only event.
  2. Don't over staff your booths. Even a large both (10x10) only has room for ~ 3 people.
  3. Lighten up. This is supposed to be fun.



Other than that, I have only praise for the conference. Command Prompt has already made back all of the money it spent on sponsoring and traveling. We acquired quite a few new customers and are exceedingly happy with the result. Expect us to sponsor again.

You should also expect that I will speak again. I gave away three excellent bottles of whiskey to attendees of my presentation. I enjoy speaking at this conference because this conference understands what a conference is really about.

What else would I say about the conference? I had a blast. I would definitely go again. I will do everything I can to help the excellent organization team grow not just 25%, but 50% next year. What if the community stepped up and planned on attending "PgConf U.S." in 2016? The community should step up, promote and advocate throughout every community they are involved in. It's worth it.

Let's get more of everyone involved and save them from the nefarious reaches of those "other" databases.

---
[View this page online](https://www.commandprompt.com/blog/reflections_on_pgconfus_2015/)

---

# WhatcomPUG meeting last night on: sqitch and... bitcoin friends were made!

> Last night I attended the second WhatcomPUG. This meeting was about Sqitch,  a interesting database revision control mechanism. The system is  written in Perl …

Last night I attended the second [WhatcomPUG](<https://plus.google.com/communities/116781216881095067633>). This meeting was about [Sqitch](<http://www.sqitch.org/>), a interesting database revision control mechanism. The system is written in Perl and was developed by David Wheeler of PgTap fame. It looks and feels like git. As it is written in Perl it definitely has too many options. That said, what we were shown works, works well and appears to be a solid and thorough system for the job. 

I also met a couple of people from [CoinBeyond](<http://www.coinbeyond.com/>). They are a point-of-sale software vendor that specializes in letting "regular" people (read: not I or likely the people reading this blog) use Bitcoin! 

That's right folks, the hottest young currency in the market today is using the hottest middle aged technology for their database, PostgreSQL. It was great to see that they are also located in Whatcom County. The longer I am here, the more I am convinced that Whatcom County (and especially Bellingham) is a quiet tech center working on profitable ventures without the noise of places like Silicon Valley. I just keep running into people doing interesting things with technology. 

Oh, for reference: 

  * Twitter: [@coinbeyond](<http://twitter.com/coinbeyond>)
  * Facebook: [CoinBeyond](<http://facebook.com/CoinBeyond>)
  * LinkedIn: [Linkedin](<http://linkedin.com/company/coinbeyond>)

---
[View this page online](https://www.commandprompt.com/blog/whatcompug_meeting_last_night_on_sqitch_and_bitcoin_friends_were_made/)

---

# Stomping to PgConf.US: Webscale is Dead; PostgreSQL is King! A challenge, do you accept?

> I submitted to PgConf.US. I submitted talks from my general pool. All of them have been recently updated. They are also all solid talks that have been well rec…

I submitted to [PgConf.US](<http://www.PgConf.US/>). I submitted talks from my general pool. All of them have been recently updated. They are also all solid talks that have been well received in the past. I thought I would end up giving my, "Practical PostgreSQL Performance: AWS Edition" talk. It is a good talk, is relevant to today and the community knows of my elevated opinion of using AWS with PostgreSQL (there are many times it works just great, until it doesn't and then you may be stuck). 

I also submitted a talk entitled: "Suck it! Webscale is Dead; PostgreSQL is King!". This talk was submitted as a joke. I never expected it to be accepted, it hadn't been written, the abstract was submitted on the fly, improvised and in one take. Guess which talk was accepted? "Webscale is Dead; PostgreSQL is King!". They changed the first sentence of the title which is absolutely acceptable. The conference organizers know their audience best and what should be presented.

What I have since learned is that the talk submission committee was looking for dynamic talks, dynamic content, and new, inspired ideas. A lot of talks that would have been accepted in years past weren't and my attempt at humor fits the desired outcome. At first I thought they were nuts but then I primed the talk at [SDPUG/PgUS PgDay @ Southern California Linux Expo.](<http://www.socallinuxexpo.org/scale/13x>)

I was the second to last presenter on Thursday. I was one hour off the plane. I was only staying the night and flying home the next morning, early. The talk was easily the best received talk I have given. The talk went long, the audience was engaged, laughter, knowledge and opinions were abound. When the talk was over, the talk was given enthusiastic applause and with a definite need for water, I left the room.

I was followed by at least 20 people, if not more. I don't know how many there were but it was more than I have ever had follow me after a talk before. I was deeply honored by the reception. One set of guys that approached me said something to the effect of: "You seem like you don't mind expressing your opinions". At this point, some of you reading may need to get a paper towel for your coffee because those that know me, know I will readily express an opinion. I don't care about activist morality or political correctness. If you don't agree with me, cool. Just don't expect me to agree with you. My soapbox is my own, rent is 2500.00 a minute, get in line. I digress, what did those guys ask me about? [Systemd](<http://www.freedesktop.org/wiki/Software/systemd/>), I don't think they were expecting my answer, because I don't really have a problem with Systemd.

Where am I going with this post? I am stomping my way to PgConf.US with an updated version of this talk (You always learn a few things after giving a performance). I am speaking in the first slot on Friday and I am going to do everything I can to bring it. I can't promise to be the best, I can promise to do everything in my power to be my best. I am being recorded this time. My performance will be on the inner tubes forever. I have no choice.

A challenge, do you accept?

I challenge all speakers at this voyage of [PgConf.US](<http://www.pgconf.us/>) to take it up a notch. If you were accepted, you have a responsibility to do so. Now, now, don't get me wrong. I am not suggesting that you put on a chicken suit and Fox News t-shirt to present. I am however suggesting that if you are a monotone speaker, try not to be. If you are boring, your audience will be bored and that is the last thing the conference, you or the audience wants. So speak from your diaphragm, engage the audience and make their time worth it!

---
[View this page online](https://www.commandprompt.com/blog/stomping_to_pgconfus_webscale_is_dead_postgresql_is_king_a_challenge_do_you_accept/)

---

# PostgreSQL is King! Last week was quite busy being a servant.

> Last week was one of the busiest community weeks I have had in a long time. It started with an excellent time in Vancouver, B.C. giving my presentation, &quot;An ev…

Last week was one of the busiest community weeks I have had in a long time. It started with an excellent time in Vancouver, B.C. giving my presentation, "An evening with PostgreSQL!" at VanLUG. These are a great group of people. They took all my jibes with good humor (Canadians gave us Maple Syrup, we gave them Fox News) and we enjoyed not only technical discussion but discussions on technology in general. It is still amazing to me how many people don't realize that Linux 3.2 - 3.8 is a dead end for random IO performance. 

After VanLUG I spent the next morning at the Vancouver Aquarium with my ladies. Nothing like beautiful weather, dolphins and jelly fish to brighten the week. Once back in Bellingham, we moved on to a WhatcomPUG meeting where I presented, "Practical PostgreSQL: AWS Edition". It was the inaugural meeting but was attended by more than just the founders which is a great start! 

I got to rest from community work on Wednesday and instead dug my head into some performance problems on a client High Availability Cluster. It is amazing that even with proper provisioning how much faster ASYNC rep is over SYNC rep. Some detailed diagnosis and proving data demonstrated, we switched to ASYNC rep and all critical problems were resolved. 

On Thursday it was off to Southern California Linux Expo where I presented, "Suck it! Webscale is dead; long live PostgreSQL!". The room was packed, people laughed and for those who might have been offended, I warned you. Your offense is your problem. Look inside yourself for your insecurities! All my talks are PG-13 and it is rare that I will shy away from any topic. My disclosure aside, I had two favorite moments: 

  1. When someone was willing to admit they hadn't seen Terminator. I doubt that person will ever raise his hand to one of my questions again. 
  2. When Berkus (who knew the real answer) suggested it was Elton John that wrote the lyrics at the end of the presentation. 



After I spent the evening with JimmyM (BigJim, my brother), Joe Conway of SDPUG/Credativ , Jim Nasby of the fledgling bird that is Blue Treble and the very enjoyable, I don't remember her name but she works at Enova (a well known PostgreSQL installation). Flying out the next morning at 8am probably should have been avoided though. 

I am glad to be on the ground for the next few weeks before I head off to PgConf.US. It is looking like this conference is once again prove why PostgreSQL is King! Bring your people from all the lands, you are about to enter utopia.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_is_king_last_week_was_quite_busy_being_a_servant/)

---

# AWS performance: Results included

> I am not a big fan of AWS. It is a closed platform. It is designed to be the Apple of the Cloud to the Eve of Postgres users. That said, customers drive busine…

I am not a big fan of AWS. It is a closed platform. It is designed to be the Apple of the Cloud to the Eve of Postgres users. That said, customers drive business and some of our customers use AWS, even if begrudgingly. Because of these factors we are getting very good at getting PostgreSQL to perform on AWS/EBS, albeit with some disclosures: 

  1. That high IO latency is an acceptable business requirement. 
  2. That you are willing to spend a lot of money to get performance you can get for less money using bare metal: rented or not. Note: This is a cloud issue not an AWS issue. 



Using the following base configuration (see adjustments for each configuration after the graphic): 
    
    
    port = 5432                             
    max_connections = 500                   
    ssl = true                              
    shared_buffers = 4GB                    
    temp_buffers = 8MB                      
    work_mem = 47MB                         
    maintenance_work_mem = 512MB            
    wal_level = hot_standby                 
    synchronous_commit = on         
    commit_delay = 0                        
    commit_siblings = 5                     
    checkpoint_segments = 30               
    checkpoint_timeout = 10min              
    checkpoint_completion_target = 0.9      
    random_page_cost = 1.0                  
    effective_cache_size = 26GB
    

Each test was run using pgbench against 9.1 except for configuration 9 which was 9.3:   

    
    
    pgbench -F 100 -s 100 postgres -c 500 -j10 -t1000 -p5433

Here are some of our latest findings: 

![](https://files.commandprompt.com/jd/tps9.3.png)

The AWS configuration is: 

> 16 Cores  
>  30G of memory (free -h reports 29G)   
>  (2) PIOPS volumes at 2000 IOPS a piece.   
>  The PIOPS volumes are not in A RAID and are mounted separately.   
>  The PIOPS volumes are formatted with xfs and default options   
>  The PIOPS volumes were warmed. 

  1. Configuration 1: 

> $PGDATA and pg_xlog on the same partition   
>  synchronous_commit = on   
> 

  2. Configuration 2: 

> $PGDATA and pg_xlog on the same partition   
>  synchronous_commit = off   
> 

  3. Configuration 3: 

> $PGDATA and pg_xlog on the same partition   
>  synchronous_commit = off   
>  commit_delay = 100000   
>  commit_siblings = 50   
> 

  4. Configuration 4: 

> $PGDATA and pg_xlog on the same partition   
>  synchronous_commit = off   
>  commit_delay = 100000   
>  commit_siblings = 500   
> 

  5. Configuration 5: 

> $PGDATA and pg_xlog on different partitions   
>  synchronous_commit = off   
>  commit_delay = 100000   
>  commit_siblings = 500   
> 

  6. Configuration 6: 

> $PGDATA and pg_xlog on different partitions   
>  synchronous_commit = on   
>  commit_delay = 100000   
>  commit_siblings = 500   
> 

  7. Configuration 7: 

> $PGDATA and pg_xlog on different partitions   
>  synchronous_commit = on   
>  commit_delay = 0   
>  commit_siblings = 5   
> 

  8. Configuration 8: 

> $PGDATA and pg_xlog on different partitions   
>  synchronous_commit = on   
>  checkpoint_segments = 300   
>  checkpoint_timeout = 60min   
> 

  9. Configuration 9: 

> $PGDATA and pg_xlog on different partitions   
>  PostgreSQL 9.3   
>  synchronous_commit = on   
>  checkpoint_segments = 300   
>  checkpoint_timeout = 60min   
>

---
[View this page online](https://www.commandprompt.com/blog/aws_performance_results_included/)

---

# Don't kill yourself

> As a PostgreSQL consultant you end up working with a lot of different types of
clients and these clients tend to all have different requirements. One client
ma…

As a PostgreSQL consultant you end up working with a lot of different types of clients and these clients tend to all have different requirements. One client may need high-availability, while another needs a DBA, while yet another is in desperate need of being hit with a clue stick and while it is true that there can be difficult clients, there is no bad client. 

> What!!! Surely you can't be serious? 
> 
> Don't call me shirley. 
> 
> I am absolutely serious. 

A bad client is only a reflection of a consultants inability to manage that client. It is true that there are difficult clients. They set unrealistic expectations, try to low ball you by with things like: "We can get your expertise for 30.00/hr from India" or my favorite: calling you directly when it is after hours to "chat". 

How are these not bad clients? They are not bad clients because it is you that controls the relationship with the client. You as the consultant have to set proper boundaries with the client to insure that the relationship as a whole is positive and profitable. If you can't manage that relationship you have two choices: 

  1. Hire someone who can 
  2. Fire the client 



Woah! Fire the client? Yes. Terminate the relationship with the client. 

It is always amazing to me how many people can't fathom the idea of firing a client. It is always some sacred vow that a client can fire you but you are left holding the bag, somehow that bag is filled with the feces of some dog and you are expected to light it on fire and leave it on the porch of some unsuspecting high-school football coach.[1] 

The counter argument to this is usually "I need the money". This is a valid argument but do you need the money so badly that you are willing to sacrifice your health or your relationships? It is astonishing how many consultants are willing to do exactly that. In the words of the legendary band Big Fun, "Suicide, don't do it"[2]. 

The better you manage a client, the better the relationship. Good luck! 

  1. http://en.wikipedia.org/wiki/All_the_Right_Moves_(film)  

  2. https://www.youtube.com/watch?v=i-w1GeH8KPU

---
[View this page online](https://www.commandprompt.com/blog/dont_kill_yourself/)

---

# Along the lines of GCE, here are some prices

> I was doing some research for a customer who wanted to know where the real value to performance is. Here are some pricing structures between GCE, AWS and Softl…

I was doing some research for a customer who wanted to know where the real value to performance is. Here are some pricing structures between GCE, AWS and Softlayer. For comparison Softlayer is bare metal versus virtual. 

GCE: 670.00   
16 CPUS   
60G Memory   
2500GB HD space 

GCE: 763.08   
16 CPUS  
104G Memory  
2500GB HD space 

Amazon: 911.88  
16 CPUS  
30G Memory   
3000GB HD Space 

Amazon: 1534.00   
r3.4xlarge  
16 CPUS   
122.0 Memory   
SSD 1 x 320   
3000GB HD Space 

Amazon: 1679.00   
c3.8xlarge   
32 CPUS   
60.0 Memory   
SSD 2 x 320   
3000GB HD Space   


None of the above include egress bandwidth charges. Ingress is free. 

Softlayer: ~815 (with 72GB memory ~ 950)   
16 Cores   
RAID 10   
4TB (4 2TB drives)   
48GB Memory   


Softlayer: ~1035 (with 72GB memory ~ 1150)  
16 Cores   
RAID 10   
3TB (6 1TB drives, I also looked at 8-750GB and the price was the same. Lastly I also looked at using 2TB drives but the cost is all about the same)   
48GB Memory

---
[View this page online](https://www.commandprompt.com/blog/along_the_lines_of_gce_here_are_some_prices/)

---

# GCE, A little advertised cloud service that is perfect for PostgreSQL

> Maybe...

I have yet to run PostgreSQL on GCE in production. I am still testing it but I have learned the following:


A standard provision disk for GCE will g…

Maybe... 

I have yet to run PostgreSQL on [GCE](<https://cloud.google.com/products/compute-engine/>) in production. I am still testing it but I have learned the following: 

  1. A standard provision disk for GCE will give you ~ 80MB/s random write. 
  2. A standard SSD provisioned disk for GCE will give you ~ 240MB/s. 



Either disk can be provisioned as a raw device allowing you to use Linux Software Raid to build a RAID 10 which even further increases speed and reliability. Think about that, 4 SSD provisioned disks in a RAID 10... 

The downside I see outside of the general arguments against cloud services (shared tenancy, all your data in a big brother, lack of control over your resources, general distaste for $vendor, or whatever else we in our right minds can think up) is that GCE is current limited to 16 virtual CPUS and 104GB of memory. 

What does that mean? Well it means that it is likely that GCE is perfect for 99% of PostgreSQL workloads. By far the majority of PostgreSQL need less than 104GB of memory. Granted, we have customers that have 256GB, 512GB and even more but those are few and far between. 

It also means that EC2 is no longer your only choice for dynamic cloud provisioned VMs for PostgreSQL. Give it a shot, the more competition in this space the better.

---
[View this page online](https://www.commandprompt.com/blog/gce_a_little_advertised_cloud_service_that_is_perfect_for_postgresql/)

---

# PDXPGDay 2014

> I had the honor of being asked to give the introduction at PDXPGDay 2014 this past Saturday. I didn&#x27;t speak very long but it was great to see a lot of the old …

I had the honor of being asked to give the introduction at PDXPGDay 2014 this past Saturday. I didn't speak very long but it was great to see a lot of the old stomping ground. It had been quite some time since I had been in the group of Wheeler, Roth, Wong, Berkus and a few others. 

The conference was really a mini-conference but it was great. It was held in the exact same room that PostgreSQL Conference West was held all the way back in 2007. It is hard to believe that was so long ago. I will say it was absolutely awesome that PDX still has the exact same vibe and presentation! (Read: I got to wear shorts and a t-shirt). 

Some items of note: Somebody was peverse enough to write a FUSE driver for PostgreSQL and it was even bi-directional. This means that PostgreSQL gets mounted as a filesystem and you can even use Joe (or yes VIM) to edit values and it saves them back to the table. 

Not nearly enough of the audience was aware of PGXN. This was a shock to me and illustrates a need for better documentation and visibility through .Org. 

The success of this PgDay continues to illustrate that other PUGS should be looking at doing the same, perhaps annually! 

Thanks again Gab and Mark for entrusting me with introducing your conference!

---
[View this page online](https://www.commandprompt.com/blog/pdxpgday_2014/)

---

# apt.postgresql.org... a wonderful if flawed apt repository

> The site apt.postgresql.org is a great resource for those who live in the Debian derived world. It keeps up to date with the latest postgresql packages and has…

The site apt.postgresql.org is a great resource for those who live in the Debian derived world. It keeps up to date with the latest postgresql packages and has a whole team dedicated to creating these packages. Of course, this is the Open Source world so not everyone agrees 100% with the way things are done in this project. [As I noted here, there are some issues.](<http://www.postgresql.org/message-id/53F269E2.1050309@commandprompt.com>)

These issues are not to detract from otherwise excellent work but a note to those who use the repository to look for further problems. I also have a video displaying specifically what the [issues are, here.](<https://www.youtube.com/watch?v=efaxYGaqRYI>)

---
[View this page online](https://www.commandprompt.com/blog/aptpostgresqlorg_a_wonderful_if_flawed_apt_repository/)

---

# Kicking the Donkey of PostgreSQL Replication

> This is the title of a talk I am developing for the matured PostgreSQL Conference:
PGConf NYC 2014 . Formerly a PgDay, this is now a full blown conference ext…

This is the title of a talk I am developing for the matured PostgreSQL Conference: PGConf NYC 2014 . Formerly a PgDay, this is now a full blown conference extending two days with three tracks. From all reports it is set to be the largest PostgreSQL Conference ever in the United States, surpassing even the old West and East series (which no conference in the U.S. has done to date). It is truly exciting times for our community. 

This talk will be a departure from my standby talks of PostgreSQL Performance and Choosing the right hardware. Katz asked me, "to bring your full East Coast from the West Coast personality.". I plan on doing so. So cinch up the boot straps it is going to be a ride. In classic JD style I am going to be blunt and to the point about the good, the bad, and the, "WTH were they thinking" of PostgreSQL Replication. 

So outside of personality what am I really trying to deliver to the community? I think the description of the talk says it all: 

>   * Have you ever wondered how to configure PostgreSQL Replication? 
>   * Have you ever wondered how to configure PostgreSQL Log Shipping? 
>   * Have you ever wondered: Which one is best for my application? 
>   * Are you aware of the pitfalls of Replication? Where it breaks? When it will act in a way that is counter-intuitive? Do you know how to fix it? 
>   * Do you know how to monitor it? 
> 


If you have asked yourself any of these questions, this is the talk for you. We will step through PostgreSQL replication, the technology involved, the configuration parameters and how to configure it in a manner that isn't fragile. We will also cover gotcha's how to prepare for them and understanding what replication is doing. 

This talk is not not for the faint of heart. I will take a no holds barred approach and give you the real deal, the dirt and the gold that is one of the most sought after PostgreSQL features. 

On a closing note, this conference is showing how a PostgreSQL User Group, combined with the resources of United States PostgreSQL can help grow and educate the community. They don't just help NYCPUG, they also help PDXPUG, PHILLYPUG and SEAPUG. Maybe your PUG should consider working with PgUS? If so, give "Jonathan S. Katz" [jonathan.katz {@} excoventures.com] a jingle.

---
[View this page online](https://www.commandprompt.com/blog/kicking_the_donkey_of_postgresql_replication/)

---

# Security Considerations While Using ssh-agent.

> Recently we got contacted by a customer, and started the typical remote access setup: ask them to open ssh port for our bastion server, create a new user for u…

Recently we got contacted by a customer, and started the typical remote access setup: ask them to open ssh port for our bastion server, create a new user for us, and add the corresponding ssh public key. Well, they promptly responded, and we tested access, got into their bastion server and then tried to get to one of the broken servers but, it was asking for a password. We just asked the customer for the password, and got a reply stating that they had assumed we were using agent forwarding.

The first instinct of the engineer handling the ticket was: well, lets just start ssh-agent, load the key, and forward it! Of course, after a brief discussion, it became clear it was a bad idea.

It is well known that agent forwarding (forwarding of the ssh authentication agent connection) can be considered, under certain conditions, a security risk, because when you do that a socket is created on the remote host, and any user with access to the socket would be able to authenticate using the keys loaded in the agent.

Some of you could still ask: what is the risk?, after all, the agent connection gets forwarded over ssh, the socket permissions are very restrictive, and the agent will not expose the keys, not even encrypted, it will only answer to authentication requests. Furthermore, when you read ssh-agent man page, it sounds reassuring:

> (...)"The idea is that the agent is run in the user's local PC, laptop, or terminal. Authentication data need not be stored on any other machine, and authentication passphrases never go over the network. However, the connection to the agent is forwarded over SSH remote logins, and the user can thus use the privileges given by the identities anywhere in the network in a secure way."(...)

No wonder a lot of people trust ssh-agent so much.

But this is only partially true. The reality is that any user with enough privileges (root-level access, or access to the same user you are using to login) on the remote host will be able to use your forwarded agent through the local socket, and thus authenticate using the keys you loaded into the agent, potentially gaining access to other servers you manage, for as long as you keep your session open. It is worth noting that the access is limited to *using* the keys, but not fetching them, ie, the agent doesn't allow access to the private keys, but only answers authentication requests.

Because of this, it is not a good idea to forward the agent to a server you don't trust (either because you don't know and/or don't trust the other administrators, or because you can't tell for sure if the server is compromised). If in doubt, don't do it, if you really have to do it, limit the keys you add to the agent.

In general, assume that every key you add to the agent will be used by someone or something (bot) on the remote server, ask yourself if you know who will use the key and if you are okay with that.

Now, back to our customer situation. Not having a lot of time to argue or consider alternatives (customer reported an emergency), we just decided to create a new key for this customer, and use what they wanted: agent forwarding. This worked just fine, and allowed us to get into all the failing servers comfortably, and without any risks.

The first thing we had to do was create the key, something like this:

> ssh-keygen -t rsa -f ~/agent_keys/new_key-id_rsa

Running ssh-keygen, and then typing in a new key destination would work too, but if you hit enter, you could unwillingly overwrite your default id_rsa file.

Now that we generated the new key, to use it with the agent we need to:

1\. Start SSH agent (we don't run it by default), and have the agent run a shell.

> ssh-agent bash

In my opinion, this is simpler than starting the agent and then exporting the variables, and has the advantage that the agent will automatically quit when you exit the shell, no need to kill the agent, and no risk that you forget to kill it.

2\. Add the key(s) you need to use (keys will be usable by anyone with access to the agent's socket, either on the local or remote server):

> ssh-add ~/agent_keys/new_key-id_rsa

3\. Connect to the remote host, enabling agent forwarding, likely using the -A parameter:

> ssh -A remote_host

Of course, if you modified ~/.ssh/config file to include "ForwardAgent yes", the -A parameter would be unnecessary. Remember to never set ForwardAgent to "yes" globally, unless you really know what you are doing.

4\. When you are done, just exit the shell, and agent will automatically quit.

Most problems have different solutions, and this one is not an exception. We decided to use this solution, because it was aligned with what the customer expected, and was fast to implement.

I hope this little post helps increase the awareness of the associated risks of doing agent forwarding and that, in the end, helps sysadmins make informed decisions with security in mind.

Until next time!

---
[View this page online](https://www.commandprompt.com/blog/security_considerations_while_using_ssh-agent/)

---

# Managing pg_hba.conf With Ansible

> pg_hba.conf is perhaps one of the easiest to understand configuration files in PostgreSQL. Its syntax is straightforward, the concept seems to resemble that of…

pg_hba.conf is perhaps one of the easiest to understand configuration files in PostgreSQL. Its syntax is straightforward, the concept seems to resemble that of any popular IP filter or ACL mechanism in various software packages. pg_hba.conf is also well documented, like the rest of PostgreSQL, and we love it because it lets us do what we want without getting in our way. What else could we possibly ask of it?

Perhaps, it can be a bit of a nuisance when for you pg_hba.conf means not just one file but many. You may have a dozen read-only standbys and your infrastructure is expanding -- a good sign that you're probably all the rage on the market -- so at one point you may realize you need to modify pg_hba.conf contents and introduce some changes.

Well, there a number of ways to do that, and if it is just one line that needs to be added, or edited, it is very tempting to just go ahead and do it. Manually. However, what we often forget blinded by this illusion of simplicity of a task at hand is the hidden extra toll of additional actions that need to be carried out. Like reloading PostgreSQL to apply changes made in pg_hba.conf. And thus the amount of manual labor has just doubled, and if you made a mistake, even a teeny tiny typo, you might need to do it again and the word would be then quadrupled and it would most likely come with a bonus of some frustration in the air that usually accompanies broken illusions.

We at Command Prompt, Inc. have been increasingly relying on ansible to solve this very problem. And we would like to give you an idea about how empowering this rookie of configuration management can be. If you have never heard of ansible before, think chef or puppet. It is similar, but in many ways a different beast.

Ansible can be used to do all sorts of things. For example, we successfully deployed backups software for one of our customers, distributed SSH public key to configure access without a password to a dozen of hosts (all under 15 minutes including writing a playbook to do this), installed unattended-upgrades and manage its configuration files and a blacklist, deployed various in-house custom reports scripts that require distribution of executables, configuration files and cron jobs, applied SQL files to PostgreSQL DB, automated bulk of tedious work when deploying a monitoring system, continuously update and deploy a base toolset that we use on all servers that we own or manage (tools like sar, atop, molly-guard, tree, etc.) and so on.

It is typically run in two modes: playbooks and ad-hoc. Playbooks are just (YAML) files that have a list of tasks that are run in successive order. Much like what happens in a BASH script. Ad-hoc mode is a way to call ansible to run just one task at a time directly on your terminal's command line. Combined they are incredibly useful not only for massive and rapid deployment, but also in day-to-day work of a system administrator.

And as a system administrator or DBA, you can actually update your pg_hba.conf (or a slew of them) with a touch of one command. Perhaps one of the best things about using ansible and having actual playbooks is that they can be run against your inventory of hosts (yeah, ansible parlance) again, and again, which in effect means that you can always ensure that your current, actual configuration is exactly what it was initially intended to be as expressed in a playbook (in configuration management club this is usually talked about as configuration drift and idempotency).

So, let's take a look at this default pg_hba.conf in PostgreSQL 9.1 on Ubuntu Server 12.04 Precise:
    
    
    $ sudo grep "^[a-z]" /etc/postgresql/9.1/main/pg_hba.conf
    [sudo] password for admin: 
    local   all             postgres                                peer
    local   all             all                                     peer
    host    all             all             127.0.0.1/32            md5
    host    all             all             ::1/128                 md5
    

Suppose we want to add a new entry for a host at 10.10.100.15/32, and apply this change to bazillion of hosts (yes, ansible is actually aware of this number and is fully capable of handling it).

So, this is our new pg_hba.conf line
    
    
    host    all             cmd_zabbix_mon 10.10.100.15/32            trust
    

Now we need a playbook with a task that will add this new line to pg_hba.conf. Before we create one, we need to make sure that all hosts where we want to see the change happen are in ansible hosts inventory file, /etc/ansible/hosts.

In our example it is a very simple one:
    
    
    [localhost]
    127.0.0.1
    
    [allhosts]
    precise
    

We are going to connect to allhosts, which is a name of a group of hosts with just one hostname in it -- precise. In fact, it is the same host where we are going to run ansible from.

It is a good practice to run ansible from a control machine to SSH into managed nodes, i.e. the control machine is a separate system. In practice, you will probably end up managing the control machine too and thus need to SSH into it as well.

Therefore in our example we're going to SSH into the same machine where ansible is run from, which will serve as an illustration that all you need to get started with ansible is a single, modest virtual machine.

Anyway, allhosts could be also a very long list of hostnames, e.g.
    
    
    [allhosts]
    precise
    venus
    www.commandprompt.com
    db1.nondescript.org
    db-[2:140].nondescript.org
    

So, with inventory all set, we can now write the playbook. Playbooks are YAML files and thus YAML syntax is something to have a good command of.

Ansible is extremely flexible in various ways, and that is why there are no strict rules about how your playbooks should be organized. We usually find the following layout most convenient to work with
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ tree
    .
    |-- file
    |-- setup
        |-- configure.yml
    |-- templates
    |-- vars
        |-- general.yml
    
    4 directories, 2 files
    

file/ is used for executables, binaries and all manner of files that need to be copied over to managed nodes.

setup/ contains playbooks

templates/ is where we keep template files

vars/ is used to hold special purpose playbooks that are used in essence as configuration files to separate variables apart from tasks (you'll see in a minute how this can be useful).

So, here it is. You're looking at what technically speaking is called incorrectly here a pg_hba.conf playbook. To get our terminology straight, each file in setup/ is actually called a playbook, and the multitude of YAML files found in such directory tree is referred to as a collection of playbooks.

Now, let's take a closer look at vars/general.yml
    
    
    ---
    
    #
    # General
    sys_usr: admin
    sudo_user: postgres
    
    #
    # Miscellaneous
    pg_hba_conf: /etc/postgresql/9.1/main/pg_hba.conf
    

It has three variables:

sys_usr: sets a username that is used to connect to managed nodes and to run tasks as sudo_user: is what user we want to run a task as via sudo on a managed node

and finally

pg_hba_conf: is a location of pg_hba.conf file

In our example we are going to get a little fancy and have ansible edit pg_hba.conf as postgres user, by logging into the managed node -- precise -- and modifying pg_hba.conf as postgres via sudo.

So, let's take a look at the most interesting and useful playbook file.
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ cat setup/configure.yml 
    ---
    #
    # An example playbook to configure pg_hba.conf file 
    
    - hosts: allhosts
      vars_files:
       - ../vars/general.yml
      user: $sys_usr
      sudo_user: $sudo_user
      tasks:
    
       #
       # Adding a new line
       - lineinfile: dest=$pg_hba_conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^#sIPv4slocal.+" line="host    all             cmd_zabbix_mon  127.0.0.1/32            trust"
    

We say here that

  * we want to connect to each host in host group allhosts and run all tasks on each of those hosts
  * that our variables file is vars/general.yml
  * that we want to log in as $sys_usr
  * and then run tasks via sudo as $sudo_user



Then we list our tasks. There is just one task that uses this monstrous looking thing that is called lineinfile: module. This mess of symbols says "Add new line as defined by line= after an existing line that starts with '# IPv4 local' text".

I chose this particular example not to scare our readers but to try to clarify how this module that has this not so intuitive syntax, but is otherwise useful, works; because in all honesty, when I first encountered it I think spent many hours of futile attempts to just understand how to use it.

Anyway, we'll talk more about lineinfile: a bit later. For now, just try to read what it says and you may notice that it uses regular expressions (Python flavor), and of course it gives you a headache. I understand, but it also is a great tool for making one line changes in configuration files that are not managed completely by ansible via templates.

Alright, let's see some magic at work.
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible-playbook setup/configure.yml -kK
    SSH password: 
    sudo password [defaults to SSH password]: 
    
    PLAY [allhosts] *************************************************************** 
    
    GATHERING FACTS *************************************************************** 
    ok: [precise]
    
    TASK: [lineinfile dest=/etc/postgresql/9.1/main/pg_hba.conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^#sIPv4slocal.+" line="host    all             cmd_zabbix_mon  127.0.0.1/32            trust"] ***
    changed: [precise]
    
    PLAY RECAP ******************************************************************** 
    precise                    : ok=2    changed=1    unreachable=0    failed=0
    

I am personally a bit paranoid when it comes to security. I admit it, but I also know that our internal wiki has a very eloquent statement in regards to what may ensue should we as a team manage to screw up our customers environment. Just for the record, we are never abused here at CMD, only loved. We are all very friendly and positive people, and still, even though it is very convenient to rely on SSH keys to get into systems without having to enter a password, when it comes to ansible I choose to consciously type in a password each time I run a playbook. Especially, when the numbers of systems involved are large. Call it self-inflicted torture, but I'd rather think twice before letting ansible cause damage at the speed of the bullets flying out of a machine gun.

That being said, to run an ansible playbook you run ansible-playbook command by telling it what playbook file you want it to process. While -k and -K indicate that you want to be asked for user: and sudo_user: passwords respectively.

Once the passwords have been entered and submitted, ansible does its usual routine: it tries to SSH into allhosts, in our case just one but could be a bunch, gather some facts about a system that actually bubble up into a playbook and can be later used to uniquely identify your systems. This allows to apply some logical conditions, or decide to skip certain tasks for some of the hosts, or even types of systems. It then proceeds by announcing what task is going to be played and follows up immediately after that with results: either success, failure or nothing has been changed (ah, idempotency!). A play summary report is also shown in the end to indicate how many tasks resulted in what state, whether any of the hosts were unreachable during the attempted play and whether there were any failures.

In this case our task was successfully run, so let's see what happened to pg_hba.conf
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ sudo grep "^[a-z]" /etc/postgresql/9.1/main/pg_hba.conf
    [sudo] password for admin: 
    local   all             postgres                                peer
    local   all             all                                     peer
    host    all             cmd_zabbix_mon  127.0.0.1/32            trust
    host    all             all             127.0.0.1/32            md5
    host    all             all             ::1/128                 md5
    

Alright, we just added a new line. Here's a truncated version of the pg_hba.conf that shows that the line was added indeed after one that started with "# IPv4 local"
    
    
    ...
    # "local" is for Unix domain socket connections only
    local   all             all                                     peer
    # IPv4 local connections:
    host    all             cmd_zabbix_mon  127.0.0.1/32            trust
    host    all             all             127.0.0.1/32            md5
    ...
    

Let's run the same playbook again and see what happens:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible-playbook setup/configure.yml -kK
    SSH password: 
    sudo password [defaults to SSH password]: 
    
    PLAY [allhosts] *************************************************************** 
    
    GATHERING FACTS *************************************************************** 
    ok: [precise]
    
    TASK: [lineinfile dest=/etc/postgresql/9.1/main/pg_hba.conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^#sIPv4slocal.+" line="host    all             cmd_zabbix_mon  127.0.0.1/32            trust"] ***
    ok: [precise]
    
    PLAY RECAP ******************************************************************** 
    precise                    : ok=2    changed=0    unreachable=0    failed=0 
    

Nothing changed. This is expected and is a good thing. Here you see idempotency in action (shouldn't I say inaction instead?). In other words when the changes that are expressed by a sum of playbook tasks are already in place, ansible will not needlessly try to apply them again. If this new line that we have just added disappeared, or were edited in some fashion, just run the playbook against this host one more time and ansible will either re-add the line, or add a new one respectively (leaving modified line intact; read more on this behavior below).

To illustrate what is going to happen here I changed the line in pg_hba.conf that we had added in a previous run of the playbook, and then I ran it again. This is the result:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ sudo grep "^[a-z]" /etc/postgresql/9.1/main/pg_hba.conf
    local   all             postgres                                peer
    local   all             all                                     peer
    host    all             cmd_zabbix_mon  127.0.0.1/32            trust
    xhost    all             cmd_zabbix_mon  127.0.0.1/32            trust
    host    all             all             127.0.0.1/32            md5
    host    all             all             ::1/128                 md5
    

As our line was tampered with, and because of how our lineinfile: task's regexp is written, a new line was added again but the old, now modified line was left intact.

Alright let's clean up pg_hba.conf of these two new lines and do something else with the help of lineinfile: module, namely change an existing line.

We will build on our example by adding a new task.
    
    
    ---
    #
    # An example playbook to manage pg_hba.conf file 
    
    - hosts: allhosts
      vars_files:
       - ../vars/general.yml
      user: $sys_usr
      sudo_user: $sudo_user
      tasks:
    
       #
       # Adding a new line
       - lineinfile: dest=$pg_hba_conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^#sIPv4slocal.+" line="host    all             cmd_zabbix_mon  127.0.0.1/32            trust"
    
       #
       # Replacing an existing line
       - lineinfile: dest=$pg_hba_conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^hosts+alls+cmd_zabbix_mons.+" line="host    all             cmd_nagios_mon 10.10.100.15/32            trust"
    

Save the file, run the playbook. Here's the result:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible-playbook setup/configure.yml -kK
    SSH password: 
    sudo password [defaults to SSH password]: 
    
    PLAY [allhosts] *************************************************************** 
    
    GATHERING FACTS *************************************************************** 
    ok: [precise]
    
    TASK: [lineinfile dest=/etc/postgresql/9.1/main/pg_hba.conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^#sIPv4slocal.+" line="host    all             cmd_zabbix_mon  127.0.0.1/32            trust"] ***
    changed: [precise]
    
    TASK: [lineinfile dest=/etc/postgresql/9.1/main/pg_hba.conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^hosts+alls+cmd_zabbix_mons.+" line="host    all             cmd_nagios_mon 10.10.100.15/32            trust"] ***
    changed: [precise]
    
    PLAY RECAP ******************************************************************** 
    precise                    : ok=3    changed=2    unreachable=0    failed=0   
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ sudo grep "^[a-z]" /etc/postgresql/9.1/main/pg_hba.conf
    local   all             postgres                                peer
    local   all             all                                     peer
    host    all             cmd_nagios_mon 10.10.100.15/32            trust
    host    all             all             127.0.0.1/32            md5
    host    all             all             ::1/128                 md5
    

Wonderful, the line was first added as in our first example, then the username on this same line was changed from cmd_zabbix_mon to cmd_nagios_mon. In fact, we replaced an entire line, and that's how one should think about line editing with lineinfile: module. Needless to say, this could be done to any part of pg_hba.conf.

And there you have it, two most frequent uses of lineinfile: module: adding a new line and replacing (or editing) an existing one.

If it seems a bit confusing and hard to swallow, it actually kind of is. Regardless, here's a little something to help you, an outline of the path to mastery with lineinfile: module.

First and foremost, know specifics of Python regular expressions. Then know thy enemy.

Here are the essentials.

To insert a new line your regexp= and line= must match, and insertafter= must indicate a line after which you want your new line to appear. Subsequent runs will not make any further changes if a line already exists. If a line does not exist, a new line will be added. How you define if a line exists is irrelevant, understand how lineinfile: defines your reality.

If regexp= and insertafter= match and the line they describe exists it will be replaced with line=. Subsequent runs will not make any further changes. If a line you match does not exist no changes will be made.

> **Note:** _However, if regexp= is empty last line of your file will be replaced with line=, or it may well be some other unexpected place! Bottom line is, be extra cautious when working with lineinfile: unless you're confident beyond any shadow of a doubt and you know exactly what changes will happen. It's a tricky one to work with, so test multiple times in your lab before you use lineinfile: tasks in production environment._

lineinfile: is great -- because it is the only module that performs line editing so far? -- to edit just one line at a time, but let's face it, sometimes its syntax may be really confusing. Especially when your lines are a full of funky characters that need escaping. It is still worth the effort to learn how to use it, because I could testify that it proved very helpful in numerous instances of my work as system administrator.

With that in mind, there are less confusing ways to manage your pg_hba.conf with ansible.

Still, a very attentive reader may have noticed that we never reloaded PostgreSQL configuration and thus all the changes to pg_hba.conf have not taken effect yet.

You have an idea about the playbook mode now. Let's reload PostgreSQL configuration by running ansible in ad-hoc mode.
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible allhosts -m service -a "name=postgresql state=reloaded" -kK
    SSH password: 
    sudo password [defaults to SSH password]: 
    precise | success >> {
        "changed": true, 
        "name": "postgresql", 
        "state": "stopped"
    }
    

That was nice and easy, wasn't it? The syntax is very simple:

* we already know what allhosts is for  
* -m service says that we are going to use module named service  
* -a is used to pass parameters to the service module  
* name= and state= and the service module parameters  
* -k and -K ask us for our credentials

Note that we reloaded PostgreSQL as root via sudo. Unless a different sudo user is specified on command line or a sudo_user: variable is used when using a playbook, ansible assumes that you want to run commands as root. In other words, this is default sudo command behavior.

Ad-hoc mode is often something we use in a new environment where we set up ansible. One of the things it helps to do is gather some facts about the systems we are going to manage. For example, for the purposes of being able to refer to any of the managed hosts in playbooks by their hostname, and then taking actions based on the knowledge of what hosts ansible is currently running tasks on, one of the first things that we do is establishing how ansible sees the managed hosts hostnames. In practice, we learned, they may differ from what you might expect solely from the contents of /etc/hostname and /etc/hosts, or BIND configuration (it really depends on how well your systems are configured).

To that end we use setup module. Its purpose is to gather facts about hosts and print them on stdout:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible allhosts -m setup -k |grep fqdn
    SSH password: 
            "ansible_fqdn": "precise.localdomain",
    

Here we just selected to show only FQDN. Toss out grep and re-run the command to see a complete list of facts for your host(s).

In ad-hoc mode you can do other, more general yet equally useful things. For example, see if a user is in /etc/sudoers file on all hosts:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible allhosts -m command -a "grep ansible /etc/sudoers" -kK
    SSH password: 
    sudo password [defaults to SSH password]: 
    precise | success | rc=0 >>
    ansiblemgr ALL=(ALL) ALL
    

or check if your managed nodes can still, or already, be logged in:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible allhosts -m ping -k
    SSH password: 
    precise | success >> {
        "changed": false, 
        "ping": "pong"
    }
    

And should you wish to reload PostgreSQL configuration from a playbook, just add the following extra task to the end of our example playbook:
    
    
       #
       # Reload PostgreSQL configuration
       - service: name=postgresql state=reloaded
    

Save the file, re-run the playbook. Assuming pg_hba.conf was not previously modified, the results thus would be like this:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible-playbook setup/configure.yml -kK
    SSH password: 
    sudo password [defaults to SSH password]: 
    
    PLAY [allhosts] *************************************************************** 
    
    GATHERING FACTS *************************************************************** 
    ok: [precise]
    
    TASK: [lineinfile dest=/etc/postgresql/9.1/main/pg_hba.conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^#sIPv4slocal.+" line="host    all             cmd_zabbix_mon  127.0.0.1/32            trust"] ***
    changed: [precise]
    
    TASK: [lineinfile dest=/etc/postgresql/9.1/main/pg_hba.conf regexp="^hosts+alls+cmd_zabbix_mons+127.0.0.1/32s+trust$" insertafter="^hosts+alls+cmd_zabbix_mons.+" line="host    all             cmd_nagios_mon 10.10.100.15/32            trust"] ***
    changed: [precise]
    
    TASK: [service name=postgresql state=reloaded] ******************************** 
    changed: [precise]
    
    PLAY RECAP ******************************************************************** 
    precise                    : ok=4    changed=3    unreachable=0    failed=0
    

You may want to be looking at PostgreSQL log file when running playbook this time, just to make sure you see if SIGHUP was indeed sent to the service:
    
    
    ...
    2013-11-14 07:16:17 PST LOG:  received SIGHUP, reloading configuration files
    

Now, for the final piece of our ansible discussion let's talk about what I mentioned several minutes ago. Arguably, the easier and less messy way to manage pg_hba.conf. That is, by way of using templates.

Ansible leverages Jinja2 templating engine. That said, it is very easy to learn how to use it by example. We are going to create another playbook to deploy our new, template based pg_hba.conf.
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ cp setup/configure.yml setup/deploy.yml
    

After some editing we come up with this
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ cat setup/deploy.yml 
    ---
    #
    # An example playbook to deploy pg_hba.conf file 
    
    - hosts: allhosts
      vars_files:
       - ../vars/general.yml
      user: $sys_usr
      tasks:
    
       #
       # Deploying a template
       - template: src=../templates/pg_hba.conf.j2 dest=$inst_dir/pg_hba.conf owner=postgres group=postgres mode=0640
    
       #
       # Reload PostgreSQL configuration
       - service: name=postgresql state=reloaded
    

Let's break it down:

* no sudo_user: this time, we do everything as root via sudo call  
* template: module takes our template file pg_hba.conf.j2 and after some processing produces a resulting pg_hba.conf in $inst_dir, which is defined in vars/general.yml. It also sets ownership and access permissions to postgres.postgres and 0640 respectively.

Here's how the vars/general.yml looks like now
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ cat vars/general.yml 
    ---
    
    #
    # General
    sys_usr: admin
    
    #
    # Miscellaneous
    pg_hba_conf: /etc/postgresql/9.1/main/pg_hba.conf
    inst_dir: /etc/postgresql/9.1/main
    

And after that we create a template for pg_hba.conf
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ cp /etc/postgresql/9.1/main/pg_hba.conf templates/pg_hba.conf.j2
    

Copying a file and using it unmodified would be enough to create a template. You could go ahead with just this template and deploy to as many hosts as you need. Sometimes this approach is useful, but more often than not you will want slightly different pg_hba.conf files on different hosts. Sometimes, perhaps, you will want your pg_hba.conf to be very different on many hosts. At that point you may be better off using several templates to avoid unnecessary complexity and to continue to maintain ease of readability of each individual template file.

So, after some editing our example pg_hba.conf.j2 template looks like this. This is a truncated version. As you've just seen we used stock pg_hba.conf to create initial version of a template file, and thus anything that appears before the listed below truncated part of template code remains unmodified.
    
    
    ...
    
    # DO NOT DISABLE!
    # If you change this first entry you will need to make sure that the
    # database superuser can access the database using some other method.
    # Noninteractive access to all databases is required during automatic
    # maintenance (custom daily cronjobs, replication, and similar tasks).
    #
    # Database administrative login by Unix domain socket
    local   all             postgres                                peer
    
    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    
    # "local" is for Unix domain socket connections only
    local   all             all                                     peer
    # IPv4 local connections:
    
    {% if ansible_fqdn == "precise.localdomain" or ansible_fqdn == "venus.localdomain" %}
    host    all             cmd_zabbix_mon 10.10.100.15/32          trust
    
    {% elif asible_fqdn == "www.commandprompt.com" %}
    host    all             johnson 192.168.180.17/32               md5
    
    {%elif ansible_fqdn == "db1.nondescript.org" %}
    host    all             blackfox 172.16.12.9/32                 ident
    
    {% else %}
    host    all             cmd_zabbix_mon 10.10.100.12/32          md5
    {% endif %}
    
    
    host    all             all             127.0.0.1/32            md5
    # IPv6 local connections:
    host    all             all             ::1/128                 md5
    # Allow replication connections from localhost, by a user with the
    # replication privilege.
    #local   replication     postgres                                peer
    

Our template is a bit fancy. It makes use of ansible facts (ansible_fqdn) and it has some conditional statements that will add a specific pg_hba.conf entry depending on where (what host) this template is being deployed to.

Thus, precise.localdomain and venus.localdomain are going to get this line:
    
    
    host    all             cmd_zabbix_mon 10.10.100.15/32          trust
    

and db1.nondescript.org this one
    
    
    host    all             blackfox 172.16.12.9/32                 ident
    

If the ansible_fqdn fact does not match any of the hostnames specified a default choice of
    
    
    host    all             cmd_zabbix_mon 10.10.100.12/32          md5
    

is going to be applied.

You could go as far as use variables from vars/general.yml (and any other facts that are gathered prior to execution of playbook tasks) in a template. They would get expanded and make your template even more powerful.

Now, let's run this new playbook. And before we do so, lets delete pg_hba.conf to simulate a situation where a pg_hba.conf has been lost, but PostgreSQL is still running just fine, safely keeping a cached version of the configuration file in its memory. It would be an imminent problem on the next service restart, but not if became aware of the problem in a timely manner and then ran our new playbook before PostgreSQL had to be restarted:
    
    
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ls -lah /etc/postgresql/9.1/main/pg_hba.conf
    -rw-r----- 1 postgres postgres 4.5K Nov 14 08:26 /etc/postgresql/9.1/main/pg_hba.conf
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ sudo rm /etc/postgresql/9.1/main/pg_hba.conf
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ date
    Thu Nov 14 08:30:58 PST 2013
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ansible-playbook setup/deploy.yml -kK
    SSH password: 
    sudo password [defaults to SSH password]: 
    
    PLAY [allhosts] *************************************************************** 
    
    GATHERING FACTS *************************************************************** 
    ok: [precise]
    
    TASK: [template src=../templates/pg_hba.conf.j2 dest=/etc/postgresql/9.1/main/pg_hba.conf owner=postgres group=postgres mode=0640] *** 
    changed: [precise]
    
    TASK: [service name=postgresql state=reloaded] ******************************** 
    changed: [precise]
    
    PLAY RECAP ******************************************************************** 
    precise                    : ok=3    changed=2    unreachable=0    failed=0
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ ls -lah /etc/postgresql/9.1/main/pg_hba.conf 
    -rw-r----- 1 postgres postgres 4.5K Nov 14 08:31 /etc/postgresql/9.1/main/pg_hba.conf
    admin@precise:~/CMD/svn/ansible-tests/pg_hba.conf$ sudo grep "^[a-z]" /etc/postgresql/9.1/main/pg_hba.conf 
    local   all             postgres                                peer
    local   all             all                                     peer
    host    all             cmd_zabbix_mon 10.10.100.15/32          trust
    host    all             all             127.0.0.1/32            md5
    host    all             all             ::1/128                 md5
    

As you can see pg_hba.conf was first removed and then recreated, and an appropriate entry for precise.localdomain host added while all the others within {% if %} ... {% endif %} conditional statement were ignored. Had there been more hosts online in my test lab, they all would've received a tailored version of pg_hba.conf according to the configuration of our template.

This approach is easier on the eyes, less error prone, offers a lot more flexibility and allows you to tailor pg_hba.conf for many systems simultaneously using just one template file.

Not only that, in a lot of cases ansible playbooks become a centrally managed configuration pool for various pieces of our infrastructure, with the added benefit of having an extra backup copy of the configs that prove useful not only in emergency when a configuration file is lost but even when we need to evaluate the existing configuration. Incredibly useful when you can look at all of the configs at once in just one file.

Now, for the final touch, if you were to deploy this template in an environment that runs a mix of systems (Red Hat Enterprise Linux, Ubuntu Server, Debian GNU/Linux, etc. ) and you wanted to make changes only on hosts of a certain type, you can easily do so by adding an extra line to this example playbook:
    
    
    ...
       #
       # Deploying a template
       - template: src=../templates/pg_hba.conf.j2 dest=$inst_dir/pg_hba.conf owner=postgres group=postgres mode=0640
         when: ansible_distribution == "Debian" or ansible_distribution == "Ubuntu"
    ...
    

Here ansible_distribution is an ansible fact, much like ansible_fqdn that we used in the pg_hba.conf template file, and as you've seen by now they can be used in various places.

And this concludes our today's discussion about ansible as a tool to help you manage your PostgreSQL configurations. Much more could be said about it, this is truly just the tip of the iceberg. However, this should be able to help you see how you could be managing your PostgreSQL configurations more effectively.

As I stated in the opening paragraphs we have been increasingly relying on ansible to do all sorts of things, so if you're asking yourself if you could start managing something with ansible, the answer is that you most probably can.

---
[View this page online](https://www.commandprompt.com/blog/managing_pg_hbaconf_with_ansible/)

---

# PgConf.eu is over, it was a blast but I am curious about the future

> First let me say that I attended pgConf.eu like I attend every conference (that I am not running). I show up for a few hours on the first day, then I come back…

First let me say that I attended pgConf.eu like I attend every conference (that I am not running). I show up for a few hours on the first day, then I come back and attend my talk. I don't take travel lightly and as much as I bromance my fellow elephant bretheren, I want to explore the sights and this was freaking Ireland people. 

I had an odd feeling for the time I was there. The community was in full force, there was at least 240 people there and that was great. It was the commerce side, the sponsor side, the **money** side that was lacking. EnterpriseDB, Cybertec and 2ndQuadrant were there with booths but I wonder if it was even worth it? 

It is great that 3 of the largest European commercial contributors were sponsors. I think the traditional model of sponsorship is over and those companies are not getting their investment back. This is certainly not the fault of PgConf.eu nor is it the fault of the sponsors. It is habit to fall into what we know. It is that what we know, is broken. There is no true return on investment. You might pull a couple or even a half a dozen leads. Yes you get 20 minutes to give your speech at the end of the conference (when a lot of the people have left anyway) but business is about relationships. I don't see how 3 booths at a 240 person conference enables relationships to be built. 

I wonder what the attendees are getting out of it? Do we see these sponsors as more beneficial than companies (such as Credativ) who wasn't sponsoring with a booth but was speaking? Or are we just silently thankful that they are there because that way we don't have to spend 500 Euro to attend the conference? If the latter, does it make sense for companies to continue to contribute? What could a company do for the community (and themselves) with a 20k sponsorship versus having a booth and their name on a shirt? 

Which brings me to my final point. If pgConf.eu (or Pgcon, NYCPgConf) were to charge 500.00, and it was sponsor free (or at least more creative in presence) would you still go? What if that included a half day tutorial? What if the conference was only about PostgreSQL + Community. Yes, sponsors are part of the community and they are more than welcome to show up in matching shirts and speak when their talks are accepted but no booths, no littered t-shirts, just good old fashion community, and education. 

What do you think?

---
[View this page online](https://www.commandprompt.com/blog/pgconfeu_is_over_it_was_a_blast_but_i_am_curious_about_the_future/)

---

# 5 Things a Non-Geek Girl Learned from Playing with Geeks at CMD

> When I began at Command Prompt, Java was coffee, Python was a snake, and a Ruby was best used on the color of glittery slippers. If you would have asked me two…

When I began at Command Prompt, Java was coffee, Python was a snake, and a Ruby was best used on the color of glittery slippers. If you would have asked me two and a half years ago what "PostgreSQL" does, I would have asked you what language you were speaking.

A year later, I took my first sales call with out Joshua Drake (jd, @linuxhiker). I was shaking in my boots and it was inevitable that I was going to be sick. Then something happened as soon as I heard the customer say, "Hello".

I understood what the customer needed and most importantly, I knew we could do it. I was able to say confidently and with out doubt, "Yes, we can take care of you."

I still have a LONG way to go and I will never be a geek. But here are some key things a non-geek girl has learned from playing with geeks:

1\. It's a big, technical world out there. It is vast and fast-paced. To keep up, you have to continue to instigate fresh ideas and put the time in to develop them. You also have to learn from other people's ideas. The PostgreSQL world is about more than consulting. It's a community of people passionate about the dynamic capabilities of PostgreSQL.

2\. Document down to your underwear. We are passionate about documentation at CMD and you should be too. Only good things can come from documenting work and as Open Source advocates, we promote sharing the Postgres love.

3\. Keeping your software, hardware, and underwear (sorry, it rhymed)updated is key in keeping up the health of your systems. If you don't, you will have problems at some point down the road and you will kick yourself for not making the upgrades sooner.

4\. Our goal is for people to be successful with PostgreSQL. In order to help people do that, it sometimes takes asking "stupid" questions. It will be worth your technical ego if it saves you time, money, and your sanity in the future.

5\. Take risks! Customers sometimes get nervous when we tell them what they are currently using just isn't going to work. The unknown can be unnerving but we are here to make things run as smoothly as possible. Take the risk and trust us!

So there it is, folks. You Postgres guys (and gals) out there do some really cool stuff. You make the technical world go round and most non-technical people don't even have a base understanding of your brilliance. I'm fortunate to have the CMD team to answer my "stupid" questions with patience and kindness. This is an adventure!

Angela

_Angela Roberson has been with Command Prompt for two and a half years. She is currently the CMD Team Manager and can help you with all of your non-geek customer needs._

---
[View this page online](https://www.commandprompt.com/blog/5_things_a_non-geek_girl_learned_from_playing_with_geeks_at_cmd/)

---

# A pg_basebackup Wish List

> pg_basebackup was introduced in Postgres 9.1 as a simple way to copy the data directory of a running database cluster. This was a great addition to a small gro…

[pg_basebackup](<http://www.postgresql.org/docs/current/static/app-pgbasebackup.html>) was introduced in Postgres 9.1 as a simple way to copy the data directory of a running database cluster. This was a great addition to a small group of [PostgreSQL Client Applications](<http://www.postgresql.org/docs/current/static/reference-client.html>).

The pg_basebackup approach differs from the standard pg_start_backup(), rsync (or other file system copy), pg_stop_backup() approach in that it uses the replication protocol over a standard Postgres connection to make the base backup. A few highlights: 

  * A completely standalone backup can be created easily by using the --xlog-method argument (the stream option here is particularly nice so that you don't have to muck with the [wal_keep_segments](<http://www.postgresql.org/docs/current/static/runtime-config-replication.html#GUC-WAL-KEEP-SEGMENTS>) Postgres setting).
  * Thanks to the cascading replication machinery in 9.2 pg_basebackup can take a backup from an active hot standby server (where the basic pg_start_backup() approach fails).
  * As of 9.3 pg_basebackup will even create a recovery.conf file for you (with the --write-recovery-conf switch), so it's basically a one-liner to get a standby with replication set up!



There's a lot to like, but I'm greedy....

## Wish #1: Parallelization

If "idle hands are the devil's playthings" I can only imagine what the devil would do with idle CPUs and network bandwidth. It would be great if pg_basebackup were able to parallelize creation of the base backup and make use of more available resources. In the past I've written a script to parallelize rsync by first processing its --itemize-changes output and then spawning multiple rsync processes in parallel to perform the copies; this parallelization can really cut down on the time to get a base backup copied. There are times when getting something done _as fast as possible_ trumps other concerns.

## Wish #2: Compression Options

Sometimes network bandwidth is in short supply. pg_basebackup has a --gzip switch to enable compression, but this compression is actually done on the client machine rather than the server. Certainly there is the option to run pg_basebackup from the originating server and use netcat (or scp, etc.) to get the data copied to the destination _if_ we are using pg_basebackup's --format=tar (-Ft) option. For example, on the originating server: 
    
    
    nierman@source:~$ pg_basebackup -D - -Ft -x | pbzip2 -p8 | nc -l 1201

(in an actual use case I'd also insert [pv](<http://www.ivarch.com/programs/pv.shtml>) in the pipeline to get nice status/progress updates at various stages), and on the destination server: 
    
    
    nierman@destination:~$ nc source 1201 > newbasedir/base.tar.bz2

This process is a bit more complicated than a single command from the client/destination server, but more importantly we lose out on things like streaming WAL files when using the tar format with pg_basebackup. Note that I've also used pbzip2 above (a parallelized version of bzip2). It would be great to have the option to use external programs like pbzip2, pigz, etc. with pg_basebackup compression. Let's call that Wish #2b. 

## Wish #3: Don't Die on Me Now!

Here's some output from a recent pg_basebackup session: 
    
    
    pg_basebackup: starting background WAL receiver
    2052690927/2052718105 kB (100%), 1/1 tablespace
    pg_basebackup: could not get transaction log end position from server:
    FATAL:  could not open file "./#postgresql.conf#": Permission denied

pb_basebackup chunked through almost 2TB of data and then it died just before finishing. Ack. Why? At some point someone had edited the postgresql.conf file as root and their editor saved the backup copy seen above (in the postgres data directory of course!); the Postgres backend couldn't read that file (owned by root) when creating the base backup. I would have loved to see a simple error message and have pg_basebackup continue on its merry way. Certainly an initial ls -l in the data directory is a good quick check that can be done manually, although that wouldn't save me from people that hide their cat photos deep inside the Postgres base directory.

---
[View this page online](https://www.commandprompt.com/blog/a_pg_basebackup_wish_list/)

---

# Just back from NYCPug August, on to more talks

> In August I spoke at NYCPUG on Dumb Simple PostgreSQL Performance. The talk was well accepted and there was about 60 people in attendance. I have always enjoye…

In August I spoke at NYCPUG on Dumb Simple PostgreSQL Performance. The talk was well accepted and there was about 60 people in attendance. I have always enjoyed my trips to NYC but this is the first time I have taken a leisurely look at the city. I found myself enjoying a water front walk from 42nd, through the Highline, to Battery Park, all the way to the Brooklyn Bridge and over to Brooklyn to a great pub for dinner. What I enjoyed most about the walk outside of the 10 miles was the community that was present. I think it is easy to get jaded by "midtown" and all that is the tourist in that area. The hustle and bustle, the pollution and dirt of a city. The waterfront walk however reminded me very much of Seattle, there was green and water everywhere, very little litter, lots of families and bike riders. All around a wonderful day and it made me look forward to coming back to NYC again in March for the NYC PostgreSQL Conference. 

Alas my travel schedule is just beginning. I will be speaking at the Seattle PostgreSQL User Group on Oct 1st. I will be giving the same talk as I did in NYC as it has been updated and always seems to be well received. If you are in town you should come join us: 

> 1100 Eastlake Ave E, Seattle, WA 98102 

I always enjoy Seattle and will also be making a side trip to Bellingham as it looks like I will be moving there soon. It will be sad to say good bye to the Columbia River Gorge but I am looking forward to the Mount Baker area as well as hopefully starting Vancouver, B.C. and Whatcom county PostgreSQL user groups. 

Just three weeks after Seattle, I will be cross the pond to wonderful Ireland where it is bound to be cold, dark and wet. That's alright though as I will plan on staying from Oct 26th - Nov 3rd, allowing for a full trip of sight seeing. Of course I will be dropping by on Friday the 1st to speak on PostgreSQL Backups which reminds me that I need to update the talk for the new pg_dump features found in 9.3.

---
[View this page online](https://www.commandprompt.com/blog/just_back_from_nycpug_august_on_to_more_talks/)

---

# Compiling and installing OpenSRF 2.2 on Centos 5.9

> We do quite a bit of work for King County Library systems. The library system has 45 branches and runs the Open Source Evergreen ILS. One of the very smart thi…

We do quite a bit of work for King County Library systems. The library system has 45 branches and runs the Open Source Evergreen ILS. One of the very smart things that the Evergreen project decided was that their database of choice would be PostgreSQL. One of the things that the Evergreen project is not good at is supporting LTS releases of Linux and therefore certain things can be a chore. For example, by default OpenSRF 2.2 which is the current stable OpenSRF release can not be installed via RPM or compiled from source by default on CentOS 5.9. 

When discussing with the community about CentOS, the response was the classic responses of, "just upgrade", "move to Fedora", "it isn't that hard to migrate to Debian" showing a clear misunderstanding of what it takes to support infrastructure on this scale. I digress. 

So what to do next? Well, get your hands dirty of course. 
    
    
    Use yum to (make sure you have EPEL):
        * Install gcc44 gcc44-c++ libevent-devel httpd-devel
    
    ** Note: make sure you only have the 64bit versions installed. 
    ** Yum will sometimes install both i386 and x86_64.
    
    Download compile and install: memcache 1.4.5
    
        * wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz
        * CC=/usr/bin/gcc44 CXX=/usr/bin/g++44 
          ./configure --prefix=/usr/local/memcache/
        * make install
    
    Download compile and install: libmemcache 1.0.7
    
    ** Note: 1.0.5 may also work as the requirement is libmemcache library version 0.8.0
    
        * wget \
          https://launchpad.net/libmemcached/1.0/1.0.7/+download/libmemcached-1.0.7.tar.gz
        * CC=/usr/bin/gcc44 CXX=/usr/bin/g++44 ./configure \
          --prefix=/usr/local/libmemcache/ \ 
          --with-memcached=/usr/local/memcache/bin/memcached
        * make install
    
    Add the new libmemcache to ld.so.conf (or create a /etc/ld.so.conf.d file):
        * /usr/local/libmemcache/lib
        * ldconfig -vv|grep mem (you should see something like this:)
             libmemcached.so.3 -> libmemcached.so.3.0.0
             libmemcachedprotocol.so.0 -> libmemcachedprotocol.so.0.0.0
             libmemcachedutil.so.0 -> libmemcachedutil.so.0.0.0
    /usr/local/libmemcache/lib:
             libmemcachedutil.so.2 -> libmemcachedutil.so.2.0.0
             libmemcached.so.10 -> libmemcached.so.10.0.0
             libmemcachedprotocol.so.0 -> libmemcachedprotocol.so.0.0.0
             libmemcached.so.2 -> libmemcached.so.2.0.0
             libmemcachedutil.so.0 -> libmemcachedutil.so.0.0.0
             libmemcached.so.2 -> libmemcached.so.2.0.0
             libmemcachedutil.so.0 -> libmemcachedutil.so.0.0.0
    
    The .so.3 is a dependency from the installed RPM. This should not cause any 
    problems as long as you see the /usr/local/libmemcache/lib line.
    
    Download compile and install: opensrf 2.2.0
        * cd (where you unpacked opensrf)/src/extras
            * make -f Makefile.install fedora 
              # this will install any outstanding perl packages etc
        * cd (where you unpacked opensrf); CC=/usr/bin/gcc44  \
            CXX=/usr/bin/g++44 CFLAGS="-I/usr/local/libmemcache/include" \
            LDFLAGS="-L/usr/local/libmemcache/lib" \ 
            memcached_CFLAGS=/usr/local/libmemcache/include \
            memcached_LIBS=/usr/local/libmemcache/lib LIBS=-lmemcached \
            ./configure --prefix=/usr/local/openils --with-gnu-ld 
        * make install
    
    cd /
    ln -sf /usr/local/openils .
    

At some point I might turn this into some rpm packages but right now, we solved the problem.

---
[View this page online](https://www.commandprompt.com/blog/compiling_and_installing_opensrf_22_on_centos_59/)

---

# Calling Bullsh*t in Open Source communities

> We are all human. We all lose our temper. We all have our moments of, &quot;I really wish I could take that back&quot;. Of course not if you are not Linus Torvalds. Now …

We are all human. We all lose our temper. We all have our moments of, "I really wish I could take that back". Of course not if you are not Linus Torvalds. Now everyone knows that Linus has a temper, that he is a foul mouth, lacks certain social graces and is generally one of the, if not the most important developers to surface in the last 20 years. Does that mean he gets to be a jerk? In his mind, yes. 

In some ways I agree with Linus. If you are a donkey butt and you don't pay attention to your community and follow its guidelines, then just leave. We don't have time for you anyway. We are trying to solve problems here. In other ways I don't agree with Linus because he exhibits a distinct lack of grace and grace will always get you further than angst. I have been taught this over and over through the years. Sometimes I get it right, sometimes I call out half the Postgres hackers in a room of 200+ and upset lots of itty bitty sensitive egos. So grace it is and grace I try to exhibit although sometimes fail. 

Linus could learn from this. Although he sits upon a high perch, he is greatly flawed in his thinking and there are some developers that are calling him on it. 

http://thread.gmane.org/gmane.linux.kernel.stable/58049/focus=1525074 

Linus excuses his behavior by stating it is just who he is: 

http://thread.gmane.org/gmane.linux.kernel.stable/58049/focus=1525074 

I once said that the days of Cowboy Open Source is over. Linus apparently didn't see that talk. People are going to tire of the, "I am a socially inept geek and therefore have an excuse to be a jackass excuse". In fact I would argue that most have already tired of it. 

Linus I would suggest you look at the -hackers community at Postgresql.org. There you will find a wide disparate group of hackers from dozens of different cultures who all manage to get the job done without juvenile threats, and foul language. They almost are always able to do it professionally too. Have a nice day.

---
[View this page online](https://www.commandprompt.com/blog/calling_bullsht_in_open_source_communities/)

---

# postgres_fdw for 9.2

> We have backported the postgres_fdw to 9.2. It is read only of course as the infrastructure for writes is not in 9.2 but it is usable. Enjoy it!

Postgres-FD…

We have backported the postgres_fdw to 9.2. It is read only of course as the infrastructure for writes is not in 9.2 but it is usable. Enjoy it! 

  * [Postgres-FDW](<https://github.com/commandprompt/postgres_fdw>)

---
[View this page online](https://www.commandprompt.com/blog/postgres_fdw_for_92/)

---

# The steaming pile that is Precise with kernel 3.2

> I don&#x27;t know if it is a mainline kernel problem but I can tell you that on 
Ubuntu Precise, Linux kernel 3.2 is a disaster for PostgreSQL. I am not even
goin…

I don't know if it is a mainline kernel problem but I can tell you that on Ubuntu Precise, Linux kernel 3.2 is a disaster for PostgreSQL. I am not even going to go into a huge rant about it. I am just posting the numbers. See for yourself. There should be a public service announcement about it. 

before upgrade to 3.9 
    
    
    08:35:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
    08:45:01 AM     all     30.91      0.00      5.66     40.05      0.00     23.38
    08:55:02 AM     all     29.32      0.00      5.10     39.66      0.00     25.92
    09:05:02 AM     all     31.71      0.00      6.24     40.99      0.00     21.06
    09:15:01 AM     all     32.45      0.00      6.59     46.74      0.00     14.21
    09:25:01 AM     all     20.62      0.00      5.39     60.00      0.00     14.00
    09:35:01 AM     all     31.03      0.00      3.61     33.95      0.00     31.41
    09:45:01 AM     all     36.54      0.00      3.22     34.13      0.00     26.11
    09:55:02 AM     all     40.17      0.00      3.66     30.98      0.00     25.19
    10:05:01 AM     all     33.49      0.00      3.04     32.28      0.00     31.19
    10:15:01 AM     all     48.63      0.00      2.87     25.50      0.00     23.00
    10:25:01 AM     all     51.34      0.00      3.56     26.06      0.00     19.04
    10:35:01 AM     all     39.41      0.00      3.44     29.86      0.00     27.29
    10:45:02 AM     all     36.07      0.00      8.79     30.94      0.00     24.20
    10:55:03 AM     all     38.04      0.00      7.98     32.98      0.00     21.01
    11:05:11 AM     all     39.25      0.00      8.81     36.75      0.00     15.19
    11:15:02 AM     all     35.19      0.00      8.76     41.98      0.00     14.07
    11:25:03 AM     all     38.21      0.00      9.65     38.86      0.00     13.28
    11:35:02 AM     all     42.92      0.00     11.66     34.28      0.00     11.14
    11:45:02 AM     all     39.40      0.00      9.96     39.03      0.00     11.61
    11:55:01 AM     all     28.72      0.00      3.27     36.32      0.00     31.69
    

after upgrade to 3.9 
    
    
                    CPU     %user     %nice   %system   %iowait    %steal     %idle
    08:35:02 AM     all     40.08      0.00      4.46     10.66      0.00     44.80
    08:45:01 AM     all     38.80      0.00      3.94      7.96      0.00     49.29
    08:55:01 AM     all     31.48      0.00      3.03      2.58      0.00     62.91
    09:05:01 AM     all     32.18      0.00      3.09      3.86      0.00     60.87
    09:15:01 AM     all     26.71      0.00      2.39      3.52      0.00     67.39
    09:25:01 AM     all     30.49      0.00      3.10      2.80      0.00     63.61
    09:35:01 AM     all     32.50      0.00      3.49      3.42      0.00     60.60
    09:45:01 AM     all     36.76      0.00      3.85      6.39      0.00     53.01
    09:55:01 AM     all     44.45      0.00      4.63      9.23      0.00     41.69
    10:05:02 AM     all     38.39      0.00      4.28      8.60      0.00     48.72
    10:15:01 AM     all     33.57      0.00      3.53      4.10      0.00     58.80
    10:25:01 AM     all     29.42      0.00      2.96      3.16      0.00     64.45
    10:35:01 AM     all     32.90      0.00      3.37      5.33      0.00     58.40
    10:45:01 AM     all     34.56      0.00      3.62      4.32      0.00     57.50
    10:55:01 AM     all     34.84      0.00      3.37      4.27      0.00     57.52
    11:05:02 AM     all     38.30      0.00      4.05      7.56      0.00     50.08
    11:15:01 AM     all     36.80      0.00      3.54      9.51      0.00     50.16
    11:25:01 AM     all     34.79      0.00      3.82      8.17      0.00     53.21
    11:35:01 AM     all     32.68      0.00      3.07      4.97      0.00     59.28
    11:45:02 AM     all     31.77      0.00      3.45      6.07      0.00     58.72
    11:55:01 AM    all     33.58      0.00      3.92      6.39      0.00     56.10

---
[View this page online](https://www.commandprompt.com/blog/the_steaming_pile_that_is_precise_with_kernel_32/)

---

# Returning multiple results without a round trip

> My blog on changes to the wire protocol [1] prompted this question from a reader:


&quot;Would it be necessary to modify the wire protocol to support multiple q…

My blog on changes to the wire protocol [1] prompted this question from a reader: 

> "Would it be necessary to modify the wire protocol to support multiple query/result-set combinations per server round-trip? That is, to be able to send a hundred different queries (each with a different number and type of columns in the result set) and receive a hundred different results all in a single network round-trip? That is a feature supported by some other databases that can have an order-of-magnitude effect on the performance of high-latency installations (satellite, etc.)." 

I did a little research into this and it seems that we can already do this, sort of. See the following: 
    
    
    postgres=# select 1; select 'two'; select 'three'; select 4;
     ?column? 
    ----------
            1
    (1 row)
    
     ?column? 
    ----------
     two
    (1 row)
    
     ?column? 
    ----------
     three
    (1 row)
    
     ?column? 
    ----------
            4
    (1 row)
    

This will avoid the round trip. However there is a limitation. If these were tables, the server would only send the metadata of the last SELECT. The metadata being things such as table description, and number of rows returned. So if you return data from 4 tables, you are only going to know what to do with the last of the tables returned. 

So it appears that the wire protocol does indeed support the ability to send multiple sets back but the server / libpq does not support sending multiple sets with isolated metadata. 

The benefit of supporting this could be huge. Consider in a web word you can often end up calling dozens if not hundreds of queries for a single page draw. A network round trip on its own is not expensive but if you add up 30 or 200 of them, the performance degradation adds up quickly. This is especially true when you consider that they each have their own overhead with the server processing the query. 

1\. [Modifying the backend protocol for 9.4/10.0](<http://www.commandprompt.com/blogs/joshua_drake/2013/05/modifying_the_backend_protocol_for_94100/>)

---
[View this page online](https://www.commandprompt.com/blog/returning_multiple_results_without_a_round_trip/)

---

# Modifying the backend protocol for 9.4/10.0.

> A recent discussion on the lists about potentially incompatible changes
to 9.4/10.0 of PostgreSQL the idea of things we wanted to do to the wire
protocol in …

A recent discussion on the lists about potentially incompatible changes to 9.4/10.0 of PostgreSQL the idea of things we wanted to do to the wire protocol in upcoming releases. 

The wire protocol is the language spoken between a client and the server of postgresql. The majority of programming languages out there do not implement their own version of the protocol instead opting to bind to the C library libpq. There are notable exceptions, specifically C# and Java both of which implement native versions of the wire protocol for their respective languages. 

The current wire protcol is v4 and was developed for 7.4 of PostgreSQL. That was released in 2003. I think we can safely say there is a lot of new thinking and things we want to change in the protocol to bring it up to newer thoughts on performance and features. A list of which can be found here: 

https://wiki.postgresql.org/wiki/Todo#Wire_Protocol_Changes 

One of them is particularly entertaining: Use Commpression. We had a patch for using compression on the wire protocol many years ago and we were essentially told there wasn't a use case. Funny how things change over time. That is the way of the community (replication now in core, cough cough) and we love it for it. The community is relatively conservative and because of that we have arguably the most stable and feature rich RDMS of it. 

An item I suggested was the ability for the wire protocol to understand the type of connection that was being requested. In short I want the ability to tell a connection that it is a read-write, read-only or write-only connection. In practice a read-only connection would work something like this: 
    
    
    conn-r = psycopg2.connect(database='testdb', user='test', conn-type='r')
    

I think this would be particularly useful to a tool such as pgPool-II. PgPool-II is a sophisticated software that supports replication, load balancing and query caching. Although we only use it for load balancing, which it is very good at. 

The problem is, it is relatively slow. It is slow because it has to parse each query that is executed to determine what to do with it. If it is a SELECT only then it can be load balanced. Again, it works well but if pgPool-II knew from the get go the type of connection it was dealing with because the protocol told it on negotiation then it wouldn't need to parse the query because the query was called on the conn-type='r' handle. 

I could see it also being useful in the future if we were to get load balancing into core. The connection receiving postmaster would see that it is a read-only connection and automatically pass it a replication slave. 

To see more of what is being discussed [you can review the thread.](<http://www.postgresql.org/message-id/CA+U5nMKYjubjyKNXdYkGjuk+xKKeqh-ES9SykH5sY-_3iR+-qg@mail.gmail.com>)

---
[View this page online](https://www.commandprompt.com/blog/modifying_the_backend_protocol_for_94100/)

---

# Considering PITRtools 1.4

> We quietly released PITRTool 1.3 last week. This version has been in development for a
long time and over the past 6 months became a priority to complete. The…

We quietly released PITRTool 1.3 last week. This version has been in development for a long time and over the past 6 months became a priority to complete. There is one known minor issue that may or may not be fixed as it doesn't affect production usage in a meaningful way. Release 1.3 contiues to support all the way back to 8.2 with warm standby but we also now support streaming replication and hot standby. 

With 1.4 we will be making some changes, quite a few of them in fact. Over the years replication and and log shipping has matured in PostgreSQL. We want to take advantage of that maturity. With that here are some of the changes we plan to make: 

  * Allow -B in cmd_standby to be multithreaded as well as CPU throttled. 

This will allow base backups to take advantage of multi-core machines as well as limit the amount of CPU resources that the process takes up. This will effectively eliminate any benefit to pg_basebackup when using PITRtools. 

  * Allow for generic start/stop/restart cluster commands. 

This was an interesting problem we came across with one of our clients who still run Solaris. They are using zones as well SMF. This means that PITRTools out of the box didn't properly work on their environment because we directly call pg_ctl from PITRtools. The solution we came up is to allow the following in the cmd_standby.ini 
    
        pg_start_cmd
    pg_stop_cmd
    pg_restart_cmd
    

This will allow custom calls from SMF or any other management interface to stop and start PostgreSQL. 

  * Make sane defaults for configuration options 

The configuration file has grown to a ridiculous number of options in 1.3. For 1.4 we are going to assume most commands are in $PATH. This will remove the need for many of our configuration options. We are considering still allowing specification of location if you don't use a standard path but that has yet to be decided. 

  * Add better monitoring and logging options When PITRtools was originally written there was no reasonable way to know what the state of a warm standby was. That has changed with recent releases of PostgreSQL. Thus we will enable the ability to monitor and log in a more verbose manner. 

  * Compress wal logs that are shipped/archived 

PITRtools already has a queuing mechanism for wal logs but they are stored uncompressed. This could benefit from compression on the disk. 

  * Potentially adding non replication options 

PITRtools has all the mechanisms to properly handle postgresql backups. Why not add the option? 

Of course more things will come as we discuss further. Feel free to join the project and let us know your ideas! 

1\. [PITRtools](<https://public.commandprompt.com/projects/pitrtools/wiki>)

---
[View this page online](https://www.commandprompt.com/blog/considering_pitrtools_14/)

---

# Remembering to check the docs: Autovacuum

> I was on a call very late last night with a good customer. Well, it was very early. They were having some performance problems and we were talking through how …

I was on a call very late last night with a good customer. Well, it was very early. They were having some performance problems and we were talking through how to resolve them before the EST wake up. It is late, we are all tired and of course there are too many people on the call. 

So what is the problem? The problem is they weren't running Autovacuum. Now many of my brethren would say, "HERESY!" but in reality there are good reasons not to run Autovacuum (although I would say not Autoanalyze). Autovacuum is unpredictable, and can cause performance problems. 99% of the time you should run Autovacuum but there is a 1% reason to consider other alternatives. 

The point I trying to make here in my sleep deprived state is that Autovacuum can be turned on with just a reload. It does not require a restart. I swore up and down that it required a restart and I ended up being wrong. I am not sure why I thought it needed a restart. 

So there you go folks. Tip of the day, "autovacuum = on" only needs a reload. 

Tallyho read the docs!

---
[View this page online](https://www.commandprompt.com/blog/remembering_to_check_the_docs_autovacuum/)

---

# GNU and the FSF should be split up

> The FSF should be broken up.

Yes, I really did just write that. I believe the the FSF no longer fulfills its
mission. Wait, let&#x27;s back up a step. I can feel t…

**The FSF should be broken up.**

Yes, I really did just write that. I believe the the FSF no longer fulfills its mission. Wait, let's back up a step. I can feel the torches started to be covered in pitch and the frankenstein cry of, "kill the heretic" starting to rumble through the old streets of the Free Software country. I am not here to say that the FSF is useless or that it doesn't have purpose. I am not here to say that Richard Stallman shouldn't continue on his political mission to save the world from the use of rightfully produced and licensed closed source software. 

What I am saying is that the FSF and GNU should separate and that this separation will act as a catalyst to allow for both to complete its mission in a more productive manner. That's right, fsf.org and gnu.org should be two separate non profits, with two different boards. Yes, I am aware that the two are one and it shall and always be. I am declaring that "for better or worse" is now worse and a divorce is now in order. 

I have the deepest respect for the GNU project. I write this blog entry largely on software that would not be possible without GNU components. I run Linux (no, not GNU/Linux). I run KDE 4.10. I write this in Kate, although I normally prefer Joe. I run PostgreSQL. I run Pidgin, Thunderbird, Gimp, Google Chrome (no not Chromium), Wine, Netflix Desktop, Python, LibreOffice and my music is playing using Amarok. And this my fine Open Source (yes Open Source, not Free Software) denizens is exactly why I think GNU should fork from FSF. 

FSF/Richard Stallman is a political movement. A political ideal full zealotry. It is uncompromising, unrelenting, stalwart and venerable. It has done a lot of good, it continues to strive to do a lot of good. However... 

"The Free Software Foundation (FSF) is a nonprofit with a worldwide mission to promote computer user freedom and to defend the rights of all free software users."[1] 

**On the other hand:**

"The primary and continuing goal of GNU is to offer a Unix-compatible system that would be 100% free software. Not 95% free, not 99.5%, but 100%. The name of the system, GNU, is a recursive acronym meaning GNU's Not Unix a way of paying tribute to the technical ideas of Unix, while at the same time saying that GNU is something different. Technically, GNU is like Unix. But unlike Unix, GNU gives its users freedom."[2] 

As you can see, although both are inextricably intertwined but they are also fundamentally different in their purpose. One is about freedom and rights of users. The other is about developing Free Software. 

It is my assertion that the continued political movement of the FSF is causing the GNU Project to suffer from slow, politicized and in some ways arcane development. Consider, what tools you use. How many of those tools are actually from the GNU project? All the tools I previously listed, do they need GNU? Absolutely. Are any of them from GNU? Only GIMP. I think you will find this is the case with most modern Open Source (and Free Software) users. 

It is time for developers not lobbyists to run GNU. 

  1. http://www.fsf.org/about/ 
  2. http://www.gnu.org/gnu/about-gnu.html

---
[View this page online](https://www.commandprompt.com/blog/gnu_and_the_fsf_should_be_split_up/)

---

# Writing a custom conflict handler for Bucardo 4

> Bucardo, an asynchronous multi-master replication system (or, maybe the asynchronous multi-master replication system for PostgreSQL, cause I know of no other a…

Bucardo, an asynchronous multi-master replication system (or, maybe the asynchronous multi-master replication system for PostgreSQL, cause I know of no other actively developed ones), deals with replication conflicts by providing conflict handlers in a form of standard (built-in) or custom code procedures. The built-in conflict handlers resolve a conflict by taking a row from the source or the target databases (in Bucardo 4 only 2 masters are supported, called 'source' and 'target' below), or using a delta row timestamp to determine the winner; other options include skipping conflicting rows altogether or picking one at random, but they are not very useful if you need the data to be consistent between replicas. For more complex conflict resolution rules it's necessary to write a custom conflict handler and, since the documentation is really scarce on that matter, I've decided to show how to create a simple one.

For the test we'll be using a simple database named 'test' with a single table:
    
    
    CREATE TABLE test.products(product_id INTEGER PRIMARY KEY, name VARCHAR, 
    price float); 

Suppose the table exists on both replicas, initially empty. Let's setup a simple Bucardo master-to-master replication:
    
    
    bucardo_ctl add database source_test name=test host=source.local user=postgres
    bucardo_ctl add database target_test name=test host=target.local user=postgres
    bucardo_ctl add table test.products db=source_test herd=sample
    bucardo_ctl add sync test_swap source=sample targetdb=target_test type=swap
    

Yikes, we've got an error: 
    
    
    WARNING: Issuing rollback() due to DESTROY without explicit disconnect() of
    DBD::Pg::db handle dbname=test;host=source.local;port=5432 at line 29.
    CONTEXT:  PL/Perl function "validate_sync"
    SQL statement "SELECT validate_sync('test_swap')"
    PL/Perl function "validate_sync"
    Failed to add sync: DBD::Pg::st execute failed: ERROR: Table "test.products"
    must specify a way to handle conflicts at line 285. at line 30.
    CONTEXT: PL/Perl function "validate_sync" at /usr/local/bin/bucardo_ctl line
    3362.
    

The problem is that we haven't specified how replication conflicts should be resolved. For this, let's add a custom handler to the 'test' table and try to add the sync once more:
    
    
    bucardo_ctl add customcode example src_code=code/sample.pl whenrun=conflict 
    goat=1
    bucardo_ctl add sync test_swap source=sample targetdb=target_test type=swap
    

The sync is added normally. You can start Bucardo with _bucardo_ctl start_ and replicate a couple of rows to make sure it works.
    
    
    bucardo_ctl start
    
    psql -h source test -c "INSERT INTO test.products(id, name, price)
    SELECT id, 'product '||id, id+0.99 from generate_series(1,3) id"
    psql -h source test -c "INSERT INTO test.products(id, name, price)
    SELECT id, 'product '||id, id+0.99 from generate_series(4,5) id"
    
    ...
    psql -h source test -C 'SELECT count(*) FROM test.products
    psql -h target test -C 'SELECT count(*) FROM test.products
    

If everything works normally, 5 should be returned for both source and target databases.

Let's examine the custom conflict handler line. Obviously, the code should only be executed during conflicts, as indicated by the whenrun option. The line also contains the ID of the goat (table) the code should be added to. I'm not aware of a variant of bucardo_ctl command to get that id, but it's pretty simple once you recall that Bucardo keeps all the settings in the database and per-table properties are stored in the bucardo.goat table:
    
    
      select id from goats where name='test.products';  

The command also suggests that the custom code should be written in Perl, much like Bucardo itself. Below is the contents of sample.pl. The conflicts are resolved by choosing the row with the highest price value. Here's the code from sample.pl
    
    
    my ($args) = @_;
    return if (exists $args->{dummy});
    my $sourceprice = $args->{rowinfo}{sourcerow}{price};
    my $targetprice = $args->{rowinfo}{targetrow}{price};
    my $winningdb = "";
    if ($sourceprice > $targetprice) {
           $args->{rowinfo}{action} = 1;
    	   $winningdb = $args->{sourcename}
    } else {
    	   $winningdb = $args->{targetname}
           $args->{rowinfo}{action} = 2;
    }
    $args->{message} = "$winningdb won, price: ".$targetprice;
    

The $args->{dummy} is the magic that Bucardo verifies to identify its own custom code. The code following that line reads the price values from source and target rows, compares them and decides which database wins. The lines that make Bucardo perform specific actions are the ones that assign new values to the $args->{rowinfo}{action} attribute. The value should be a bitmap of the following flags (the description below is actually taken directly from Bucardo source code).
    
    
    	1 = Add source row to the target db
    	2 = Add target row to the source db
    	4 = Add source row to the source db
    	8 = Add target row to the target db
    

Let's update source and target database rows with the same product_id but with different price values, simulating a conflict:
    
    
    psql -h source -c 'update test.products set price=10 where product_id = 1' 
    test;
    psql -h target -c 'update test.products set price=5 where product_id = 1' 
    test
    UPDATE 1
    UPDATE 1
    

The commands above lead to some activity in the Bucardo log. The relevant messages are:
    
    
    [Wed Nov 21 10:13:56 2012] CTL Got notice "bucardo_ctl_kick_test_swap" from
    24779
    [Wed Nov 21 10:13:56 2012]  KID Target delta count for test.products: 1
    [Wed Nov 21 10:13:56 2012]  KID Total source delta count: 1
    [Wed Nov 21 10:13:56 2012]  KID Total target delta count: 1
    [Wed Nov 21 10:13:56 2012]  KID Total delta count: 2
    [Wed Nov 21 10:13:56 2012] KID Logged details of conflict to
    bucardo_conflict.log
    [Wed Nov 21 10:13:56 2012]  KID Running conflict custom code 22: example
    [Wed Nov 21 10:13:56 2012]  KID Finished custom code 22
    **[Wed Nov 21 10:13:56 2012] KID Message from conflict code 22: source_test won,
    price: 10**
    [Wed Nov 21 10:13:56 2012]  KID Conflict handler action: 1
    [Wed Nov 21 10:13:56 2012]  KID Action summary: 1:1
    **[Wed Nov 21 10:13:56 2012]  KID [1/1] test.products UPDATE source to target 
    pk 1**
    

Lines above indicate that the target database will be updated with the source row, since it has the highest price value among the two. Note the message from the custom code: it's the line written to $args->{message}. A good way to get yourself acquainted with various information stored in args is to use Data::Dumper to dump that information into $args->{message} (the other way is to read the source code, e.g. search for rowinfo hash inside Bucardo.pm). 

Let's check that the conflict is actually resolved in favor of the source database:
    
    
    psql -U bucardo -d test -h **source** -c 'SELECT price FROM test.products WHERE
    product_id = 1'
     price 
    -------
        10
    (1 row)
    
    psql -U bucardo -d test -h **target**  -c 'SELECT price FROM test.products
    WHERE product_id = 1'
     price 
    -------
        10
    (1 row)
    

At this point you may wonder about the last two actions in the bitmap above. Why might it be necessary to add the source row to the source database or the target row to a the target one? The answer becomes obvious once you learn that the handler can modify the rows written to the respective databases by changing the contents of the %rowinfo hash. For instance, let's write a new custom code that updates both conflicting rows with the average of their price values. Since the updated rows will be different from the original source and target ones, they should be propagated to both databases. That's when those two final bitmap actions come in handy. The new code looks like this:
    
    
    my ($args) = @_;
    return if (exists $args->{dummy});
    my $sourceprice = $args->{rowinfo}{sourcerow}{'price'};
    my $targetprice = $args->{rowinfo}{targetrow}{'price'};
    
    my $newprice = ($sourceprice + $targetprice)/2;
    $args->{message} = "Updating $args->{sourcename} and 
    $args->{targetname} with price $newprice";
    
    $args->{rowinfo}{sourcerow}{'price'} = $newprice;
    $args->{rowinfo}{targetrow}{'price'} = $newprice;
    
    # update source db with source row + update target db with target row
    $args->{rowinfo}{action} = 12; 
    

To install the new code it's necessary to reload the corresponding sync: 
    
    
    bucardo_ctl update code sample src_code=src/sample_new.pl
    bucardo_ctl reload sync test_swap
    
    bucardo_ctl reload test_swap
    Reloading sync test_swap...
    

Let's check the result:
    
    
    psql -h source -c 'update test.products set price=20 where product_id = 1' 
    test;
    psql -h target -c 'update test.products set price=40 where product_id = 1' 
    test
    UPDATE 1
    UPDATE 1
    

The following lines appear in the log:
    
    
    [Wed Nov 21 16:29:04 2012] CTL Got notice "bucardo_ctl_kick_test_swap" from
    24779
    [Wed Nov 21 16:29:04 2012]  KID Target delta count for test.products: 1
    [Wed Nov 21 16:29:04 2012]  KID Total source delta count: 1
    [Wed Nov 21 16:29:04 2012]  KID Total target delta count: 1
    [Wed Nov 21 16:29:04 2012]  KID Total delta count: 2
    [Wed Nov 21 16:29:04 2012] KID Logged details of conflict to
    bucardo_conflict.log
    [Wed Nov 21 16:29:04 2012]  KID Running conflict custom code 22: example
    [Wed Nov 21 16:29:04 2012]  KID Finished custom code 22
    **[Wed Nov 21 16:29:04 2012] KID Message from conflict code 22: Updating
    source_test and target_test with price 30**
    [Wed Nov 21 16:29:04 2012]  KID Conflict handler action: 12
    [Wed Nov 21 16:29:04 2012]  KID Action summary: 12:1
    **[Wed Nov 21 16:29:04 2012] KID [1/1] test.products UPDATE source to source pk 1**
    **[Wed Nov 21 16:29:04 2012] KID [1/1] test.products UPDATE target to target pk 1**
    [Wed Nov 21 16:29:04 2012] KID Updating bucardo_track for test.products on
    source_test
    [Wed Nov 21 16:29:04 2012] KID Updating bucardo_track for test.products on
    target_test
    [Wed Nov 21 16:29:04 2012]  KID Issuing final commit for source and target
    

And the result is exactly the average of the row price values: 
    
    
    
    psql -U bucardo -d test -h source -c 'SELECT price FROM test.products WHERE
    product_id = 1'
     price 
    -------
        30
    (1 row)
    
    psql -U bucardo -d test -h target -c 'SELECT price FROM test.products WHERE
    product_id = 1'
     price 
    -------
        30
    (1 row)
    

This post highlights only a small subset of Bucardo custom code capabilities. At the moment, the only way to learn more is by digging into the source code or reading the test cases provided with it. I hope it will be useful to anyone learning about Bucardo multi-master capabilities. Bucardo 5, the new version of Bucardo, may add even more features to conflict resolution code (and, hopefully, make it easier and better documented). Meanwhile, if you are willing to share your examples of Bucardo 4 custom code, use the comments to this post.

---
[View this page online](https://www.commandprompt.com/blog/writing_a_custom_conflict_handler_for_bucardo_4/)

---

# ... and that was my last day

> This has been cooking for a while now, and now it&#x27;s time to open it up: July 31st, 2012 was my last day with Command Prompt, Inc.
I joined Command Prompt in O…

This has been cooking for a while now, and now it's time to open it up: July 31st, 2012 was my last day with Command Prompt, Inc.

I joined Command Prompt in October 2005. Back then I wasn't a very prolific blogger, it seems, because it took me six months to [get this fact out](<http://advogato.org/person/alvherre/diary/6.html>). I haven't improved much since then, even though boss Josh Drake kept telling me to publish my thoughts and ideas on various PostgreSQL-related matters.

During my time with them I had the opportunity to work on many interesting things. I got a number of patches into PostgreSQL, some of them thanks to some Command Prompt customer sponsoring it; I worked on the Command Prompt proprietary PostgreSQL fork, Mammoth Replicator, and on PL/php; and I got to talk to very smart people, learn a lot, and generally have tons of fun.

I enjoyed my time with Command Prompt very much; the colleagues I leave are very capable and knowledgeable. I particularly have to thank Alexey Klyukin with whom I shared thousands of hours of work in all kinds of projects.

But I decided a needed a change, so I'm leaving Command Prompt. I had some job offers at PGCon, and I have already decided what I'm going to do; I look forward to many more years of PostgreSQL hacking and bug-hunting.

Command Prompt has been growing in business and number of employees lately; I hope that trend continues and that they have great success. I heartfully thank Command Prompt very much for the great opportunity they gave me all these years.

See you in pgsql-hackers.

---
[View this page online](https://www.commandprompt.com/blog/and_that_was_my_last_day/)

---

# Fedora 17 not so easy PostgreSQL configuration

> I don&#x27;t usually post rants here, but this one might be actually helpful to others, so let&#x27;s make an exception. It will be related to installing PostgreSQL from…

I don't usually post rants here, but this one might be actually helpful to others, so let's make an exception. It will be related to installing PostgreSQL from distro-specific packages. I usually prefer setting PostgreSQL from sources, unlike the majority of users; nevertheless, I'm familiar with how popular distros, like Debian or Fedora, manage their PostgreSQL layouts. Or so I thought until today. 

My task was simple: install PostgreSQL instance for testing on a fresh Linux box, use a non-standard port. The catch: the box was running a relatively new Fedora 17. 

Normally, I run a single database instance per each host, so I find Fedora's PostgreSQL layout much more straightforward then Debian's: all configuration files are stored in $PGDATA ( _/var/lib/pgsql/data_ by default), just like in a source-based installation. Everything you need to change should be there. 

I launched vim on _/var/lib/psql/data/postgresql.conf_ , uncommented **listen_address** , setting it to '*' to allow the server to listen on TCP sockets and modified the **port** line to 5552. Afterwards, I did 
    
    
    service postgresql restart

Nothing happened. By examining 
    
    
    ps ax|grep postgresql

I confirmed my guess that the port number is embedded into the PostgreSQL command-line. So, let's check _/etc/rc.d/init.d/postgresql.service_. 

Alas, there were no postgresql related files there. At that moment I started to have my suspicions. I did 
    
    
    find / -name 'postgresql*'

and found a bunch of files called postgresql.service. The most promising of them was _/usr/lib/systemd/system/postgresql.service_ , so I pointed my editor there. The file indeed contained the setting for PostgreSQL port, along with a warning, stating the changes would be overwritten during package. There was a suggestion to create _/etc/systemd/system/postgresql.service_ and include the current postgresql.service there before adding a line that changes PGPORT. 

I did the suggestion above and issued service postgresql restart once again. My custom _postgresql.service_ looked like this: 
    
    
    .include /usr/lib/systemd/system/postgresql.service
    [Service]
    Environment=PGPORT=5552
    

Guess what - nothing had changed. Before giving up and going to google for answers I had tried on last thing - changing the _/usr/lib/systemd/system/postgresql.service_ directly, despite the warning, and doing service restart. Amusingly, nothing changed even then, but I got another warning suggesting to run systemctl --system daemon-reload. 

Finally, I reverted my _/usr/lib/systemd/system/postgresql.service_ changes, did 
    
    
    systemctl --system daemon-reload

restarted postgresql service one last time and the changes in _/etc/systemd/system/postgresql.service_ finally came into effect. Ran netstat and confirmed that PostgreSQL instance was listening on port 5552 at last. It took no less than 10 steps to figure this out. 

In a conclusion, I totally understand that every distro packagers have a right to make PostgreSQL configuration process as complex as they want, but with a such popular one as Fedora and the trend to make PostgreSQL easier for new users I find the whole procedure ridiculously complicated. Pushing the changes to the Fedora layout might be hard, but here's one small thing that will make the configuration easier right away: just add a comment to the postgresql.conf shipped with Fedora, describing the process to change the port parameter. 

Now off to do actual work :-)

---
[View this page online](https://www.commandprompt.com/blog/fedora_17_not_so_easy_postgresql_configuration/)

---

# The Write Ahead Log: Essentials

> WAL (acronym for the Write Ahead Log) is the mechanism that Postgres uses to implement durability (the D in ACID) of data changes in the face of a system crash…

**Updated: 08/08/2022**

 **By: Joshua D. Drake**

## What is WAL

WAL (Write Ahead Log) is the mechanism that Postgres uses to implement durability (the D in [ACID](<https://en.wikipedia.org/wiki/ACID>)) of data changes in the face of a system crash. WAL is also a critical component for Postgres to provide binary replication, Point in Time Recovery as well as online binary backups.

The central philosophy of Postgres durability is that data must be written to the WAL and marked as written to permanent storage before the data is written to data pages. The guarantee of this durability is accomplished by the fsync system call or equivalent mechanism and is controlled by three primary postgresql.conf parameters: fsync, wal_sync_method, and synchronous_commit. The benefit of this process is that Postgres does not need to write data pages to permanent storage on every transaction commit because in the event of a crash we will be able to recover Postgres to a consistent state using the WAL. If a crash occurs, pages (data) that have not yet been written but are consistent will be recovered from the WAL and written to the data pages.

 _Note: WAL files reside in the directory $PGDATA/pg_wal and data pages reside under the directory structure $PGDATA/base/$database/$datapages_

A performance benefit of the WAL design is a significant reduction in the number of disk flushes (writes) as the WAL only needs to be flushed to permanent storage at the time of transaction commit. In a multiuser environment, commits of many transactions may be accomplished with a single flush of the WAL file. As the log file is written sequentially, the cost of the flushing is much less than that cost of writing to the data pages. This is because data pages are written in a random-write fashion. This performance benefit is especially true in instances where you have a lot of small transactions working on different parts of the database. Fortunately, with the prevalence of memory based permanent storage (SSD, NVME, etc…) the benefit of WAL being written sequentially is no longer often realized.

## Configuring WAL

The five primary parameters for configuring WAL are wal_level, fsync, wal_sync_method, synchronous_commit, and full_page_writes.

### wal_level

The wal_level determines the level of information that will be written to the WAL. Different levels provide different feature capabilities within Postgres. The three levels of WAL are minimal, replica and logical. It requires a Postgres full restart to change this parameter.

#### minimal

This is the minimum level of WAL which only keeps enough information to recover from a crash. You will be unable to use the Binary Replication, Logical Replication or Point In Time Recovery features of Postgres with wal_level configured to this setting. Use this setting only when working locally as you significantly limit further capabilities. A benefit of this setting is that the WAL will record less information and thus require less I/O than the other two settings.

#### replica

This level provides enough information for all Binary Replication and Point in Time Recovery but not Logical Replication.

#### logical

This level records the most information to the WAL. It also enables the feature Logical Replication and Logical Decoding. If you have the I/O it is recommended that you use this setting as a default. Logical Decoding allows the use of external capabilities such as replicating from Postgres or WAL2JSON.

### fsync

This parameter determines if Postgres will call an fsync() on every commit of a transaction.

The options for this parameter are [on|off]. Leave this on at all times. Turning this parameter off will eventually lead to data corruption as Postgres will have zero guarantees if the data being written to disk properly.

### wal_sync_method

This is the type of fsync() that will be called. Generally speaking it is safe to leave this alone as the initialization of the Postgres cluster by initdb will perform a quick test to see which one is the most efficient. You can also test your platform for the best setting by using pg_test_sync. When using Linux derived operating systems, open_datasync is generally the most efficient.

#### Example use of pg_test_sync

The following is the output of using pg_test_sync on a laptop running Ubuntu 22.04 with an NVME drive. It is a consumer level drive so it is nowhere near as fast as what you would expect in a server based installation. Of note is that the test uses 8kB and 16kB sizes for writes. This is because PostgreSQL shared_buffers and page size are 8kB. The higher the ops/sec the better.
    
    
    ./pg_test_fsync -f /tmp/pg_test_sync.out
    
    5 seconds per test
    O_DIRECT supported on this platform for open_datasync and open_sync.
    
    Compare file sync methods using one 8kB write:
    (in wal_sync_method preference order, except fdatasync is Linux's default)
           open_datasync                      3127.328 ops/sec     320 usecs/op
           fdatasync                          2236.094 ops/sec     447 usecs/op
           fsync                              1972.384 ops/sec     507 usecs/op
           fsync_writethrough                              n/a
           open_sync                          1962.019 ops/sec     510 usecs/op
    
    Compare file sync methods using two 8kB writes:
    (in wal_sync_method preference order, except fdatasync is Linux's default)
           open_datasync                      1390.982 ops/sec     719 usecs/op
           fdatasync                          2160.199 ops/sec     463 usecs/op
           fsync                              1915.200 ops/sec     522 usecs/op
           fsync_writethrough                              n/a
           open_sync                           957.680 ops/sec    1044 usecs/op
    
    Compare open_sync with different write sizes:
    (This is designed to compare the cost of writing 16kB in different write
    open_sync sizes.)
            1 * 16kB open_sync write          1930.955 ops/sec     518 usecs/op
            2 *  8kB open_sync writes          969.495 ops/sec    1031 usecs/op
            4 *  4kB open_sync writes          469.447 ops/sec    2130 usecs/op
            8 *  2kB open_sync writes          234.476 ops/sec    4265 usecs/op
           16 *  1kB open_sync writes          111.828 ops/sec    8942 usecs/op
    
    Test if fsync on non-write file descriptor is honored:
    (If the times are similar, fsync() can sync data written on a different
    descriptor.)
           write, fsync, close                1909.474 ops/sec     524 usecs/op
           write, close, fsync                1910.523 ops/sec     523 usecs/op
    
    Non-sync'ed 8kB writes:
           write                            876074.096 ops/sec       1 usecs/op

  
The Non-sync’ed result can be tempting. It means that an fsync() was not called after each write and is the effective result of running with fsync = off. It is critical that one understand that this is not a safe way to operate PostgreSQL, you **will eventually corrupt** your database.

### sychronous_commit

This parameter determines if Postgres is going to write to WAL in a synchronous or asynchronous fashion. There are multiple valid options: remote_apply, on (the default), remote_write, local, and off.

We are only going to discuss the options of **on** or **off**. The other options are for an environment where Postgres is utilizing replication. The most significant user-visible difference when writing data in synchronous (on) or asynchronous (off) fashion is two-fold. First is performance: writing synchronously is slower, however it guarantees that your data is written to permanent storage at transaction commit. While synchronous_commit is enabled, the Postgres backend that is submitting data will wait for a return of TRUE that the WAL process has flushed the data to disk. When synchronous_commit is off, the Postgres process will only wait for the WAL process to confirm that it has the data, not that it has been written to disk. Although rare, if you write asynchronously there is an opportunity that you may lose data that was considered committed by your application on a crash of the Postgres server.

#### Consistency

Whether synchronous_commit is on or off does not affect the consistency or validity of your data. This means that even in the event of a database crash all of your foreign keys, rows, index entries etc.. are protected from violation or corruption by the WAL.

### Full page writes

By default and for data safety reasons, Postgres will write the complete page to WAL if it is the first modification of the page. This is necessary because if Postgres crashes during a page write, Postgres may end up with a page that contains old and new data. The data stored in WAL if full_page_writes is off will not be enough to properly restore the page during crash recovery. This parameter is similar to fsync in that turning it off will increase performance with inevitable data corruption and worse, it may be silent corruption.

## Checkpoints

A checkpoint is a point in the transaction sequence where Postgres will write all data in memory and changes that have been reflected in WAL to the data files. In a practical sense, the checkpoint process is used to help manage the size of WAL and to ensure that at some point in time, data is guaranteed to be written to the data files.

There are four (of six) primary parameters that control checkpoint behavior. They are checkpoint_timeout, checkpoint_completion_target, max_wal_size, and min_wal_size.

### checkpoint_timeout

This is the total time between an automatic checkpoint. It has a valid range of 30 seconds to one day. The default is five minutes. If you have an application that utilizes a lot of writes (insert/update/delete) it is almost always best to change the default. A reasonable recommendation is to set this to 30 to 60 minutes. However, increasing this parameter will increase the WAL size on disk, potentially causing an overflow of max_wal_size and thus forcing a checkpoint.

### checkpoint_completion_timeout

This is the target of completing a checkpoint as a fraction of time between checkpoints. The default is 0.9 and should not be changed. In earlier versions of Postgres the default was 0.5 and almost universally caused performance degradation as you would essentially perform two checkpoints between checkpoint_timeout. Decreasing this parameter will increase your overall I/O load.

### max_wal_size

This is the total amount of disk space that WAL may consume before a checkpoint is forced. The default is 1GB. This is a soft limit as there are a number of parameters and workload conditions that can cause the WAL to exceed the value without causing a checkpoint. Some of this include a failing archive_command, heavy server load, or use of the deprecated wal_keep_segments setting. If you have available storage this is a reasonable setting to increase. However, without proper tuning of the wal writer this can cause an unreasonable amount of data to be written during a checkpoint which may cause performance issues.

 _Note: Increasing the size of max_wal_size will increase recovery times if Postgres crashes_

### min_wal_size

Postgres will recycle WAL files for future use during a checkpoint rather than remove them if the storage space used for WAL is below this size on disk. This can help reduce unexpected spikes in WAL usage. For example, when running long transactions with heavy writes (batch jobs). If you specify a value without units, it is interpreted as megabytes. The default is 80MB. If your transactional load often contains heavy writes within a single transaction, increasing this parameter may help your overall write performance.

#### References

All of the information found in this article can also be found within the official Postgres documentation:[ http://www.postgresql.org/docs/current/static/wal-configuration.html](<http://www.postgresql.org/docs/current/static/wal-configuration.html>) and links therein.

The original author of this blog was Alvaro Herrera. Substantial changes have been made since then.

---
[View this page online](https://www.commandprompt.com/blog/the_write_ahead_log/)

---

# In considerations of closed source development

> Open Source development has a lot going for it, as Bruce Momjian readily points out in a recent blog [1]. However, I believe he missed some key points that are…

Open Source development has a lot going for it, as Bruce Momjian readily points out in a recent blog [1]. However, I believe he missed some key points that are positive for closed source development. Bruce asserts that with Open Source development the developers are the face of the software. That is true but certainly isn't always a good thing. There is a reason that the majority of software development, revenue generation, and software developer employment is closed source (and no it isn't because management and marketing are trying to keep the developer down). 

It is simple. Most of us Open Source developers aren't generally good with average people. We are good with our "breed" of people but move us out of our element and suddenly we can be awkward, offensive, and generally weird. We talk differently than other people, we have inside humor that doesn't span directions, and are just as inclusive as the richest Skull & Bones society members. Is this bad? No, it is reality. Whenever you take a group of individuals who are on a different playing field than the average person you are going to end up in this situation. 

The second point that Bruce states is that closed source users have very little interaction with users. I think this is misunderstood. To say that Open Source has more interaction with users is, in my opinion, completely false or is at least given much more weight than is reality. Ask any consultant: the majority of their customers have zero idea about the workings of the community, how to communicate with the community, or interactions with developers. Frankly, they don't want to. They have software to run, businesses to operate, and employees to pay. 

This can be further illustrated by watching the community. It tooks PostgreSQL years longer than it should have to get replication, and the community is just now starting to look at logical replication, features that were available in closed source versions of PostgreSQL and as open source addons years ago. The users wanted integrated replication but the community wasn't willing to implement them at the time. 

Please don't get me wrong, I love Open Source. I love Open Source development. Heck, the only closed source software I run is to play Civ5 occasionally. Everything else is Open Source but I do think that we need to keep perspective on what is going on in the very large world that does not involve Open Source. It is much bigger, in a lot of ways more productive, and employ smore people (a rarity in today's economy) than Open Source could ever hope to. 

1\. http://momjian.us/main/blogs/pgblog/2012.html#July_2_2012

---
[View this page online](https://www.commandprompt.com/blog/in_consideration_of_close_source/)

---

# Binding PostgreSQL server to specific CPU cores in Linux

> Recently we had a customer who was running PostgreSQL 8.2 on a 32 cores system with 64GB of memory. They were deploying this server in addition to the already …

Recently we had a customer who was running PostgreSQL 8.2 on a 32 cores system with 64GB of memory. They were deploying this server in addition to the already running one with 24 total cores and 32GB of memory. PostgreSQL configuration has been adjusted for extra resources, the database has been partitioned roughly in half between the 2 servers and the queries running against both servers were similar. 

Suprisingly, when compared to the old server, the extra resources didn't improve the performance. Quite the contrary, the load average and CPU utilization on a new system was much higher during load spikes, while the TPS number plummeted. After performing initial examination of their server (applying our [Audit & Tune package](<http://commandprompt.com/products/audit_and_tune/>)) we've decided that 8.2 might itself become an issue. This version of PostgreSQL is outdated and no longer supported by the community. What was suggested is that 8.2 doesn't scale well for 32 cores. How can we verify that hypothesis? Since they were running a relatively modern Linux kernel (2.6.32, supplied with RHEL 6) we were able to take advantage of the interface provided by the taskset utility. 

taskset is a small Linux tool that allows setting the CPU affinity of the process, i.e. which cores a given process is scheduled to run on. For instance, if we have total 4 cores available and willing to limit the process ID 12345 to the last two cores (the first two might be handling a lot of I/O) we can do it with the following command, assuming you are the owner of PID 12345 (CPU cores start from 0): 
    
    
    taskset -pc 2,3 12345

Alternatively, the set of CPU cores can be specified by a hexadecimal bitmask, which is convenient if the mask is calculated programatically. The last 2 cores out of 4 total are represented by the 1100 binary mask, hex 0xC. The command above is equivalent to: 
    
    
    taskset -p 0xC 12345

It's possible to start a new task already limited to a given subset of CPU cores, i.e. by applying taskset to a PostgreSQL startup script: 
    
    
    taskset 0xC /etc/init.d/postgresql start

In our case, however, we had to deal with a production server and run taskset against the already running PostgreSQL processes. 

To restrict PostgreSQL to specific cores one has to set the affinity for each of the processes the server consists of. The order in which the processes are restricted is important: if we don't handle the postmaster first it may spawn new backend processes that won't get into the list of postgres PIDs and won't be affected by taskset. Normally, one can get the postmaster's PID by getting it from ps. On a system with no PID wraparound and a single PostgreSQL instance the postmaster process has the lowest PID among all of the PostgreSQL processes, so here's the one-liner to get it: 
    
    
    postmaster_pid=$(pidof postgres | xargs -n1 | sort | head -n1)

In our case we have limited PostgreSQL it to the total of 24 cores, from 8 to 31: 
    
    
    taskset -pc 8-31 $postmaster_pid

After the postmaster's affinity is set no new postgres backends can utilize cores outside of those the postmaster process was limited to. Next we can do the same for the existing backend and auxillary processes: 
    
    
    pidof postgres -o $postmaster_pid | xargs -n1 taskset -pc 8-31

Afterwards, one can verify (via top, vmstat or any other utility that shows utilization of individual CPU cores) that postgres processes only utilize those cores they were limited to. In our initial test (not to be performed on a production instance!) we launched a number of postgres backends running a simple infinite loop: 
    
    
    do $$ begin loop end loop;end;$$;

and checked via the top utility that the cores that postgres was not supposed to be using were idle. 

Finally, what about the initial hypothesis? Turns out that binding 8.2 to 24 cores didn't produce the expected load relief. Nevertheless, given that data the customer was able to alleviate the load spikes by making changes to the application, and we learned another tool that might be useful when debugging PostgreSQL on high-performance multi-core systems.

---
[View this page online](https://www.commandprompt.com/blog/binding_postgresql_server_to_specific_cpu_cores_in_linux/)

---

# Migrating hierarchical queries from Oracle to PostgreSQL

> This is the second part in a series of blog posts describing PostgreSQL analogs of common Oracle queries

One of the most intricate Oracle specific constructio…

This is the second part in a [series of blog posts](<http://www.commandprompt.com/blogs/alexey_klyukin/2012/03/>) describing PostgreSQL analogs of common Oracle queries

One of the most intricate Oracle specific constructions is "START WITH ... CONNECT BY". According to [Oracle's documentation](<http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm>), the syntax is: SELECT [query] [START WITH initial_condition] CONNECT BY [nocycle] condition. This statement is commonly used to traverse hierarchical data in the parent-child order. It's easier to illustrate how it works with an example.

Consider a table that stores opponents moves in a game of chess. Each table row contain coordinates (in [algebraic notation](<http://en.wikipedia.org/wiki/Algebraic_notation_\(chess\)>)) of a single move by whites and the move in response by blacks, as well as a column that references a preceding move, making it possible to keep multiple continuations of a specific move for the post-game analysis.
    
    
    CREATE TABLE moves(id integer, parent integer, white varchar(10), 
    black varchar(10));

The following statements describe 2 variants of a very short game, the first one leading to the early checkmate (known as a scholar's mate), and the second one to the position where black successfully avoids being checkmated.
    
    
    INSERT INTO moves VALUES(1, 0, 'e4', 'e5');
    INSERT INTO moves VALUES(2, 1, 'Qh5', 'Nc6');
    INSERT INTO moves VALUES(3, 2, 'Bc4', 'g6');
    INSERT INTO moves VALUES(4, 3, 'Qf3', 'Nf6'); -- checkmate is avoided
    INSERT INTO moves VALUES(5, 2, 'Bc4', 'Nf6');
    INSERT INTO moves VALUES(6, 5, 'Qxf7#', NULL); -- blacks being checkmated
    

Let's build an Oracle query showing a sequence of moves that leads to the checkmate:
    
    
    SELECT DISTINCT id AS final_move_id, 
    LTRIM(SYS_CONNECT_BY_PATH(NVL(white,'')||':'||NVL(black,''),';'),';')||';' 
    AS moves, LEVEL AS mate_in 
    FROM moves WHERE white LIKE '%#' OR black LIKE '%#' START WITH id = 1 
    CONNECT BY PRIOR id = parent;

FINAL_MOVE_ID  |  MOVES  |  MATE_IN   
---|---|---  
6  |  e4:e5;Qh5:Nc6;Bc4:Nf6;Qxf7#:;  |  4   
  
The query instructs Oracle to look for a checkmate:

  * The search starts at the move with id = 1, as indicated in the START WITH clause, and considers all possible continuations that lead to a checkmate, denoted by the final '#' in the move's description. 
  * Each move and its direct continuation, for instance, moves 2 and 5 represent the parent-child relationship, described by the PRIOR condition. 
  * The search depth is stored in the LEVEL pseudo-column. 



As a result, Oracle goes from one row to another only if the parent column of the new row contains the id of the current row, accumulating all visited rows in a result set. The SYS_CONNECT_BY_PATH clause produces a string out of the specified columns of the visited rows, connecting each (parent, child) pair by the designated character (';' in our case).

Being Oracle SQL extension, CONNECT BY is not available in PostgreSQL. Recent versions of PostgreSQL implement [Common Table Expressions (CTE)](<http://www.postgresql.org/docs/current/interactive/queries-with.html>), SQL-standard way of dealing with hierarchical data. Here's one possible rewrite of the query above for PostgreSQL using recursive CTEs: 
    
    
    WITH RECURSIVE search_moves(id, parent, white, black, level, path, checkmate)
    AS (
      SELECT id, parent, white, black, 1 AS level, 
      COALESCE(white,'')||':'||COALESCE(black,'')||';' AS path, 
      FALSE as checkmate FROM moves WHERE id = 1
    UNION ALL
      SELECT m.id, m.parent, m.white, m.black, sm.level + 1 AS level,
      sm.path||COALESCE(m.white,'')||':'||COALESCE(m.black,'')||';' AS path, 
      CASE WHEN m.white LIKE '%#' OR m.black LIKE '%#' THEN true ELSE false END 
      AS checkmate FROM moves m, search_moves sm WHERE m.parent = sm.id
    ) SELECT id AS final_move_id, path AS moves, level AS mate_in 
    FROM search_moves WHERE checkmate = true;
    

final_move_id | moves | mate_in  
---|---|---  
6 | e4:e5;Qh5:Nc6;Bc4:Nf6;Qxf7#:; | 4  
  
The SELECT statement above fetches rows produced by the recursive CTE, defined in the WITH RECURSIVE block. This block consists of 2 parts, separated by the UNION ALL clause:
    
    
    WITH RECURSIVE search_moves(id, parent, white, black, level, path, checkmate)
    AS (
      SELECT id, parent, white, black, 1 AS level, 
      COALESCE(white,'')||':'||COALESCE(black,'')||';' AS path, 
      FALSE AS checkmate FROM moves WHERE id = 1
    UNION ALL
      SELECT m.id, m.parent, m.white, m.black, sm.level + 1 AS level,    
      sm.path||COALESCE(m.white,'')||':'||COALESCE(m.black,'')||';' AS path, 
      CASE WHEN m.white LIKE '%#' OR m.black LIKE '%#' THEN true ELSE false END 
      AS checkmate FROM moves m, search_moves sm WHERE m.parent = sm.id
    )

Let's break it down into smaller fragments and examine them in more detail. The first one is the recursion base case, adding the first row to the result set:
    
    
    SELECT id, parent, white, black, 1 AS level, 
    COALESCE(white,'')||':'||COALESCE(black,'')||';' AS path, 
    FALSE AS checkmate FROM moves WHERE id = 1

This part is analogous to the START WITH clause in the Oracle statement above. The second part contains rules to return the whole result set out of the rows already added to it and those from the moves table that matches the WHERE condition:
    
    
    SELECT m.id, m.parent, m.white, m.black, sm.level + 1 AS level,
    sm.path||COALESCE(m.white,'')||':'||COALESCE(m.black,'')||';' AS path, 
    CASE WHEN m.white LIKE '%#' OR m.black LIKE '%#' THEN true ELSE false END
    AS checkmate FROM moves m, search_moves sm WHERE m.parent = sm.id
    

This condition is equivalent to the Oracle's PRIOR clause, choosing the new row to add to the result set: the row should be a direct child of another already added row.

In order to highlight the sequence of moves leading to a checkmate 'white' and 'black' attributes of rows added to the result set are concatenated into a string containing attributes from previously added rows, producing the output similar to Oracle's SYS_CONNECT_BY_PATH:
    
    
    sm.path||COALESCE(m.white,'')||':'||COALESCE(m.black,'')||';'

Note that there is no special LEVEL pseudo-column in PostgreSQL: instead, an arbitrary counter, named 'level' out of convenience, is incremented for each transition from parent to a child row.

Here's another example. Suppose we have a table describing bus routes, each row containing 2 consecutive stops and a route they belong to:
    
    
    CREATE TABLE segments(start_id integer, end_id integer, route_id integer);
    INSERT INTO segments VALUES(1,2,10);
    INSERT INTO segments VALUES(1,2,1);
    INSERT INTO segments VALUES(2,8,1);
    INSERT INTO segments VALUES(2,3,10);
    INSERT INTO segments VALUES(3,5,10);
    INSERT INTO segments VALUES(5,8,10);
    INSERT INTO segments VALUES(8,1,10);
    

It's possible to extract all bus stops in order belonging to a specific route using the technique described above. There is a caveat, though: by following the stops along the way sooner or later the algorithm reaches the starting point and, unless special precautions are taken, loops infinitely. One can prevent it (starting from Oracle 10g) by adding the NOCYCLE clause:
    
    
    SELECT * FROM (SELECT DISTINCT route_id, LEVEL, 
    SYS_CONNECT_BY_PATH(start_id, '/') "route" 
    FROM segments WHERE route_id = 10 START WITH start_id = 1 
    CONNECT BY NOCYCLE start_id = PRIOR end_id AND route_id = PRIOR route_id 
    ORDER BY level DESC) WHERE ROWNUM <= 1;
    

ROUTE_ID  |  LEVEL  |  route   
---|---|---  
10  |  5  |  /1/2/3/5/8   
  
Consider the analogous PostgreSQL query without the clause that detects cycles: 
    
    
    WITH RECURSIVE routes(route_id, level, route, start_id, end_id) AS (
      SELECT route_id, 1 AS level, '/'||start_id AS route, start_id, end_id 
      FROM segments WHERE start_id = 1
    UNION ALL
      SELECT cs.route_id, ps.level +1 AS level, ps.route||'/'||cs.start_id 
      AS route, cs.start_id, cs.end_id FROM segments cs, routes ps 
      WHERE cs.start_id = ps.end_id AND cs.route_id = ps.route_id
    ) SELECT route_id, level, route FROM routes 
      WHERE route_id = 10 ORDER BY level DESC LIMIT 1;
    

The query above works correctly if there are no cycles in the data hierarchy. For the segments table it loops until a user cancels it. Let's change it to handle cycles correctly:
    
    
    WITH RECURSIVE routes(route_id, level, route, cycle, start_id, end_id) AS (
      SELECT route_id, 1 AS level, array[start_id] AS route, false AS cycle, 
      start_id, end_id FROM segments WHERE start_id = 1
    UNION ALL
      SELECT cs.route_id, ps.level +1 as level, ps.route || cs.start_id as route, 
      cs.start_id = ANY(ps.route) as cycle, cs.start_id, cs.end_id 
      FROM segments cs, routes ps WHERE cs.start_id = ps.end_id AND 
      cs.route_id = ps.route_id AND cycle = false
    ) SELECT route_id, level, '/'||array_to_string(route,'/') AS route 
      FROM routes WHERE cycle = false AND route_id = 10 
      ORDER BY level DESC LIMIT 1;
    

route_id | level | route  
---|---|---  
10 | 5 | /1/2/3/5/8  
  
The difference between the last two queries is the addition of the array to store stops visited along the route:

  * Each new stop is compared to the contents of this array (using the ANY operator).
  * If the stop id is already present in the array, then a cycle is detected and subsequent searches along the corresponding route are stopped.
  * Otherwise, the stop is added to the array and the execution continues.



This actually works a bit differently from Oracle's CONNECT BY NOCYCLE (but similarly to the newer cycle detection code in Oracle 11g R2): we can only detect a cycle upon entering one and, as a result, the first row of a cycle is also saved by CTE and can be retrieved by lifting off the cycle = false restriction in the resulting SELECT.

Common Table Expressions are available in PostgreSQL 8.4 and above. For the earlier versions, there is [tablefunc](<http://www.postgresql.org/docs/8.3/interactive/tablefunc.html>) contrib module, containing the function that emulates most of the connect by functionality. While not as general as recursive CTEs, it nevertheless brings the power of hierarchical queries to earlier versions of PostgreSQL.

Latest version of Oracle Database (11g R2) includes SQL standard recursive CTEs, making possible to port CTE queries from 11g R2 to PostgreSQL with only minor changes. There are a couple of useful extensions implemented by Oracle, for instance, it's possible to do depth-first or breadth-first search and there exists a mechanism for cycle detection not yet implemented in PostgreSQL (which can be emulated as demonstrated in the examples). There are CTE extensions in PostgreSQL as well: version 9.1 introduced writable CTEs, allowing INSERTs, UPDATEs and DELETEs with RETURNING in the WITH blocks, making it possible to combine results of multiple DML queries and SELECTs in a single query.

Finally, despite the fact that this post is about Oracle to PostgreSQL conversion, I can't consider it complete without mentioning some interesting applications of recursive CTEs: there is an awesome library called [pgchess](<http://blog.2ndquadrant.com/en/2010/12/pgchess-code-published.html>) written by Gianni Ciolli that actually allows a user to play chess against the PostgreSQL database, Oracle and PostgreSQL queries to solve a [sudoku puzzle](<http://wiki.postgresql.org/wiki/Sudoku_puzzle>) and a number of other interesting examples one can find in the snippets section of the [PostgreSQL wiki](<http://wiki.postgresql.org>). Have fun and stay tuned for further posts!

---
[View this page online](https://www.commandprompt.com/blog/migrating_hierarchical_queries_from_oracle_to_postgresql/)

---

# Cool and Sexy: Open Source PostgreSQL enterprise contenders

> As with any healthy project, there will be offshoots and people will take the source, fork it and try to create something new, better, different or just.... Ho…

As with any healthy project, there will be offshoots and people will take the source, fork it and try to create something new, better, different or just.... How that person feels it should be. This is a good thing, it leads to new ideas, new communities and sometimes truly interesting pieces of software. 

Postgres-XC has been around for a while, it is primarily developed by NTT and EnterpriseDB. It has a small community but a dedicated engineering/hacker backing. Postgres-XC is interesting because it keeps reasonably up to date with the latest Postgres (1.0 is set to be based on 9.1 of PostgreSQL) but provides a shared nothing clustering architecture. This type of infrastructure is one of the holy grails of web based applications. 

Should Postgres-XC deliver on its promises (hint: it does), you will be able to scale out (as opposed to up which Postgres already does extremely well) at an almost 1 to 1 ratio. This means that instead of having to purchase 2 large machines at 10-12k a piece you could purchase 4 machines at 1.5k a piece and achieve similar performance (theoretically, I need to test this). It also means that scaling out in the "cloud" will be easier. 

I invite everyone interested in PostgreSQL to [take a look at Postgres-XC](<http://postgres-xc.sourceforge.net/>). It is going to 1.0 soon and it needs community members to help flesh out the warts that haven't been found yet. 

Another Postgres fork that has recently appeared is [tPostgres](<http://www.tpostgres.org/>). tPostgres (doesn't that look wrong at the beginning of a sentence?) is set to do to Microsoft SQL what EnterpriseDB did to Oracle, with one minor, small, interesting, exception: tPostgres is Open Source. Further Microsoft SQL is more in line with PostgreSQL in the types of workloads you usually see it performing. Imagine a tPostgres with Postgres-XC. Imagine an open source way to easily port Microsoft SQL apps to PostgreSQL. 

Now don't get me wrong, the latest versions of Microsoft SQL are actually good products. Yes, I did just say that. However, they are not Open Source, they are expensive (comparatively) and let's get real, we want everyone to run Postgres. 

Unfortunately tPostgres is only just announced and they are literally at the beginning of building their community but as it is being initiated by Denis Lussier (co-founder of EnterpriseDB), I imagine that he will come through with something very interesting indeed.

---
[View this page online](https://www.commandprompt.com/blog/cool_and_sexy_open_source_postgresql_enterprise_contenders/)

---

# PgNext: Cancelled

> It is with regret that I announce that PgNext is cancelled. I am not sure what is next for the PostgreSQL Conference series. The reasons are long and myriad an…

It is with regret that I announce that PgNext is cancelled. I am not sure what is next for the PostgreSQL Conference series. The reasons are long and myriad and I will not bore you with them. However I will present the following video:  
  


  
If you can't see the video, [here is the video link.](<https://vimeo.com/40607631>)

That video represents why I would put on the conferences. They were fun. We had a good time.

If you are looking for other Postgres conferences there are the following:

  * [PgCon](<http://www.pgcon.org/>)
  * [PostgresOpen](<http://www.postgresopen.org/>)
  * [PgConf.EU](<http://www.pgconf.eu>)



Personally, I would suggest staying local and attending or help organize a local PUG day for PostgreSQL. PUG days are the best in small conferences. You are meeting with many locals, quite a few contributors usually show up, and you get to go home at night. The content is always top notch and chances are you know many of the people there. There are many. We recently had them in NYC, DC/Maryland, and Austin. There is a Denver PgDay on the 26th of October (no website yet) as well.

---
[View this page online](https://www.commandprompt.com/blog/pgnext_cancelled/)

---

# Remembering our roots

> Once upon a time, JD was a assistant manager for Block Buster video. This was a very long time ago and before a 23 month employment stint at Powells Books. It …

Once upon a time, JD was a assistant manager for Block Buster video. This was a very long time ago and before a 23 month employment stint at [Powells Books](<http://www.powells.com/>). It was at Powells that the world of computers was actually introduced to me as a viable employment option. While there I designed a special order database in DBase IV, was introduced to University Ingres, went through Book Buyer training, became a Novell Netware Administrator, and began a side business selling pre-built computers and parts. I also pretended to go to college and generally just had zero clue about life. I still don't have much of a clue about life. 

Why does this matter? It doesn't really. I am just rambling because my sister asked me today something that surprised me, "What is UNIX?". I had to just kind of stare at the screen for a moment. Of course she asked me this as she was happily proclaiming that she received an iPhone for her birthday. How far we have come. 

I explained what UNIX was, the basic history, it's involvement in the Internet and it occurred to me that for me, there was one very specific point in life that my professional world went from, "huh.... give me my 7.50/hr" to, "Hey, I can actually become educated in something useful.". It was the mental [ absorption of this book](<http://www.amazon.com/A-Practical-Guide-Unix-System/dp/0805302433/ref=sr_1_1?s=books&ie=UTF8&qid=1334082419&sr=1-1>). 

That book, allowed me to learn Unix, which allowed me to learn Linux (back when SLS was king), which brought me to Postgres95, which brought me to PostgreSQL, which brought me to [co-writing this book,](<http://www.amazon.com/Practical-PostgreSQL-OReilly-Command-Prompt/dp/1565928466/ref=sr_1_1?s=books&ie=UTF8&qid=1334082600&sr=1-1>) which lead me to be a major contributor to PostgreSQL not only through my work with the Fundraising group (via [SPI](<http://www.spi-inc.org/>))but also [. I would also bring up the conferences but those are already mentioned today. 

While waxing nostalgia I am reminded of a [recent blog post by Bruce Momjian](<http://momjian.us/main/blogs/pgblog/2012.html#April_9_2012>) where he mentions, "Postgres adoption is probably five years behind Linux's adoption.". I would agree with him, and would add that a lot of it is directly contributed to our development model. Many in the community have argued for years that time based releases of PostgreSQL would help development, many others... have argued for years that this is a bad idea. Many of those opponents of time based releasing, and one very influential one at that (TGL) are now starting to come around. More on that later, I have work to do!

---
[View this page online](https://www.commandprompt.com/blog/remembering_our_roots/)

---

# PgNext (PostgreSQL Conference) CFP is still open

> As a reminder, the CFP for PgNext is still open. We are in Denver this year, let&#x27;s make it rock! This year we are keeping it simple and getting back to roots. …

As a reminder, [the CFP for PgNext](<https://www.postgresqlconference.org/>) is still open. We are in Denver this year, let's make it rock! This year we are keeping it simple and getting back to roots. The conference is about community, networking with professionals, learning and in general having a good time. Who can't have a good time in Denver?

---
[View this page online](https://www.commandprompt.com/blog/pgnext_postgresql_conference_cfp_is_still_open/)

---

# URI connection strings, PgNext CFP and other generalities (FKlocks)

> Our team has been hard at work on several things. One is the URI patch for libpq which was just committed and sponsored by Heroku (Thanks Heroku). This is a no…

Our team has been hard at work on several things. One is the URI patch for libpq which was just committed and sponsored by Heroku (Thanks Heroku). This is a novel patch that brings standard URI connection handling to libpq and any client/driver that decides to implement the functionality. [You can see the patch here.](<https://commitfest.postgresql.org/action/patch_view?id=720>)

We are still actively working on [PgNext: The Next PostgreSQL Conference](<https://www.postgresqlconference.org/>). The folks on the organizing team have been an invaluable resource at helping us determine the direction of the conference. We have also been receiving a lot of emails thanking us for the selection of Denver as the location, many of them from new attendees. [If you haven't submitted a talk yet, now is the time!](<https://www.postgresqlconference.org/>)

The FKLocks patch was unfortunately pushed to 9.3 due to some outstanding issues not the least of which was a performance regression under normal FK use. This is a large patch that team member Alvaro Herrera has been working on for a very long time. It is a patch that has the potential to greatly increase the performance of foreign keys. It has been a lesson in patience, evaluation of sponsored work (it was partially, and only partially sponsored), and resource allocation. Hopefully we can be done with this soon.

---
[View this page online](https://www.commandprompt.com/blog/uri_connection_strings_pgnext_cfp_and_other_generalities_fklocks/)

---

# Pearls of Oracle to PostgreSQL conversion

> 
We have been working on a large Oracle 8i conversion to PostgreSQL. Our customers were not concerned with the data conversion: there are tools like ora2pg an…

We have been working on a large Oracle 8i conversion to PostgreSQL. Our customers were not concerned with the data conversion: there are tools like [ora2pg](<http://ora2pg.darold.net/>) and [oracle foreign data wrapper](<http://keithf4.com/oracle_fdw>) to accomplish this. They do, however, have a significant number of queries that needs to be converted.

Apparently, most queries from Oracle and PostgreSQL look similar; after all, both are relational database systems, as opposed to Cassandra or MongoDB, seeking to adhere to the same standards. Unfortunately, Oracle is known for the non-standard syntax extensions that are widely used by DB developers. Fortunately, the PostgreSQL community went great lengths not only to rely on SQL standards, but to use them as a source for the new powerful features.

How do recent versions of PostgreSQL stack up against Oracle syntax extensions, you may ask. The answer is very well; in fact, there is hardly anything in Oracle 8i syntax that cannot be emulated by PostgreSQL. Let's consider a couple of examples, starting from the one of the most peculiar syntax construction Oracle is known for, outer joins:

Oracle versions before 9 used a non-standard syntax for left and right outer joins; support for full outer joins was missing altogether. Suppose we have a schema to track orders:
    
    
    CREATE TABLE users(id INTEGER, email VARCHAR2(200));
    CREATE TABLE products(id INTEGER, name VARCHAR2(200), price FLOAT(126));
    CREATE TABLE orders(id INTEGER, userid INTEGER, productid INTEGER, 
                        quantity INTEGER);
    

A typical LEFT JOIN, returning all users that haven't made any orders, looks like this:
    
    
    SELECT u.id FROM users u, orders o
    WHERE o.userid IS NULL AND u.id = o.userid (+);
    

Oracle's OUTER JOIN is represented by a special WHERE clause with a '+' sign added. The '+' denotes the nullable side of the join: we are looking for users that don't have any rows associated with their ids in the orders table. The PostgreSQL equivalent of this query will be a straightforward:
    
    
    SELECT u.id FROM users u LEFT JOIN orders.o ON (u.id = o.userid) 
    WHERE o.userid IS NULL;

Clearly, the rule is simple: if you see a '(+)' in the Oracle's WHERE clause - it's really an outer join; if a '+' sign is on the left side of the binary operator - it's a RIGHT JOIN and vice versa. 

Let's consider an Oracle construction that is a little more complex to emulate, Oracle's rownum column. This is a special pseudo-column that numbers rows returned by an Oracle query. For instance, to get positions of all products in the product list ordered by price, one can issue the following Oracle query:
    
    
    SELECT rownum as position, id, name, price 
    FROM (SELECT * FROM products ORDER BY price);
    

If 'products' stores data in no particular order, the rownum value would be different from the product id.

Unlike Oracle, PostgreSQL doesn't have a rownum column, so what would we do with the query above? Turns out, we can emulate it with the help of [window functions](<http://www.postgresql.org/docs/current/interactive/tutorial-window.html>), a feature available since PostgreSQL 8.4. These functions are capable of performing calculations over related group of rows called partitions. In our example, we need to apply the function called row_number() over the whole result set (denoted by the empty PARTITION BY clause), using ordering by price to compute the row number:
    
    
    SELECT row_number() OVER (ORDER BY price) as position, id, name, price 
    FROM products ORDER BY price;
    

Note that there is a subtle problem in the queries above. Different positions will be assigned to the items with equal price points. While there is no easy way to fix this in Oracle 8i, we can assign equal positions to the items with no price differences by switching the window function from row_number() to rank() in the PostgreSQL case: 
    
    
    SELECT rank() OVER (ORDER BY price) as position, id, name, price 
    FROM products ORDER BY price
    

There is another common use case of Oracle's rownum column, to limit the number of rows returned from a query like this (used to extract the 5 most expensive products): 
    
    
    SELECT * FROM (SELECT * from products ORDER BY price DESC) WHERE rownum <= 5;
    

We need neither window functions, nor subqueries in the PostgreSQL equivalent of this query: 
    
    
    SELECT * FROM products ORDER BY price DESC LIMIT 5;	
    

Easy, right? 

You are probably wondering why am I comparing the recent versions of PostgreSQL to Oracle 8i, being almost 15 years old now? The reason is, there are a number of customers still running such an old products not ready to shell out hundreds of thousands for an upgrade to a new Oracle major version. PostgreSQL might be the best and cost-effective way to get their data to a modern relational database system and, of course, upgrades to new major versions are free (and can be performed in-place with [pg_upgrade](<http://www.postgresql.org/docs/current/interactive/pgupgrade.html>)).

There are more examples I'd like to demonstrate (including the conversion of Oracle's CONNECT BY clause), but this post is already getting too long, so I'm wrapping up for now. Stay tuned for further posts!

---
[View this page online](https://www.commandprompt.com/blog/pearls_of_oracle_to_postgresql_conversion/)

---

# Another day, another recovery

> This is something I have seen many times now: a customer calls us because they
lost some data and they want help recovering.

Now you must be wondering: sur…

This is something I have seen many times now: a customer calls us because they lost some data and they want help recovering.

Now you must be wondering: surely if they lost data they can just recover from their last backup, right? Right -- they had that. However we know that pg_dump takes a while to run and is stressful on the server, so it's normally run just once a day or so. What happens if you've been running almost a full work day since your last backup? It's a lot of data to lose.

And in turn you must be wondering: surely they can easily run a standby server with some form of WAL replication (streaming or continuous archive recovery) that gets the data from the master in a more timely fashion. Yes, they had that too. Or at least, they thought they had ... and this is where things start to look awry.

So why, you continue to wonder, did they think they had a working replica, when in fact they didn't? That's easy to answer: they had proper monitoring in place. At least, they thought it was proper; in fact, it wasn't, because the monitoring script contained some sort of error and it was not working at all. It reported that the replica was working, when it was not.

Reality was that their replica had broken fourty five days earlier and they hadn't noticed. Yes, really, 45 days.

But the master was still happily working all that time, and they had no problems at all ... except that their disk was slowly filling up. They had this little cleanup script that removed xlog segments that were older than 30 days. This script was run by cron regularly.

Now you have to understand that this is a pretty efficient script. You tell it to free space, and it frees a lot of space. So they run it manually, and it freed space; so much space it freed, in fact, that the database stopped working and it wouldn't start. Not precisely the most comforting of situations, regardless of the amount of free space you now have.

It turns out that instead of running it on the xlog archive dir, they had ran it on the Postgres base directory.

To recapitulate, by now I'm counting five mistakes: 

  1. Broken replica monitoring that wrongly returns that a broken replica is in good health
  2. Breaking of a replica server
  3. Ill-conceived xlog archival design that consumes arbitrary space on the master
  4. A data removal script that does not carefully filter files to delete
  5. A DBA running said script under duress, who is likely to make a mistake, makes that mistake



And that's where we, [Command Prompt Inc.](<http://www.commandprompt.com/>), enter the picture.

If you're a Postgres hacker familiar with the underlying storage layout, recovering from this type of breakage is relatively easy. If you're a user, it's impossible. They're lucky that they had that 45-days-old replica. Without that, it would have been a lot harder (it's possible to reconstruct enough catalog state by hand to let you pg_dump such a table. It's a lot more laborious, however.) What I did was copy enough files corresponding to the heap of system catalogs from the replica into the master, until a standalone backend was able to start and run a REINDEX SYSTEM. I couldn't just copy all files, because that would have overwritten catalogs that had been touched sometime in the last 30 days, which I didn't want. Fortunately there was nothing in the intervening 15 day interval after the slave broke and before the 30 day file deletion limit.

When that was done, it was possible to start up postmaster and examine status of tables. This caused some more errors, this time related to missing pg_clog files, and one related to a short pg_multixact file. I managed those by copying pg_clog files from the slave (I had to extend one using `dd` because some blocks weren't present in the slave either), and creating a dummy pg_multixact file. To extend the pg_clog file, which was the one piece of guessing I did, I examined the other pg_clog files to see how likely transaction aborts were compared to transaction commits. Commits were twenty times more frequent than aborts, so I decided to simply fill the missing pages with the 0x55 pattern, which corresponds to "all transactions committed."

With this, some tables would raise errors about missing underlying files when queried. Other tables would work fine. The next step was obvious: produce one dump for each table, discard those that failed, keep the good ones. The theory of operation was that older files, those that were erased by the script, corresponded to tables that had not been touched in a long time. So they could be recovered from the nightly pg_dump without loss of data. All other tables had recent activity, and so the new dumps would take precedence over the nightly dump.

(This would have failed if tables had more than one segment, and some segment had been deleted while others had been kept. I examined table data from pg_class and concluded that this hadn't happened.) 

From there it's easy to proceed: just restore selectively from either the nightly dump, or from the separate dump I provided. This is tedious but relatively easy, and they took over at this point. They were happy to tell me, the next day, that they had gotten all data back. (If you attempt this at home, make sure you pg_dump the resulting database and then restore that. By doing this, you ensure that the system catalogs are consistent, and that the data you restore passes all the declared constraints. I hope they did not skip this step.)

I guess there must be a lesson for them somewhere in this whole episode. I have left those for them to learn. The lesson I learned was this: we need a utility that helps us dump the `pg_filenode.map` file.

---
[View this page online](https://www.commandprompt.com/blog/another_day_another_recovery/)

---

# Decoding infomasks

> Come on, admit it: you&#x27;ve always wanted to display the infomask bits from a tuple header in a human-readable manner, but you&#x27;ve never gotten around to it and y…

Come on, admit it: you've always wanted to display the infomask bits from a tuple header in a human-readable manner, but you've never gotten around to it and you still keep htup.h in display while you peek around tuples.

Fortunately, that time is now past! Here's a short and simple recipe to decode the bits for your reading pleasure. Gone is the htup.h cheat sheet. Here's what you need:
    
    
    create type infomask_bit_desc as (mask varbit, symbol text);
    
    create or replace function infomask(msk int, which int) returns text
    language plpgsql as $$
    declare
            r infomask_bit_desc;
            str text = '';
            append_bar bool = false;
    begin
            for r in select * from infomask_bits(which) loop
                    if (msk::bit(16) & r.mask)::int <> 0 then
                            if append_bar then
                                    str = str || '|';
                            end if;
                            append_bar = true;
                            str = str || r.symbol;
                    end if;
            end loop;
            return str;
    end;
    $$ ;
    
    create or replace function infomask_bits(which int)
    returns setof infomask_bit_desc
    language plpgsql as $$
    begin
            if which = 1 then
                    return query values
                    (x'8000'::varbit, 'MOVED_IN'),
                    (x'4000', 'MOVED_OFF'),
                    (x'2000', 'UPDATED'),
                    (x'1000', 'XMAX_IS_MULTI'),
                    (x'0800', 'XMAX_INVALID'),
                    (x'0400', 'XMAX_COMMITTED'),
                    (x'0200', 'XMIN_INVALID'),
                    (x'0100', 'XMIN_COMMITTED'),
                    (x'0080', 'XMAX_LOCK_ONLY'),
                    (x'0040', 'EXCL_LOCK'),
                    (x'0020', 'COMBOCID'),
                    (x'0010', 'XMAX_KEYSHR_LOCK'),
                    (x'0008', 'HASOID'),
                    (x'0004', 'HASEXTERNAL'),
                    (x'0002', 'HASVARWIDTH'),
                    (x'0001', 'HASNULL');
            elsif which = 2 then
                    return query values
                    (x'2000'::varbit, 'UPDATE_KEY_REVOKED'),
                    (x'4000', 'HOT_UPDATED'),
                    (x'8000', 'HEAP_ONLY_TUPLE');
            end if;
    end;
    $$;
    

You can now use it like this: 
    
    
    alvherre=# select lp, t_xmin, t_xmax, t_ctid,
           infomask(t_infomask, 1) as infomask,
           infomask(t_infomask2, 2) as infomask2
    from heap_page_items(get_raw_page('foo', 0));
    

lp | t_xmin | t_xmax | t_ctid | infomask | infomask2  
---|---|---|---|---|---  
1 | 702 | 2 | (0,2) | `XMAX_IS_MULTI|XMAX_COMMITTED|XMIN_COMMITTED|XMAX_KEYSHR_LOCK` | `UPDATE_KEY_INTACT|HOT_UPDATED`  
2 | 704 | 704 | (0,3) | `UPDATED|XMAX_COMMITTED|XMIN_COMMITTED|COMBOCID` | `UPDATE_KEY_INTACT|HOT_UPDATED|HEAP_ONLY_TUPLE`  
3 | 704 | 0 | (0,3) | `UPDATED|XMAX_INVALID|XMIN_COMMITTED` | `HEAP_ONLY_TUPLE`  
  
Okay, I cheated -- there are bits here that are not part of stock Postgres, but are part of my keylocks patch. It's trivial to edit them out (just make sure you remember to change `HEAP_IS_NOT_UPDATE` to `HEAP_SHARE_LOCK`).

---
[View this page online](https://www.commandprompt.com/blog/decoding_infomasks/)

---

# What's next for Postgresql conference?

> West is wrapped up. It was smaller. We split the attendees between Postgres Open and Surge. It was a good conference. We received a lot of positive feedback an…

West is wrapped up. It was smaller. We split the attendees between [Postgres Open](<http://www.postgresopen.org/>) and [Surge](<http://www.omniti.com/surge>). It was a good conference. We received a lot of positive feedback and I was even able to be nice (stop laughing, just ask others :P) to people for the conference. 

We were able to fund two features for PostgreSQL, both of which will hopefully hit for 9.2. The first is work to be done by Greg Smith with pg_stat_statement. The other was fully funded by [Heroku](<http://www.heroku.com/>) which is standardized URI support for libpq and psql. It is my hope that we will continue to use PostgreSQL Conference to actively fund features. 

That said, there are changes in the wind. First, PostgreSQL Conference is changing from a semi-annual conference to an annual conference. There is just no way the community can support four north american conference (PgWest, PgEast, PgCon, Postgres Open). What is unknown at this point is whether or not PgWest and PgEast will continue, or if we will just merge them and have PostgreSQL Conference. What is known is that the next conference will not be on the East coast. We are currently negotiating with Denver, Seattle, and San Jose (for a repeat). 

So what else is new? Generally speaking, the PostgreSQL conference is operated by a small team within CMD with a few select community members and partners picking up some stray pieces. That has changed this time around. We have an organization and planning committee of 26, all of whom are community members and attendees and/or speakers of the conference. These folks have been an invaluable input to the conference, allowing us to learn from the people that are actually giving us the money to pull this conference off. 

Stay tuned for more information in the next couple of weeks on various decisions in regards to the conference!

---
[View this page online](https://www.commandprompt.com/blog/whats_next_for_postgresql_conference/)

---

# PgWest 2011: Only a week away

> PgWest is only a week a way folks, let&#x27;s get those registrations in!

PgWest is only a week a way folks, let's get those [registrations](<https://www.postgresqlconference.org/register>) in!

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2011_only_a_week_away/)

---

# PgWest 2011: The Schedule is out!

> This year we have a diverse range of topics on PostgreSQL. Of course we have all the standard topics on backups, performance, mvcc but we also have some very i…

This year we have a diverse range of topics on PostgreSQL. Of course we have all the standard topics on backups, performance, mvcc but we also have some very interesting presentations coming from VMWare, Fusion-IO and Translattice. 

  * [You can find the schedule here.](<http://pgwest2011.sched.org/>)
  * [Registration is open and is available here.](<https://www.postgresqlconference.org/register >)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2011_the_schedule_is_out/)

---

# PgWest 2011: Trainings filling up fast

> As we all know, PgWest is in San Jose this year in just under 3 weeks. The trainings are filling up fast and you will want to get your registrations in. We hav…

As we all know, PgWest is in San Jose this year in just under 3 weeks. The trainings are filling up fast and you will want to get your registrations in. We have great trainings on: 

  * Performance 
  * High Availability 
  * Administration 
  * Ruby on Rails (with PostgreSQL focus) 
  * Normalization 
  * DRBD 

These are filling up fast, so you will want to get your [registration in.](<https://www.postgresqlconference.org/register>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2011_trainings_filling_up_fast/)

---

# PgWest 2011: Initial list of talks is up

> We have another stellar year of content at PostgreSQL Conference West. The first round of talks has been reviewed and they are now published. There are some mo…

We have another stellar year of content at PostgreSQL Conference West. The first round of talks has been reviewed and they [are now published.](<https://www.postgresqlconference.org/2011/west/talks>) There are some more talks on the way so stay tuned for the second round. We have also [opened early registration](<https://www.postgresqlconference.org/register>), although we don't have the training options up yet. Take a look and watch for more official announcement style stuff soon. 

Of note, Jim Mlodgenski maintainer of Stado (a proper, stable fork of GridSQL) will be teaching a Practical PostgreSQL Administration course. This is a full day course. Jim has graciously agreed to allow his percentage of the training revenue to be used for the feature development community initiative.

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2011_initial_list_of_talks_is_up/)

---

# PostgreSQL at DEFCON 19

> A while ago a gentlemen by the name of Josh (Abstrct) McDougall contacted me about a game he created and subsequent contest being held at DEFCON 19. What makes…

A while ago a gentlemen by the name of Josh (Abstrct) McDougall contacted me about a game he created and subsequent contest being held at DEFCON 19. What makes this so interesting is the majority of the game was created in PostgreSQL. This truly exposed the power of PostgreSQL and the ability to create business (or data) logic directly within the database instead of just using the database as a file system. Josh was looking for a small prize to be able to give the winner of this contest and of course Command Prompt and [The PostgreSQL Conference](<http://www.postgresqlconference.org/>) was happy to help out. 

I received (reprinted with permission) this email from him today: 

> Hi Josh, I am excited to say that the Schemaverse contest at DEFCON 19 went great! By the end of the tournament we had 108 registered players and over a million queries ran against the game in a four day span. Not only did the server do great as far as performance goes but the fact that it wasn't exploited during DEFCON is also an impressive stat to note. 
> 
> I can also proudly tell you that your contribution was mentioned during my own two presentations, found in our How To guide, discussed at our contest booth (right by the front doors to the high traffic contest area! :D) AND was announced during the DEFCON 19 closing ceremonies during my allotted 2 minutes of speaking time. 
> 
> The winner of your prize is Ian Haken (xxxx@xxxxxx.com). He kicked some butt in the competition and is certainly deserving of it. He has authorized me to send you his name and email. If you need any further details you can talk to him directly. 
> 
> I likely sound like a broken record at this point but I really do need to say thanks again. Your contribution definitely helped us generate some interest in the first year of our competition and has helped us gain the respect needed to return with the contest for years to come. 
> 
> Best Regards, Josh (Abstrct) McDougall [http://schemaverse.com/](<http://schemaverse.com>)

It was an honor to sponsor this contest. It is great little things like this that truly show the power of PostgreSQL in places you least expect. 

Just a note, although the CFP is technically closed we have not closed the submission form, [if you wanted to sneak in a talk or two you are welcome to.](<https://www.postgresqlconference.org/talk_types>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_at_defcon_19/)

---

# Fixing foreign key deadlocks, part three

> As I have posted in previous articles (
Fixing foreign key deadlocks and
Part 2),
I am working on reducing the lock
strength required by foreign key checks…

As I have posted in previous articles ( [Fixing foreign key deadlocks](<http://www.commandprompt.com/blogs/alvaro_herrera/2010/11/fixing_foreign_key_deadlocks/>) and [Part 2](<http://www.commandprompt.com/blogs/alvaro_herrera/2010/11/fixing_foreign_key_deadlocks_part_2/>)), I am working on reducing the lock strength required by foreign key checks. I have [a working patch](<http://archives.postgresql.org/message-id/1311807810-sup-1055@alvh.no-ip.org>) that solves a lot of the problems already; however it doesn't solve the one problem that I initially set to fix. It turned out to require a bit more rejiggering than I initially considered.

Note: this article assumes that you know what I have already done in the patch I posted. If you want to follow through, I suggest you read the first two links above as an introduction.

## The problem

The patch I proposed removed some of the reasons that create hangs on concurrent transactions, but certain deadlocking patterns remain. Let's examine why this is so. The current isolation test framework has a test (shown below) which mirrors [Joel Jacobson's test case](<http://www.commandprompt.com/blogs/alvaro_herrera/2010/11/fixing_foreign_key_deadlocks/>). This easily illustrates the cases unfixed with the patch I presented.
    
    
     
    setup
    {
      CREATE TABLE A (
            AID integer not null,
            Col1 integer,
            PRIMARY KEY (AID)
      );
     
      CREATE TABLE B (
            BID integer not null,
            AID integer not null,
            Col2 integer,
            PRIMARY KEY (BID),
            FOREIGN KEY (AID) REFERENCES A(AID)
      );
     
      INSERT INTO A (AID) VALUES (1);
      INSERT INTO B (BID,AID) VALUES (2,1);
    }
     
    teardown
    {
      DROP TABLE a, b;
    }
     
    session "s1"
    setup           { BEGIN; SET deadlock_timeout = '100ms'; }
    step " **s1u1** "     { UPDATE A SET Col1 = 1 WHERE AID = 1; }
    step " **s1u2** "     { UPDATE B SET Col2 = 1 WHERE BID = 2; }
    step "s1c"      { COMMIT; }
     
    session "s2"
    setup           { BEGIN; SET deadlock_timeout = '10s'; }
    step " **s2u1** "     { UPDATE B SET Col2 = 1 WHERE BID = 2; }
    step " **s2u2** "     { UPDATE B SET Col2 = 1 WHERE BID = 2; }
    step "s2c"      { COMMIT; }
    

The way these tests work is by trying all possible ways of intermixing the commands of the two sessions. One of the permutations that dies due to a deadlock even with the patched code is below. The first line lists the steps taken by the two sessions, in the order in which they are executed. 
    
    
     
    starting permutation: s1u1 s2u1 s1u2 s2u2 s1c s2c
    step s1u1:  UPDATE A SET Col1 = 1 WHERE AID = 1; 
    step s2u1:  UPDATE B SET Col2 = 1 WHERE BID = 2; 
    step s1u2:  UPDATE B SET Col2 = 1 WHERE BID = 2;  <waiting ...>
    step s2u2:  UPDATE B SET Col2 = 1 WHERE BID = 2; 
    step s1u2: <... completed>
    ERROR:  deadlock detected
    step s1c:  COMMIT; 
    step s2c:  COMMIT; 
    

The locks taken by the code patched by me are: 
    
    
     
    s1u1: exclusive lock on table A
    s2u1: exclusive lock on table B,
          KEY LOCK on table A (blocks due to the lock taken by s1u1)
    s1u2: exclusive lock on table B (blocks due to lock taken in s2u1); 
          deadlock detected
    s2u2: exclusive lock on table B, KEY LOCK on table A.
    

It's easy to see that it still deadlocks: when session 2 goes to acquire the `KEY LOCK` in the tuple in table A (step `s2u1`), it blocks because of the previous `UPDATE`. So with my new code, you can `UPDATE` a tuple with a `KEY LOCK` in it (which you cannot with the current code), but you can't `KEY LOCK` a tuple that's under `UPDATE`. This asymmetry is pretty weird, but it does makes some sense: if the `UPDATE` were to touch the indexed fields, you are screwed, whereas the `KEY LOCK` already knows whether the `UPDATE` touched indexed fields or not.

## The solution

In discussion, [Noah Misch came up with the following idea](<http://archives.postgresql.org/message-id/20110211071322.GB26971@tornado.leadboat.com>): create a new lock mode for tuples, `FOR KEY UPDATE`. With this new lock mode, along with `KEY SHARE` which replaces the lone new mode my patch proposes (`KEY LOCK`), the lock conflict table for tuples would look like this:

  1. `FOR KEY SHARE` conflicts with `FOR KEY UPDATE`
  2. `FOR SHARE` conflicts with `FOR KEY UPDATE`, `FOR UPDATE`
  3. `FOR UPDATE` conflicts with `FOR KEY UPDATE`, `FOR UPDATE`, `FOR SHARE`
  4. `FOR KEY UPDATE` conflicts with `FOR KEY UPDATE`, `FOR UPDATE`, `FOR SHARE`, `FOR KEY SHARE`



In this conflict table, most things work as you would expect. `FOR UPDATE` is the lock mode acquired by `SELECT FOR UPDATE`; similarly with `FOR SHARE`. `KEY SHARE` would be the lock mode acquired by the foreign key code: the lightest lock available. The new mode `KEY UPDATE` mode would be acquired by `UPDATE` and `DELETE`:

  1. `DELETE` always takes `FOR KEY UPDATE` lock on the tuple being deleted (so it behaves as currently: everyone else is blocked until the delete is completed)
  2. `UPDATE` takes `FOR KEY UPDATE` lock if at least one column being updated is unique-indexed; `FOR UPDATE` lock if not.



## Why does this solve the problem?

With the new proposal, the sequence of locks acquired by the example above would look like this:
    
    
     
    s1u1: FOR UPDATE in table A
    s2u1: FOR UPDATE in table B,
          FOR KEY SHARE in table A
    s1u2: FOR UPDATE in table B (blocks),
          FOR KEY SHARE in table A
    s2u2: FOR UPDATE in table B (supposedly does not block because we already have it),
          FOR KEY SHARE in table A
    

So s2 completes, and then s1 is unblocked and commits.

With Noah's proposal, things get more symmetrical. This problem would be fixed by letting the `KEY SHARE` lock be acquired even while `UPDATE` is touching the tuple -- assuming that the `UPDATE` is not touching anything indexed by an unique index. Obviously, if the `UPDATE` were to try to update the AID column (the primary key), all bets would be off -- there would be a deadlock. Supposedly, that's OK; there's nothing we can do about it, anyway.

Note that the `FOR KEY UPDATE` lock doesn't need to be exposed at the SQL level, because it is taken internally by `DELETE` and `UPDATE`. Only the new mode `FOR KEY SHARE` would be exposed, because it needs to be used by the RI trigger via the SPI interface. (If there was another way to send "row marks" down, we could avoid exposing yet another nonstandard lock mode clause.)

## The catch

The "small" problem with this idea is that a tuple might now be locked by multiple transactions in more than one of three modes, `FOR KEY SHARE`, `FOR SHARE` and `FOR UPDATE`. This presents a representational problem: how do we know which transaction holds which lock mode? There's certainly not room in the tuple header for all this info, so we need to be looking elsewhere.

To fix this, we would need to store more info about the locking MultiXact; in addition to the comprising Xids, we would need to store the locktype for each, two bits per member transaction (say `00 = FOR KEY SHARE`, `01 = FOR SHARE`, `10 = FOR UPDATE`). This requires some thought: we could expand the current pg_multixact SLRU areas to give room for the extra info; I think this would foreclose the possibility of us using MultiXacts for other purposes (We don't currently use them for anything other than locking tuples, but who knows). The other possibility would be storing those bits in new SLRU areas but that seems pretty painful.

## Let's fix another problem in passing, too

This proposal also shows promise in fixing the problem with row locks being lost on aborted subtransactions; see the first Caution frame in the [ SELECT reference](<http://www.postgresql.org/docs/current/static/sql-select.html>) documentation:

**Caution**  
---  
  
Avoid locking a row and then modifying it within a later savepoint or PL/pgSQL exception block. A subsequent rollback would cause the lock to be lost. For example:
    
    
     
    BEGIN;
    SELECT * FROM mytable WHERE key = 1 FOR UPDATE;
    SAVEPOINT s;
    UPDATE mytable SET ... WHERE key = 1;
    ROLLBACK TO s;
    

After the ROLLBACK, the row is effectively unlocked, rather than returned to its pre-savepoint state of being locked but not modified. [...]   
  
Basically, the problem there is that the tuple locks are forgotten when a subtransaction updates a tuple; if the subtransaction aborts, the locks are not un-forgotten, because the field in the tuple header (Xmax in the original tuple) that keeps track of it has been overwritten with the Xid of the updating transaction.

What we could do is create a MultiXact when this is detected: an updater doesn't just stash its own Xid in the Xmax field, but instead it creates a new MultiXact with itself and whatever was previously in the Xmax. In order to do this, we would need to use the fourth bit pattern to represent those that grab `KEY UPDATE` on the tuple. While obviously no one could be interested in touching that tuple again, remembering the previous state would be useful in case the updating subtransaction aborted.

## Conclusion

I will be working to find the best way to implement this. The changes I describe require patching stuff in a lot more places than I initially intended. It seems to me that we would end up with a much better, more concurrent implementation if we follow this path. Stay tuned.

---
[View this page online](https://www.commandprompt.com/blog/fixing_foreign_key_deadlocks_part_three/)

---

# CFP for West extended

> PostgreSQL Conference West 2011 has extended it&#x27;s call for papers by 12 days. The new schedule is below:


May 25th: Talk submission opens
August 12th: Tal…

PostgreSQL Conference West 2011 has extended it's call for papers by 12 days. The new schedule is below: 
    
    
    May 25th: Talk submission opens
    August 12th: Talk submission closes (EXTENDED!)
    August 16th: Speaker notification
    

The Conference, the largest direct financial contributor to the PostgreSQL community but money isn't always what the community needs. One of the things our community needs is a way to create a stable financial environment for developers to receive compensation for development they are performing. 

Help us continue to provide the overwhelming support to the PostgreSQL Community we always have. Submit your talk today! 

[Submit Talks](<https://www.postgresqlconference.org/talk_types>)

---
[View this page online](https://www.commandprompt.com/blog/cfp_for_west_extended/)

---

# Learning from mistakes, taking new directions, observations

> Alright, so they aren&#x27;t really new directions. Command Prompt has been submitting features to .Org for a long time, we have also been a large generator of cont…

Alright, so they aren't really new directions. Command Prompt has been submitting features to .Org for a long time, we have also been a large generator of content through activity on the mailing lists, the publicly available (if outdated) Practical PostgreSQL and not to mention all the content we provide through the PostgreSQL Conference site. However, with all of these things it is easy to get lost in the mire and slowly forget doing what you are good at. 

As a team I would like to think that CMD is really good at serving the community, serving its customers, and taking care of each other. However, when you reach out of your expertise and try something new it can fail and come back to bite you. CMD for the last two years tried that, we changed our model. We started listening to companies that have a different model than we did. We felt that we could learn from their success and possibly have some better fortunes of our own. What we learned was that although there was some good information to be had (and we have used that information), the model that was being dictated to us was not the model that would allow CMD to be more successful. We also learned that their model, wasn't nearly as successful as they lead people to believe. 

One of the things that I love about the .Org business community is that we look out for each other. 2ndQuadrant, Consistent State, PgExperts, Credativ, OmniTI, and CMD (and a host of others, no offense guys). We actively seek ways to work with each other when we can, we lead exchange, we send people to other companies we know are good companies if we can't help a customer, we don't swipe customers (purposely, sometimes things happen) . There is a certain, comfortable quid pro quo. No matter the differences that Josh Berkus, Simon Riggs, Robert Treat, Kevin Kempter or and I may have on list, it is purely professional and at any point we will get together and have beer when we are at a conference or other event. We all have similar goals and they are, grow PostgreSQL, grow our companies and take care of our families (probably not in that order). 

Although CMD never stopped working with these community partners, we did lose focus through trying to become a more dominant player. It is natural to see opportunity and be slightly blinded by it. To have someone hold out their hand and say, "We know a better way, wink, wink", and think, "Hey maybe they do, let's see where this goes.". In our case, we found the way wasn't better and the way was really smoke and mirrors. This could very well be our fault. Frankly, we were blinded by opportunity that never arose and like many others in this community I am as stubborn as a mule. I just refused to adjust pace before now. 

I am strong in my convictions and I have beliefs in the way business should be done. CMD is going back to that. Those beliefs are founded on well over a decade of running this company in a manner that has assured that no team member has ever missed a paycheck including myself, that our debt has always been minimal if at all and that our communications with customers are upfront, honest and to the point. In case you hadn't noticed, we also don't employ sales teams. 

So what does all this really mean? Well for one, CMD has introduced the Google Policy. This means that every technical person in the company can spend 20% of their time on community work and sometimes that will be more. In the case of Alvaro, we have successfully received sponsorship for the rest of the Foreign Key Locks patch and he is currently spending more than 20% time on community work for example. If all goes well, we will continue to be sponsored to write features, modules and other PostgreSQL based software. We have been sponsored to do quite a bit of it lately. 

It also means that we will be attempting to reinvigorate our cross community relationships, although most of our relationships are solid I feel that not all of them have flourished the way they should. I would like to see those relationships stronger so we can continue to move .Org forward. With stronger relationships in the commercial satisfies the pre-requisite for future growth of the software community. Companies need to know they have someone to call, someone that will treat them right, someone they can trust to implement whatever it is they need with PostgreSQL. If those relationships are strong, any one of us can make sure we get those needs served, either by doing the work ourselves or handing it off to a more suitable candidate. 

In short it means, more patches, more patch review, more sponsored work and hopefully more intermingling of like interests between PostgreSQL companies. That is one of the goals behind [PostgreSQL Conference West](<http://www.postgresqlconference.org/>) raising funds for feature development. We want to continue to have PgWest (and PgEast) be a central place where community and commercial can get together and celebrate the common goals of PostgreSQL.

---
[View this page online](https://www.commandprompt.com/blog/learning_from_mistakes_taking_new_directions_observations/)

---

# PostgreSQL Conference West to sponsor PostgreSQL feature development

> As the primary organizer of The PostgreSQL Conference series, Command Prompt has been trying to find ways to continue to support the PostgreSQL Community. The …

As the primary organizer of [The PostgreSQL Conference series](<http://www.postgresqlconference.org/>), Command Prompt has been trying to find ways to continue to support the PostgreSQL Community. The Conference is already the highest direct financial contributor but the money isn't always what the community needs. The documentation may need some work (pg_dump section I am looking at you), we might want server to execute performance testing or there are features that the community wants developed. 

A recurring question in our community is, "How do I get feature X sponsored?". It is a frustrating question because there are many variables that are at play anytime you do development within an Open Source project. Just because you can develop the feature doesn't mean that the community actually wants the feature. There is also the problem of raising money for a feature, a lot of very skilled hackers do not have the contacts or frankly person skills to "sell" their idea. Once you have the money even more problems arise, what if you underbid the project? What if you can't get everyone to pay that said they would? What if you miss a commit deadline and you have to wait for the next release to start development? The list goes on and on. 

The traditional method of getting a feature developed would be to contact a company to do so. There are many people and companies that are used to working in the community, who know how to navigate the shark infested waters and are actively willing to work with you to get whatever feature done. Two of the most well known companies that do this are Command Prompt (duh moment), and 2ndQuadrant. We both have had much of the feature development we do for PostgreSQL sponsored by our customers (some of them, mutual customers). If you have a feature that you wish to get developed I highly recommend contacting one of us. 

The traditional method can be too much for a single entity to bare. If you have a feature that is 15,000 USD to develop, that just might be out of the budget of the sponsoring company and it is certainly out of the budget of most individuals. In some communities there is a bounty system where multiple entities can chose to donate to get a bug squashed or a feature developed. Unfortunately, bounties can go on forever and very little money is normally raised. So what do you do? 

The PostgreSQL Conference organizers team had an idea. What if, we take one of the resources we are rich in and use that resource in a manner that allows the community as a whole to benefit. What is this resource you might ask? Well people of course. Every 6 months the PostgreSQL Conference pulls more people into a single room than any other PostgreSQL event. What if the PostgreSQL Conference worked out a way to get those people to part with their hard earned dollars to get a feature developed? Imagine, one night instead of pub crawling if we put that 50.00, 100.00 or 250.00 to work for the betterment of PostgreSQL? 

If every person that attended #PgEast gave 100.00 to feature development, we would have raised $23,000 dollars. That would have more than paid for the ALTER TABLE ALTER COLUMN work that Command Prompt would like to develop. So that is what we are going to do at #PgWest. This year at #PgWest there will be up to 5 proposals on the table to sponsor. Only one will be from Command Prompt, we would like the others to be from other developers and companies are welcome to submit as well. Further, #PgWest will also be donating a portion of the registration fees to get these features developed. 

Stay tuned for how to submit your proposals. 

[PostgreSQL Conference West Call for Papers](<https://www.postgresqlconference.org/talk_types>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_west_to_sponsor_postgresql_feature_development/)

---

# Netflix should tell 6,000 users to please cancel their accounts

> Today, Netflix upped its rates. It was not an excessive increase (dollar wise) but it was enough to get some masses frothing at the mouth [1]. Here is the deal…

Today, Netflix upped its rates. It was not an excessive increase (dollar wise) but it was enough to get some masses frothing at the mouth [1]. Here is the deal folks, Netflix is cheap, really cheap. It is so cheap that their selection is dwindling as their contracts become due. To get even close to the equivalent service from a cable company you would be looking at upward of 100.00 per month. Netflix is asking for 16.00 and frankly should be asking for 30.00 a month. So please, quit your whining. The only people sympathetic to your cause are the people that will pull the half full soda from the fast food trash to sneak another sip. 

In reading this article I reminded of [ First World Problems.](<http://www.reddit.com/r/firstworldproblems>)

1\. http://technolog.msnbc.msn.com/_news/2011/07/12/7069809-thousands-threaten-to-quit-netflix

---
[View this page online](https://www.commandprompt.com/blog/netflix_should_tell_6000_users_to_please_cancel_their_accounts/)

---

# Real-world example of adding SAML authentication to a JBoss application

> What is SAML?
SAML stands for Security Assertion Markup Language. It&#x27;s an XML-based markup language and also an open security protocol standard. The most impo…

## What is SAML?

SAML stands for Security Assertion Markup Language. It's an XML-based markup language and also an open security protocol standard. The most important feature of this protocol is Web Browser Single Sign-On (SSO.) SSO allows users to login once and never be prompted for login/password later.

In this post we'll describe how to add SAML support to existing web application with the bare minimum of modifications to the application code itself.

## Shibboleth

While it's not impossible to implement the SAML protocol standard manually, it's much easier (and much less time-consuming) to take a ready to use solution, such as [Shibboleth](<http://shibboleth.internet2.edu/>), and this is what we are going to do: we'll integrate an existing JBoss application, running behind an Apache web server, with Shibboleth SAML2 authentication.

### Installing Shibboleth

The first step would be to download and install Shibboleth. Depending on your system, you might need to build it from source (or source RPMs,) but on Debian it comes pre-packaged:
    
    
    # apt-get install libapache2-mod-shib2
    

This will download and install Shibboleth authentication Apache module as well as `shibd` daemon, which handles the details of SAML protocol.

Currently, Debian ships with 2.3 series of Shibboleth, while the newest released version is 2.4. There's not much difference between the two versions (although the newer one allows for more compact configuration file.) If you need the 2.4 version, you'll have to install it in some more involved way. Refer to the installation docs here: <https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLinuxInstall>

### Configuring Shibboleth

Generally, Shibboleth works out of the box, but you need to provide some minimal configuration for it to do anything sensible.

**Note:** when installing from Source RPMs on rpm-based systems, you might need to adjust some build parameters or make `/etc/XML-Tooling` a symlink to `/etc/shibboleth`, since different parts of it seem to look for configuration files in different directories (I don't recall the exact name for the first dir, but `strace` is your friend if `shibd` won't start and print some cryptic errors on console.)

#### Service Provider configuration

For this scenario we will be configuring Shibboleth as a SAML Service Provider (the authentication side which provides restricted access to the resources and asks SAML Identity Provider for user access authorization.) Start by editing `/etc/shibboleth/shibboleth2.xml` and replace the default value of the `entityID` attribute in `ApplicationDefaults` element with some string which identifies your Service Provider in a unique way.

Typically a URL of the form `http://my.service-provider.com/shibboleth` can be used here (where `/shibboleth` URI not necessarily represents a resource which can be actually fetched using HTTP, it's just a common naming convention.)

In order to present your Service Provider with a security certificate you'll need to add/edit the `CredentialResolver` configuration element. On Debian (with `openssl` package installed) you may use the auto-generated "SnakeOil" certificate and private key, like this (for testing purposes **only** ):
    
    
    <CredentialResolver type="File"
        key="/etc/ssl/private/ssl-cert-snakeoil.key"
        certificate="/etc/ssl/certs/ssl-cert-snakeoil.pem"/>
    

Be sure to replace this with the real certificate and key once you're done with your testing.

**Note:** you'll need to restart `shibd` daemon for this change to take effect, since the above private key is normally not world-readable. Other changes to Shibboleth configuration take effect w/o a restart generally.

#### Identity Provider configuration

Now, any Service Provider (SP) in SAML must know to which Identity Providers (IdP) it should talk when authorizing or denying access to any particular restricted resource. To give your SP this information you'll need to edit `entityID` attribute of an appropriate `SessionInitiator` element (pre-2.4 versions) or of a `SSO` element (versions 2.4 and higher.) The `SSO` element in the newer versions' configuration is a nice shortcut to replace the whole series of configuration elements required in earlier versions (those, on the other hand, provide more flexibility.)

After putting the appropriate `entityID` for the IdP you are going to use for user authentication, you also need to add the IdP metadata file to the configuration, using an element like this:
    
    
    <MetadataProvider type="XML" file="idp-metadata.xml"/>
    

Where `idp-metadata.xml` is the XML-file containing SAML metadata for the IdP being used. You should contact your IdP to obtain this file (if you don't have this information at this point, refer to the "Testing" section below for testing options.) There is also a possibility to refer to IdP metadata by using a URL to it. The Shibboleth daemon will poll the URL periodically to check for any update on the metadata. Refer to Shibboleth documentation on `MetadataProvider` configuration element for details.

## Apache configuration

The above sections cover the Shibboleth configuration. However, this doesn't automagically adds SAML to your application... yet.

Shibboleth comes with a standalone daemon which actually handles the authentication and a web-server module, which observes client requests and talks to the Shibboleth daemon to deny or authorize the access. In this post we will be configuring Apache web server, please refer to Shibboleth documentation for use with different web servers.

To enable Shibboleth authentication for `/secure` URI on your server, add the following block to your `VirtualHost`:
    
    
    <Location /secure>
        AuthType shibboleth
        ShibRequestSetting requireSession 1
        Require valid-user
    </Location>
    

Or use `/` location to restrict access to your site as a whole. Restart or reload Apache to make the change take it's effect (by the way, Shibboleth daemon doesn't require a restart after modification of it's configuration files: it reloads them automatically.)

## Testing

At this point your Shibboleth and Apache installations are configured and now it's time to test the setup. However, sometimes you won't have the Identity Provider metadata or you just want to perform some internal testing before approaching the IdP.

You may try setting up a local IdP using the same Shibboleth installation for your test. Also there are some public online IdPs which you may use to test your newly setup SP, but I've found that installing a different SAML implementation for testing IdP works the best. First, testing on a different implementation gives your extra confidence that you've got it right, as opposed to testing with the same implementation as that of SP. Second, a locally installed solution allows for easier debugging, as opposed to using established online services.

I've found that [SimpleSAMLphp](<http://simplesamlphp.org/>) works really well for this purpose and requires minimum of configuration. So you might want to install it either on the same host or use a separate host for your testing IdP.

After configuring your testing IdP you'll need to add your SP metadata, so the IdP may verify the authentication requests coming from your SP. The SP metadata with Shibboleth is not stored in a file, but generated on request to `http://localhost/Shibboleth.sso/Metadata` (by default, from localhost only.) SimpleSAMLphp provides a web form to parse the XML metadata into it's internal format (PHP code actually) which you may paste into the IdP configuration file afterwards (typically, `simplesamlphp/metadata/saml20-sp-remote.php`.)

When this is done you are ready to test. Try accessing a restricted URL on your Service Provider site and watch you being redirected to your testing Identity Provider for authentication. After filling the login form correctly, you should be redirected back to your SP site.

However, at this point we didn't make any change to our application, so it won't notice any difference when we visit the restricted URL and are already authenticated with the IdP.

## Accessing authentication information in the application

Shibboleth passes the authentication information to the web application in form of CGI environment variables (`$_SERVER` array variable in PHP.) The sign of an established SAML session is presence of `Shib-Session-ID` environment variable.

However, if you use JBoss application server your code lives in a different process and has no direct access to the Apache server environment. To pass the required variables from Apache to JBoss you'll need to add the following `mod_jk` configuration directive:
    
    
    JkEnvVar Shib-Session-ID
    

After that, you may get the value of this variable using `request.getAttribute("Shib-Session-ID")` in your Java or JSP code.

### Accessing user identity information

Now you may tell apart SAML-authenticated access to your application from the non-authenticated. But session id is not suitable for identifying actual users, so how would you tell different users apart?

Here's where additional Shibboleth configuration files come into play. First, you might want to check the `shibd.log` file after successfully authenticating with your IdP. It will list the user identity attributes extracted from the IdP SAML response (such as name, email, affiliation, etc.)

If you don't see the expected attributes in the log, you might need to edit `attribute-map.xml` configuration file to add some `Attribute` elements. If you don't know which attributes to expect, it might be helpful to increase logging level for your SP or IdP to capture the exact SAML response XML text being sent and look for `saml:Attribute` elements which might look familiar. For example, you might want to add something like this to the attribute map file:
    
    
    <Attribute name="username" id="SAML-UserName"/>
    

This will pass the value of SAML `username` attribute in the `SAML-UserName` environment variable (remember to add appropriate `mod_jk` directives if you need to pass them further to JBoss.)

As a special case, the user identity (`NameID`) attributes extraction require special configuration syntax. For example:
    
    
    <Attribute name="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
                  id="SAML-UserName">
        <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$Name"
                  defaultQualifiers="false"/>
    </Attribute>
    

Refer to Shibboleth documentation for details.

## Performing sign-on using SAML user id

Now you should be able to identify a SAML-authenticated user. Depending on your application details you might need to find the corresponding user record in your application's authentication structures or add the new user unconditionally (after all you trust the IdP that the user is the one he pretends to be.)

**Note:** this is the first place where you'll need to touch your application code. All of the above only requires external configuration changes.

### Handling Single Logout

If you successfully managed to handle Single Sign-On using the above information, you'll likely want to add handling for Single Logout, so that user may log out of your Service Provider as well as Identity Provider.

Single Logout in Shibboleth is handled by `/Shibboleth.sso/Logout` URI by default. You might want to redirect user to that URI after logging out of your application (local logout.) This is the second place where your application code _might_ need to be modified.

## Conclusion

In this post we've shown how you can add SAML-based authentication to your application with the minimum of changes to the application code, with the use of Shibboleth SAML authentication engine.

---
[View this page online](https://www.commandprompt.com/blog/real-world_example_of_adding_saml_authentication_to_a_jboss_application/)

---

# Actually, I am going to #PgWest (and you might not want to)

> OK, I am just trying to set the record straight. People are still confused thinking I might not be going to #PgWest, but I am. I know where the confusion comes…

OK, I am just trying to set the record straight. People are still confused thinking I might not be going to [#PgWest](<http://www.postgresqlconference.org/>), but I am. I know where the confusion comes from; there are a few other conferences going on during that time frame but the only two that matter are [#PgWest](<http://www.postgresqlconference.org/>) and [Surge](<http://omniti.com/surge/2011>). So, to be clear, I will be going to #PGWest this year not Surge. Also, to be clear, it's not that I have anything against Surge. I've have never gone to Surge but I have heard nothing but good things about the conference and I suspect I'll probably go to Surge in the future. It's just that this year, I've got something better to go to. That something is #PgWest. 

**What is #PgWest?**

The theme for #PgWest is:   


> "Next Generation Data"   
>  PostgreSQL Conference West is designed to get you up to speed on how to use the data existing already locked in your organization and cope with the massive amounts of data that is coming. Our industry today is at a major inflection point with Cloud Computing, Big Data, and GeoSpatial all converging into fascatining new architecture resulting in amazing new applications. The existing advanced features and some truely innovative features in PostgreSQL 9.1 will allow PostgreSQL to be the foundation of these new architectures. 

#PgWest is the PostgreSQL West Coast conference (thus #PgWest) and it happens every year in the fall. Last year we held it in November, normally we hold it in October. This year, we are really close to October at September 27th - 30th in San Jose. #PgWest is also the single largest contributor of educational materials as well as the single largest direct financial contributor to the PostgreSQL community. If you are working with PostgreSQL, #PgWest is where you want to be in September, maybe. #PgWest is the largest PostgreSQL Conference in the United States and will continue to be as we experience easy double digit (not 10%, think 30% - 50%) growth every time we hold it. 

**Why should you go to Surge?**

Surge, from all reports, rocks. It is a great conference full of very smart, fun people who are there for solutions to problems, not minutia political babble. If you want to go to Surge, go to Surge and I guarantee you, it will be worth your time and conference dollars. 

**Why are you telling me to go to Surge?**

Surge is an annual East Coast conference, if you are torn between going to #PgWest and Surge, wait for #PgEast next March. The PostgreSQL Conference is a semi-annual conference with one conference #PgWest on the West coast and one #PgEast on the East coast. By the time Surge and #PgWest happen, #PgEast will only be six months away. I want Surge to be successful. If Surge was on the West coast, I would be reaching out to the Surge folks and trying to share facilities to save costs for everyone. 

  * [#PgWest call for papers is still open!](<https://www.postgresqlconference.org/talk_types>)
  * [Surge early bird registration](<http://omniti.com/surge/2011/register>)

---
[View this page online](https://www.commandprompt.com/blog/actually_i_am_going_to_pgwest_and_you_might_not_want_to/)

---

# #PgWest 2011: CFP Open

> Following on the smashing success of PostgreSQL Conference East, PostgreSQL Conference West, The PostgreSQL Conference for Developers, End Users and Decision M…

Following on the smashing success of PostgreSQL Conference East, PostgreSQL Conference West, The PostgreSQL Conference for Developers, End Users and Decision Makers, is being held at the San Jose Convention Center, in San Jose, CA from September 27th - 30th. Please join us in continuing to make this the largest PostgreSQL Conference series in North America. 

  * [Main site.](<https://www.postgresqlconference.org/>)  

  * [Call for papers](<https://www.postgresqlconference.org/talk_types>)

**Time line:**

> May 25th: Talk submission opens  
>  July 31st: Talk submission closes  
>  August 8th: Speaker notification  
> 

This year we will be continuing our trend of covering the entire PostgreSQL ecosystem. We would like to see talks and tutorials on the following topics: 
    
              * General PostgreSQL: 
                  * Administration 
                  * Performance 
                  * High Availability 
                  * Migration 
                  * GIS 
                  * Integration 
                  * Solutions and White Papers 
          * The Stack: 
                  * Python/Django/Pylons/TurboGears/Custom 
                  * Perl5/Catalyst/Bricolage 
                  * Ruby/Rails 
                  * Java (PLJava would be great)/Groovy/Grails 
                  * Operating System optimization
                    (Linux/FBSD/Solaris/Windows) 
                  * Solutions and White Papers

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2011_cfp_open/)

---

# PGCon 2011 Developer's Meeting picture

> For those that are curious (and which for some reason don&#x27;t follow the #pgcon tag at twitter), here&#x27;s a picture of the attendees of Developer&#x27;s Meeting.Back ro…

For those that are curious (and which for some reason don't follow the #pgcon tag at twitter), here's a picture of the attendees of Developer's Meeting.

Back row, from left to right: Robert Haas, Selena Deckelmann, Marko Kreen, KaiGai Kohei, Stephen Frost, Magnus Hagander , Robert Treat, Tom Lane, Heikki Linnakangas, Mark Wong, Josh Berkus, Kevin Grittner, Dimitri Fontaine, Koichi Suzuki, Andrew Dunstan, Fujii Masao, Jeff Davis, Greg Smith, Tatsuo Ishii, Dave Page, Simon Riggs.

Front row: Greg Stark, David Wheeler, David Fetter, Bruce Momjian, Teodor Sigaev.

If you want to see a larger version, click on it.

---
[View this page online](https://www.commandprompt.com/blog/pgcon_2011_developers_meeting_picture/)

---

# PgWest 2011: San Jose Convention Center, September 27th-30th

> I am currently at the Gartner BI conference (yes really), so I won&#x27;t have time to announce officially until later this week but I have had a lot of people aski…

I am currently at the Gartner BI conference (yes really), so I won't have time to announce officially until later this week but I have had a lot of people asking me about when West will be. So, here ya go. San Jose, September 27th-30th at the convention center. The conference is already set up at [Lanyrd if you want to get social.](<http://lanyrd.com/2011/pgwest/>)

The website is not quite updated yet but should be this week. I will post an official announcement soon with a full wrap up of the Gartner BI conference.

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2011_san_jose_convention_center_september_27th-30th/)

---

# An attempt at finding glaring btree problems

> Some time ago, a customer came to us with a strange vacuuming problem.  Their regular vacuum job would die with a message such as this one:


vacuumdb: vacu…

Some time ago, a customer came to us with a strange vacuuming problem. Their regular vacuum job would die with a message such as this one:
    
    
    vacuumdb: vacuuming of database "clint_app" failed:
      ERROR: failed to re-find parent key in index "work_items_pkey" for deletion target page 6100
    

Eventually, it turned out that their storage firmware had some glitch that caused things to go wrong in random ways, and corruption in various places was detected.

However, before this was discovered, many other errors were found and reported. After a lot of back and forth, we decided to write a simple tool to verify the data contained in btree indexes. This tool would scan the index structure and traverse the tree, reporting places on which the nodes and leaves didn't align with expectations.

I've mentioned this tool at various times in mailing lists and such, and given to a few customers. It has proven useful to determine whether a given problem is some sort of hardware problem that's causing widespread usage, or something localized. I've now published the code in [Github](<https://github.com/alvherre/pgbtreecheck>).

This is very rough around the edges, and there are more checks that could be written given sufficient interest.

If you find it useful, please let me know in a comment.

---
[View this page online](https://www.commandprompt.com/blog/an_attempt_at_finding_glaring_btree_problems/)

---

# This is what table bloat looks like

> I got curious about a bloat problem on a customer&#x27;s system today.  The statistics as calculated by normal tools/queries say that one of the tables is 2x bloate…

I got curious about a bloat problem on a customer's system today. The statistics as calculated by normal tools/queries say that one of the tables is 2x bloated. Another table is 6x bloated. And so on. For some reason I wanted to see what it looked like in a graphical way, so I threw together this simple query:
    
    
    select s, coalesce(count, 0)
      from (select block, count(*)
              from (select split_part(tid, ',', 1)::int as block,
                           split_part(tid, ',', 2)::int as offset
                      from (select trim(both '()' from textin(tidout(ctid))) as tid
                              from flight_details
                           ) a
                   ) b
          group by block) c
     right join (select s from generate_series(0, 28000) s) d on (c.block = d.a)
    order by a ;
    

(This is a 8.2 system; in newer servers you can simplify the inner query a bit). 

After setting appropriate parameters in psql (`\pset format unaligned` and `\pset fieldsep ' '` and `\o /tmp/population.data`), I gave the output to Gnuplot using this simple script: 
    
    
    set terminal jpeg size 10000,600
    set output "population.jpg"
    
    plot "/tmp/population.data" using 1:2 with points
    

When viewed zoomed out, it looks like this: 

[![population](http://farm6.static.flickr.com/5103/5614332144_d8d9367ab7.jpg)](<http://www.flickr.com/photos/alvherre/5614332144/> "table population")

This plot represents the number of tuples in each page. The plateau at the left is a very densely populated group of pages — this is optimal space usage. Then in the middle you can see a cloud which is closer to the bottom. Finally, the straight line at the far right represents the pages less than 28000 that the table has. (The query could be refined to avoid this tail.) 

Ideally you should have a bit over 10% of dead space on each page on average, if autovacuum has default parameters. In this case, there is clearly a problem after the first sixth of the table: the dots are too low. This indicates bloat in those pages.

---
[View this page online](https://www.commandprompt.com/blog/this_is_what_table_bloat_looks_like/)

---

# Our company, EnterpriseDB, is the commercial company that brings to market the open source Postgres database., Ed Boyajian.

> I tend to spend a lot of my time reviewing what is going on in the wider PostgreSQL ecosystem. Over the past few months I have been increasingly intriqued at a…

I tend to spend a lot of my time reviewing what is going on in the wider PostgreSQL ecosystem. Over the past few months I have been increasingly intriqued at a overriding theme that is starting to emerge in the market. That "EnterpriseDB" is "The PostgreSQL Company". This isn't about taglines but actual perception in the market. 

I was speaking with an individual from 10Gen (#PgEast Gold Sponsor and creator of MongoDB). This individual asked me to lay out the history of PostgreSQL, how did it operate (community) etc... While discussing this, the individual asked me a question, "So, do you work for EnterpriseDB?". Luckily I wasn't drinking anything at the time otherwise I would have needed a new monitor. 

Today, I came across [this interview with Ed of EnterpriseDB (#PgEast Platinum Sponsor)](<http://www.founderbuzz.com/interviews/ed-boyajian-of-enterprisedb-discusses-when-to-open-source-software/>), where Ed states, "Sure. Our company, EnterpriseDB, is the commercial company that brings to market the open source Postgres database.". 

I must applaud EnterpriseDB's marketing prowess. They are obviously starting to penetrate the minds of the ignorant and create a thin veneer of false-reality that is truly remarkable (no sarcasm). When you have been in this community as long as I have, and have seen how EnterpriseDB went from, "Who?" in 2004, to "JD works for them" in 2011, that is a testament to some heavy marketing lifting. 

I don't have any problem with EDB. They are a truly great community contributor but I do think it is important for everyone to remember that while EDB is the elephant in the room (no pun intended), there are hunters who have been around a lot longer. Credativ, 2ndQuadrant, Agliodbs, and yes Command Prompt are who I would argue are actually bringing Postgres to market. We are doing so by providing the professional services, custom development, training, advocacy and many thousands of hours of volunteer time that is what makes up PostgreSQL. 

Of course, we all know who the real "PostgreSQL Company" is: 
    
    
    thepostgresqlcompany.com
    
    Registrant:
    David Fetter ()
    David Fetter Consulting
    2500B Magnolia Street
    Oakland, CA 94607-2410
    US
    
    Domain Name: thepostgresqlcompany.com
    

Disclaimer, if I didn't list your company don't take it personally. I am just going with who was off the top of my head.

---
[View this page online](https://www.commandprompt.com/blog/our_company_enterprisedb_is_the_commercial_company_that_brings_to_market_the_open_source_postgres_database_ed_boyajian/)

---

# Things you learn.... Reddit runs PostgreSQL (and Cassandra)

> Not much to say here, but this is a great thread on why the &quot;Cloud&quot; is a serious problem real, production quality, database use.

Not much to say here, but this is a great thread on why the "Cloud" is a serious problem [real, production quality, database use.](<http://www.reddit.com/r/reddit.com/comments/gj5ak/dear_admin_lets_be_frank_and_honest_about_it/>)

---
[View this page online](https://www.commandprompt.com/blog/things_you_learn_reddit_runs_postgresql_and_cassandra/)

---

# When Too Smart Becomes Stupid: fixing a RoR PgSQL driver issue

> 
One of our customers who is using Ruby on Rails with the PostgreSQL database backend notified us of a long-standing issue with the database driver: Lighthous…

One of our customers who is using [Ruby on Rails](<http://rubyonrails.org/>) with the PostgreSQL database backend notified us of a long-standing issue with the database driver: [Lighthouse ticket #3721](<https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/3271>)

The driver is doing something that at first glance looks like a smart thing, but apparently it's not that smart. What it does is it tries to detect the bit-string notation (binary vs. hexadecimal) based on the string content passed to it. Let's take a look at the code: 
    
    
    elsif value.kind_of?(String) && column && column.sql_type =~ /^bit/
      case value
        when /^[01]*$/
          "B'#{value}'" # Bit-string notation
        when /^[0-9A-F]*$/i
          "X'#{value}'" # Hexadecimal notation
    

So what's so bad about it? The problem is that with this approach you just cannot reliably use hexadecimal notation to store arbitrary bit-strings. Because if the data you are storing happen to have only zeros and ones in the hexadecimal notation, then the not-so-smart driver will think it's binary notation and choose the wrong path. This is especially troublesome when varying bit-strings are used, because instead of getting database error you'll get your data corrupted. 

So how do we fix that? 

The issue reporter already provided a few options: drop bit-strings support altogether; support only one notation; or only accept strings tagged with the base prefix. The first one doesn't really fix the problem, apparently. Let's have a closer look at what's left. 

In Ruby there is a notation for both binary and hexadecimal numbers: `0b[01]+` for binary, and the usual `0x[0-9A-F]+` for the hex (sans the letters case.) So my thought was that it would be really nice to support the same prefix tags to determine the bit-string base. Unfortunately this is not going to work, because of that `0b`: it has a huge potential to be mistaken for hexadecimal number by either older driver code or a human being. 

Now to supporting only one notation. Which one to keep? Well, since the bug was not fixed for a long period of time, most people must be unaware of it and are not affected. So this means, most people must be using binary notation, which doesn't have the potential for data corruption. Another point is that even if you can _store_ the bit-string in either of notations, the fetched value is always a binary bit-string. 

Unfortunately, any approach to fix this problem potentially breaks some code. But I had to choose one which does it in the least inappropriate way. To my mind, keeping only binary notation is clearly the winner here: it doesn't change behavior for unaffected code in any way, yet any affected code will fail prominently signalling of a problem. 

After that, the patch was fairly easy to create (not posting here: it is attached to the ticket, so anyone interested may have a look.) That's it--see you next time. :)

---
[View this page online](https://www.commandprompt.com/blog/when_too_smart_becomes_stupid_fixing_a_ror_pgsql_driver_issue/)

---

# Finally, a Real Pastebin Plugin for Redmine

> 
It was rather puzzling to me why Redmine doesn&#x27;t come with a Pastebin module and why there&#x27;s no plugin for that.



One of the proposed &quot;solutions&quot; is to…

It was rather puzzling to me why [Redmine](<http://redmine.org/>) doesn't come with a [Pastebin](<http://en.wikipedia.org/wiki/Pastebin>) module and why there's no plugin for that. 

One of the proposed "solutions" is to start a new wiki page, and put some `<code>` markup there. While this seems to work, it has some limitations a real pastebin component wouldn't suffer from. First thing that comes to mind is that you need a unique name to start a new wiki page. Second, the wiki code markup is currently (as of redmine-1.1.0) done using `spans`, which makes it cumbersome to select and copy the code from the page: the line numbers will mess up your pasted code. 

Now, for public projects you can always use [the pastebin](<http://pastebin.com>) (or any of the similar sites,) but that's not an option for private projects. So I've decided to spend a few hours and create a full-blown pastebin for redmine: <https://github.com/commandprompt/redmine_pastebin>

## Use The Force, Luke

So, I've opened up the official [Plugin Tutorial](<http://www.redmine.org/projects/redmine/wiki/Plugin_Tutorial>) and started to work from there. The tutorial itself is great and I had a working prototype in a really short time, however there are some interesting details which it doesn't cover. 

## Routes

While following the tutorial, you may notice that URIs for the resources we're adding ("pastes" in our case) are different from what you see throughout standard Redmine modules. Your URIs will look like e.g. `/pastes/?project_id=1`, while in Redmine they look like `/projects/myproject/pastes`. How do we make our URIs look like the standard ones? 

Well, turns out it's enough to open up the `config/routes.rb` of your plugin and add the following line: 
    
    
    ActionController::Routing::Routes.draw do |map|
      map.resources :pastes
      map.resources :pastes, :path_prefix => '/projects/:project_id' # <= this one
    end
    

And that's it! If you followed the rails way, all your `new_paste_url` and friends will now return the nicely-looking URLs (as long as you pass the project_id param.) 

## Monkey-Patching the Referenced Models

OK, now since pastes (much like the issues) are per-project entities, we've specified the `project_id` foreign key when we've created the pastes table in our migration. So any given paste _belongs to_ some project. How do we specify that in our plugin? 

Easily :) Just open `app/models/pastes.rb` and add `belongs_to :project` at the class level. But that's only half of the problem. The project, on the other hand, _has many_ pastes. How do we add that? 

The language-supported solution in Ruby to add functionality to existing classes is called 'monkey-patching.' To employ this technique for our needs, we'll create a new file in our plugin's directory called `lib/redmine_pastebin/project_pastes_patch.rb` and put the below code there: 
    
    
    module RedminePastebin
      module ProjectPastesPatch
        def self.included(base)
          base.class_eval do
            has_many :pastes
          end
        end
      end
    end
    

To actually 'apply the patch' we should open our `init.rb` file and throw in some code like this: 
    
    
    require 'dispatcher'
    
    Dispatcher.to_prepare :redmine_model_dependencies do
      require_dependency 'project'
    
      unless Project.included_modules.include? RedminePastebin::ProjectPastesPatch
        Project.send(:include, RedminePastebin::ProjectPastesPatch)
      end
    end
    

And we're all set. There's no need to 'require' the file containing the patch module, since if you've followed the convention, the Rails' automatic dependency loader will try to load `lib/redmine_pastebin/projects_pastes_patch.rb` first time it hits `RedminePastebin::ProjectPastesPatch` in the code. 

Since every paste belongs to an author (a user,) exactly the same technique was used to monkey-patch the `user` model. 

## Making Forms Look Natural

One thing you'll notice when creating your plugin for Redmine, is that your input forms are looking different from those used throughout Redmine itself. This is because in Redmine they're using a custom `FormBuilder`. You can also use it easily, here's for example, what 'New Paste' form looks like: 
    
    
    <% labelled_tabular_form_for :paste, @paste, :url => { :action => "create",
         :project_id => @paste.project.id } do |f| %>
    <div class="box">
      <p><%= f.text_field :title %></p>
      <p><%= f.select :lang, pastebin_language_choices %></p>
      <p><%= f.text_area :text, :rows => 25, :cols => 80 %></p>
    </div>
    <%= f.submit "Paste!" %>
    <% end %>
    

## Showing Pastes in Activity Report

A nice feature of Redmine is Activity timeline report, that can show you which changes were made on the project during specified period of time. This includes creating and updating issues, committing to code repository, editing wiki pages, etc. Let's add pastes to the mix. 

Open up your `init.rb` and put a code block like this at the bottom: 
    
    
    Redmine::Activity.map do |activity|
      activity.register :pastes
    end
    

Now, open `app/models/paste.rb` and throw in some code like this: 
    
    
      acts_as_event :title => Proc.new{ |o| o.title },
        :url => Proc.new{ |o| { :controller => 'pastes', :action => 'show',
          :id => o.id } }
    
      acts_as_activity_provider :find_options => {:include => [:project, :author]},
        :author_key => :author_id
    

And that should be it. Now newly created pastes will be showing in the project activity report along any other changes. 

## More Fun with Menus

Initially I was going to add only a single project-level menu item and call it 'Pastebin,' where users could view the existing pastes and provide a link called 'New Paste' at the top of the list. However, this didn't play well with some roles permissions I don't quite recall now (it has something to do with some role being able to add new pastes, but not list the existing ones.) 

So I decided to replicate the issues approach, where 'Issues' and 'New Issue' are separate project-level menu items. Naturally I've added another `menu :project_menu, ...` stanza to my `init.rb`, and it seemed to work. Except for one minor thing: then you visit 'New Paste' link, the project menu highlights 'Pastes' instead. 

After debugging that for quite some time, I've found out that it is required to add some code like this to the `pastes_controller.rb` to make it work: 
    
    
      menu_item :new_paste, :only => [:new, :create]
    

This way the menu item is highlighted as it should be (note the :create action, since on save errors `create` renders `new`.) This is not nearly obvious, so I hope this might save someone's time someday. :) 

## The Ugly Guts

So far so good, we've been able to get what we need using pretty much approved techniques. Time for some dirty hacks. ;) 

One thing I've mentioned in the beginning which makes wiki-based "solution" of the pastebin problem unusable is that it doesn't produce such html markup from which you could copy/paste to your code easily. If you look at how syntax highlighting is handled in Redmine you'll notice the nice module called `Redmine::SyntaxHighlighting.` It is supposed to work as a facade to different pluggable syntax highlighting engines, and [CodeRay](<http://coderay.rubychan.de>) is the default one. 

Now CodeRay itself supports the layout we need for pastebin, but you can't just get to it since the Redmine's module gets in your way. It's a good place to improve Redmine itself, but for now I've just went the easy route and started using CodeRay directly, since it's bundled with Redmine anyway. This ugly hack lives in the `pastes_helper.rb`: 
    
    
      def highlighted_content_for_paste(paste)
        content_tag :div, :class => "syntaxhl box" do
          ::CodeRay.scan(paste.text, paste.lang).html(:line_numbers => :table)
        end
      end
    

At this point everything seemed to be working, until someone tried the 'diff' highlighting which appeared rather messy. Adding some simple CSS code to the `show` action template solved the problem: 
    
    
    div.paste .syntaxhl div {
      display: block;
    }
    
    table.CodeRay td.line_numbers {
      text-align: right;
    }
    

The second CSS rule makes line numbers align nicely by the lowest-order digit. This is a hack again as we need to hard-code 'CodeRay' in the selector... 

## Conclusion

That's it for this time. As one can see, making a new Redmine plugin is fairly easy and you can create a working prototype from scratch in no time. When it comes to more obscure aspects of integration, the invaluable source of learning is looking at what others have made already and, ultimately reading Redmine's source code and/or debugging it to "Make It Darn Work!" :)

---
[View this page online](https://www.commandprompt.com/blog/finally_a_real_pastebin_plugin_for_redmine/)

---

# Recovering a lost-and-found database

> Last week, a company&#x27;s only PostgreSQL database server suffered an UPS
failure.  When they found they couldn&#x27;t connect to it afterwards, they called
Command …

Last week, a company's only PostgreSQL database server suffered an UPS failure. When they found they couldn't connect to it afterwards, they called [Command Prompt](<http://www.commandprompt.com/>) to investigate.

The most important lesson to be learned here is: **you need to make very sure you[have backups](<http://www.commandprompt.com/blogs/joshua_drake/2010/07/a_better_backup_with_postgresql_using_pg_dump/>)**. Even if the strategy is too simple, or even if they are taken only once a fortnight, they are going to save your neck someday just by being there. In time you will find the way to improve your backups: make them more selective, more frequent, less intrusive, whatever. Not having any backup **at all** means that if you lose your database, you may be out of business.

This could have very well been the case here, but we worked very hard to ensure this didn't happen to them. Here's the story.

## What we were told

The customer received the following error message when trying to connect to the broken database
    
    
    psql: FATAL:  could not open relation 1663/17409944/1259: No such file or directory
    

Anyone familiar with the Postgres' system catalogs will immediately realize that something is very, very wrong here: 1259 is the OID and file name of the `pg_class` catalog. And if that file is missing, who knows what else might be missing as well?

Upon logging in into the machine and listing the database directory, it becomes quite clear that things are going very wrong indeed. Not only is pg_class missing -- all the other catalogs, and their indexes, are missing as well.

## What we found

Since the server had had an unclean shutdown, the obvious place to look for the missing files was `lost+found`. This is the directory where the `fsck` utility stores lost (and found) files that it cannot find a proper directory entry for; one peculiarity of `lost+found` entries is that since the directory entry is gone, they have lost their file names. `fsck` restores them to funny-looking names such as `#1801237981` where the number is its inode number, and leaves to you the task of figuring out what's the correct name to attach to it (and on which directory to place it.)

The way Postgres stores table data is by using plain files. Each file is just a bunch of data pages. If you can't read binary stuff, it's just a bunch of gibberish. There's nothing on the file itself that tells you what table it belongs to. If the file name is lost, such as in this case, there's no direct way to figure it out again. You're pretty much on your own.

To make the problem slightly worse, we found a whopping total of 480 files in `lost+found`. Figuring out all of those was going to take quite a while!

## What we thought

We're all told at school: the first thing to do when confronted with a huge problem is to break it up into smaller pieces. Then, instead of having to solve a single huge, impossible problem, you have to solve a large bunch of not-so-huge, hopefully tractable problems. And what better way to partition this huge problem than classifying the files.

Now, as I said earlier, Postgres data files just look like binary gibberish to an outsider. To someone in the know, however, they open all their secrets: for example, RedHat's immensely useful [`pg_filedump`](<http://pgfoundry.org/projects/pgfiledump>). `pg_filedump` can easily tell if a file is an index file, a sequence, or a table; moreover, it is possible to classify the table files according to the number of columns. 

## What we did (to sort out the files)

After creating a copy of `lost+found` that I could play with, I ran this:
    
    
    mkdir btrees sequences
    for file in *; do
    	if pg_filedump-8.3 -R 0 $file | grep -q 'Sequence: '; then
    		mv $file sequences
    	fi
    done
    for file in *; do
    	if pg_filedump-8.3 -R 0 $file | grep -q 'BTree Meta Data'; then
    		mv $file btrees
    	fi
    done
    

This moved the index and sequence files out of the way. The indexes can be recreated with `REINDEX`; the sequences are impossible to tell apart from one another, so it's easier to deal with them by setting to the values they need to have according to the data in the tables. But that's for later.

The second thing to do is classify all the remaining table files according to the number of attributes that can be found in each one. This was a bit more involved:
    
    
    for file in *; do
    	attrs=$(~cmd/pg_filedump-8.3 -fi $file |
    		grep ' Attributes: [0-9]\+' |
    		sed -e 's/.*Attributes: \([0-9]\+\) \+Size.*/\1/' |
    		sort -r |
    		head -1)
    	if [ ! -z "$attrs" ]; then
    		mkdir -p $attrs
    		mv $file $attrs
    	fi
    done
    

## What we did (to restore the catalogs)

After this has been done, what you have is a bunch of subdirectories named after a number, which is the number of attributes that all the tables whose files ended up in there have. So if you're looking for `pg_class` file, you need to look in subdir `27` (our customer was running 8.2). More likely than not, there will be multiple files in that directory. The easiest way (that I know) to figure out which file it is is to look at all of them with `pg_filedump` again (this time with the `-fi` options), and look for well-known strings in the data area; for `pg_class`, the name `pg_class` itself suffices, though the name of any table would do. Once you have identified the file, all you have to do is move it in place (17409944 is the database OID and directory name, and 1259 is, remember, `pg_class`'s file name):
    
    
    mv /data/lost+found.copy/#175254092 /var/lib/pgsql/data/17409944/1259
    

Restoring most catalogs is not hard if you follow this technique. But you're not at a point where this database is usable yet: attempts to connect to it will still fail, because you haven't restored the indexes of those catalogs. Fortunately, doing this is simple: just start a _standalone backend_ with indexes disabled and run a `REINDEX SYSTEM` of the database in question:
    
    
    postgres --single -P -D /var/lib/pgsql/data the_affected_db
    **PostgreSQL stand-alone backend 8.2.20
    backend>** reindex system the_affected_db;
    **NOTICE:  table "pg_class" was reindexed
    NOTICE:  table "pg_authid" was reindexed
    NOTICE:  table "pg_statistic" was reindexed
    ...**
    

I didn't save the exact output here, but if I remember correctly, this failed initially and I had to reindex one catalog separately first (pg_type I think). Also, I think it emitted a warning message for each index that should have been there but wasn't, saying that file such-and-such could not be removed, but this is harmless.

After you've restored all the catalogs, the database can be started normally. You can't query the user tables yet, because they are gone -- but at least you can query the catalogs which is enough to know what tables there should be, and particularly how many columns each one has.

## What we did (to restore user tables)

This query proved very useful: 
    
    
    select relnamespace, relname, relhasoids, relfilenode,
           relpages, relpages * 8192 as size, reltuples,
           (select array_to_string(array(select attlen
    				       from pg_attribute
    				      where attrelid = pg_class.oid and
                                                attnum > 0),
                                   ',')) as attrlens,
          pg_ls_dir as file
    from pg_class left join
        (select *
           from pg_ls_dir('base/17409944')
          where pg_ls_dir ~ '^[0-9]*$') foo
                  on (relfilenode = pg_ls_dir::oid)
    where relkind in ('r', 't') and relnatts = :natts
    order by relpages desc;
    

This query returns, for each table, not only the basic information in the pg_class catalog, but also whether it has OIDs and whether there is already a file on disk for that table; and lastly, the length of all of its attributes. For example, in a fresh database I see this with `natts` set to 5: 

result of query above relnamespace | relname | relhasoids | relfilenode | relpages | size | reltuples | attrlens | file  
---|---|---|---|---|---|---|---|---  
11 | pg_amop | f | 2602 | 3 | 24576 | 445 | 4,4,2,1,4 | 2602  
10621 | sql_packages | f | 10752 | 1 | 8192 | 10 | -1,-1,-1,-1,-1 | 10752  
10621 | sql_parts | f | 10757 | 1 | 8192 | 9 | -1,-1,-1,-1,-1 | 10757  
10621 | sql_implementation_info | f | 10742 | 1 | 8192 | 12 | -1,-1,4,-1,-1 | 10742  
10621 | sql_sizing_profiles | f | 10767 | 0 | 0 | 0 | 4,-1,-1,4,-1 | 10767  
  
(The reason I also display the `relhasoids` column is that some tables had OIDs but not all. I guess the database was started in a Postgres release that had OIDs enabled by default, and later moved to one that had them disabled.)

The `attrlens` columns is interesting: for example, a table with three integer columns (which would be displayed as `4,4,4`) should only have 12 bytes of data in each tuple (not counting header); so if I look into a file with `pg_filedump` and there's a tuple with 16 bytes, I know it must belong to some other table. If I see a boolean column in the last position, there is a most obvious trailing lone byte in each tuple. And so on. In most cases, this examination of tuple length in `pg_filedump` allowed me to determine the correct file for each table.

The tuple's "infomask" bits are also useful. A table with only fixed-size columns (i.e. no -1 in it, indicative of a "varlena" column such as text, varchar or numeric), for example, will not show up in `pg_filedump` as having the `HAS_VARWIDTH` bit set. Tables where all columns are `NOT NULL` cannot have tuples that have the `HASNULL` bit set. In a few cases, I had to resort to decoding the null bitmask in order to compare it with the nullable columns that each table is declared to have. And there's the OID business I mentioned above.

Another cue was the table size in pages and tuples as stored in `pg_class.reltuples` and `pg_class.relpages`. These numbers are not entirely trustworthy, because they are only updated by commands such as `VACUUMM` and `ANALYZE` (in some cases I found discrepancies up to 20% with the actual data in the table); however they should be the same ballpark.

I also resorted to examining string data and some common sense; for example, a table called "instruments" could very well hold a row that says "spectrograph" in it.

In a few cases, however, things were a bit more difficult: for example, there were several tables with three integer columns. In those cases, the only resource I had was to look into the data and try to figure out if it matched what the foreign keys were telling me. This was the most time-consuming part of the job. I assume that matching TOAST tables to their respective main tables would be complex. Fortunately they didn't have many TOAST tables either.

In all cases, after finding a relationship between table and file, all that remained was to move the file in place and run a REINDEX of that table. If the server was up I could ran a quick query to determine that the data was valid (I figured that if I messed up badly, the server would crash upon trying to read bad data. This didn't happen to me this time; maybe it was pure luck). And after a few tables were up, I could start running queries to determine that the FKs validated correctly.

## What we conclude

As I said at the beginning, the most important conclusion is **backups are really important** ; while you may believe yourself protected, such as having a UPS to prevent power failure problems, those can still fail.

However there is also something to be said for filesystems, ext3 in this case. I can excuse a filesystem from losing the name of a file I just created, or maybe a page or three of contents of an old file. I cannot find any reason for a filesystem to lose a large bunch of files that have existed for months. Something went really wrong with it. I was told [on twitter](<http://twitter.com/#!/rootwyrm/status/44914023908638720>) that ext3 is known for losing files. Also, its journal does not even have a CRC: if it gets corrupt, the replay algorithm may be told to write any random garbage anywhere on the filesystem. This cannot be sane. I guess it's time to start looking elsewhere.

I'm also having second thoughts about this idea that Postgres data files are not self-identifying. It would have helped my job immensely to have a simple header that told me what table OID the file belonged to (it should also carry the segment number, though this wasn't important to me because all tables were under 1 GB.) This is something I shall propose to the community for the 9.2 release.

## Thanks for reading this far

The procedure I described here is not _exactly_ what I did; rather, its a summary of what I found was the most productive way to go about it, after fiddling with some other alternatives.

I hope this will be useful to someone trying to figure these things out. At the same time, I really hope no one sees him or herself dealing with such an unprotected breakdown of the database.

---
[View this page online](https://www.commandprompt.com/blog/recovering_a_lost-and-found_database/)

---

# #PgEast update, trainings, roundtables and NYC -- Oh my

> I arrived at the New Yorker yesterday to find that it was an excellent choice for our attendees to sleep. In the last couple of years they have renovated all t…

I arrived at the New Yorker yesterday to find that it was an excellent choice for our attendees to sleep. In the last couple of years they have renovated all the rooms and the hotel is quite nice. I have a double and will be here the next 12 days, yes that means I will be here on St. Patrick's day. For all those PostgreSQL Peeps that have never been to NYC, the bars are open till 4AM (although I was long asleep by then). 

[Mastering PostgreSQL Administration and Surviving Server Overload are both registering at record pace (in fact if you want to take these classes you better register now). ](<http://www.postgresqlconference.org/register>) The Pro PostgreSQL and Streaming replication classes are also doing respectably. All four of these classes are being given by well know PostgreSQL Contributors, Bruce Momjian, Greg Smith, Robert Treat and Magnus Hagander respectively. 

We have also announced a round table at East specifically geared toward a very real problem in the current market, Databases in the Cloud. I am looking forward to this round table as it features and eclectic mix of expert practitioners from Cirrus, to 10Gen, Heroku and Open Hosting. 

When we decided to change the training format for #PgEast we weren't sure what to expect. We have done a few trainings in the past, specifically at the last #PgEast and they were reasonably successful. We took a shot this year and pushed the envelope on the number of trainings we were going to provide and with all risks there are some possibilities that not all things will work out. Thus, due to low registration for the class, Django. Although the Rails class is doing just fine. While considering why the registration was low, I don't think it was that it was Django. I think that it was a general Django + PostgreSQL class. If the class has been something like, Scaling your application with Django + PostgreSQL it would have been more attractive.

---
[View this page online](https://www.commandprompt.com/blog/pgeast_update_trainings_roundtables_and_nyc_--_oh_my/)

---

# NoSQL, ??? Is there a threat?

> With #PgEast just two weeks away I have been looking for every possible place that I can to advocate the conference. In doing so, I have been finding lots of i…

With [#PgEast](<http://www.postgresqlconference.org/>) just two weeks away I have been looking for every possible place that I can to advocate the conference. In doing so, I have been finding lots of interesting tidbits of information. For example, did you know (per Stefan/Mastermind) PostgreSQL is lucky to reach 15k tps per core for **SIMPLE QUERIES** , whereas MySQL can do upward of 30k tps per core for **SIMPLE QUERIES**? There is no question that PostgreSQL is going to stomp all over MySQL for complex queries by the maturity of the PostgreSQL planner alone. The problem with PostgreSQL for simple queries is not our execution but is directly related to our parser. It seems there is definitely improvement to be made here. Is this low hanging fruit? Why haven't we fixed this? 

Next, [I read today that SourceForge is moving to MongoDB plus Python](<http://blog.pythonisito.com/2011/03/allura-open-source-forge.html>). Once upon a time Sourceforge was a big time PostgreSQL shop. Now it is not uncommon for a company to chose different platforms. It is also not uncommon for people to move from or to PostgreSQL. However, this is different. 

For a company like SourceForge who has been embedded in the traditional web world for so many years to migrate wholesale to an entirely new platform which isn't even similar to their existing platform is telling. Most companies may migrate from MySQL to PostgreSQL (this makes sense) but from a fully relational, ACID compliant database to MongoDB? That is a paradigm shift and it marks what I think is an upcoming opportunity for our community. 

I have been working with 10Gen, the creators of MongoDB for the past couple of months because of PostgreSQL Conference. They even have a training and full track within #PgEast. Generally speaking, MongoDB users are not database people, they are application developers. This is why I wanted MongoDB to be present. I wanted the cross pollination of ideas, hoping that the two platforms could come together and provide a productive discourse for both sides. 

It is no secret that there is many more application developers in the market than database people and this is where the problem lays. If the majority of people doing the actual development are pushing toward technologies that makes their lives easier then the old and crufty relational database is going to lose out. Certainly PostgreSQL and other relational databases aren't going anywhere but it is important to recognize growing trends, learn from them and try to find a way to monopolize on them. 

  * What if there was a NoSQL like grammar for defining relations in PostgreSQL? 
  * Since many of the queries you would do in NoSQL are very simple, what if we solved that parser problem? 
  * What if you could replicate from/to PostgreSQL and MongoDB, taking advantage of various strengths of each?



And with that, I am going to pimp [The PostgreSQL Conference](<http://www.postgresqlconference.org/>) again. For what should be obvious reasons (it is in 12 days) we are in the final stretch of what is going to be the largest PostgreSQL conference in the Western World. If you do a little bit of legwork (GGIYF) you can even find some pretty hefty discounts to the conference. 

Oh and don't forget to follow the conference on twitter [@postgresconf](<http://www.twitter.com/postgresconf/>) and the hash tag is #PgEast.

---
[View this page online](https://www.commandprompt.com/blog/nosql__is_there_a_threat/)

---

# #PgEast session schedule is up

> The session schedule is now up. We also have a new twitter account for the conference. Further, EFF has also offered a discounted membership for #PgEast attend…

[The session schedule is now up.](<https://www.postgresqlconference.org/>) We also have a [new twitter account for the conference.](<http://twitter.com/postgresconf>) Further, EFF has also offered a discounted membership for #PgEast attendees, [more information can be found here.](<https://www.postgresqlconference.org/content/pgeast-2011-eff-membership>) Of course you can [register in full here.](<https://www.postgresqlconference.org/register>)

---
[View this page online](https://www.commandprompt.com/blog/pgeast_session_schedule_is_up/)

---

# #PgEast Training Schedule is up

> The training (not sessions) schedule is up for #PgEast trainings. You can get it
right off the front page. We are running 7 sessions in parallel with a total …

The training (not sessions) schedule is up for #PgEast trainings. You can get it [right off the front page. We are running 7 sessions in parallel with a total of 9 trainings.](<https://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/pgeast_training_schedule_is_up/)

---

# Grant schema usage to 2500 users? No can do!

> It all started with a help request from a someone on IRC: he has about 2500 roles, and all of them have been granted USAGE privileges on a schema.  He went on …

It all started with a help request from a someone on IRC: he has about 2500 roles, and all of them have been granted USAGE privileges on a schema. He went on to create a bunch more and grant the same privilege, but it failed:
    
    
    CREATE ROLE some_user_2501;
    GRANT USAGE on schema genetics to some_user_2501;
    
    ERROR:  row is too big: size 8168, maximum size 8164
    

Oops.

Now, let this be said: this is wrong design. It causes slowness, due to the way those privileges are stored. A much better way to go about this is to create a single role, grant the privileges to that role, and the grant that role to all other roles. So:
    
    
    CREATE ROLE genetic_reader;
    GRANT USAGE ON schema genetics TO genetic_reader;
    GRANT genetic_reader TO some_user_0001, some_user_0002, ...;
    

That said, there is always people who want to do things their own way, and so this answer isn't enough. They want to know how to make their original GRANT statement work. Here's how.

The reason it fails, as the message says, is that the row is too big. Supposedly, we have solved this problem in Postgres by using TOAST tables: when attributes get too large, they are compressed and sent to chunked storage to the toast table. This works fine ... as long as there **is** a toast table to start with. Turns out that not all system catalogs have one.

This is the list of system catalogs with ACL columns in them, and the OID of their toast table. If the OID is zero, it means it has no toast table and thus they will cause failures in case someone tries to grant privileges to umpteen users.
    
    
    select relname, reltoastrelid
      from pg_class
     where oid in (
            select attrelid
              from pg_attribute
             where (attname like '%acl' and atttypid = 'aclitem[]'::regtype) or
                   (attname like '%options' and atttypid = 'text[]'::regtype))
           and relkind = 'r';
    

relname | reltoastrelid  
---|---  
pg_attribute | 0  
pg_default_acl | 0  
pg_largeobject_metadata | 0  
pg_pltemplate | 0  
pg_database | 2844  
pg_tablespace | 0  
pg_class | 0  
pg_proc | 2836  
pg_foreign_data_wrapper | 0  
pg_namespace | 0  
pg_foreign_server | 0  
pg_user_mapping | 0  
pg_language | 0  
  
(13 rows)  


(I have also added "options" columns, because those could also cause problems, though the number of possible options is limited, so this is unlikely to cause any problems in practice.)

Notice that of those, only `pg_proc` and `pg_database` catalogs have toast tables. Having it for `pg_proc` is understandable: that's the catalog where function source code is stored, and that tends to get large, frequently. But `pg_database`? The only explanation is that someone got bit by the limitation on granting CONNECT privileges to a large number of roles. So it follows that all the remaining system catalogs should be modified in this way, too.

To work around this limitation, you can manually create a TOAST table to the system catalog. To do this, you need to start the server in a special mode that lets you modify the system catalogs:
    
    
    postgres -O
    

Connect to it, and do something like this:
    
    
    ALTER TABLE pg_namespace ADD COLUMN foo text;
    ALTER TABLE pg_namespace DROP COLUMN foo;
    

Then stop the server and restart it normally. Now pg_namespace, the system catalog where schema permissions are stored, has a TOAST table and you can issue all those thousands of `GRANT .. ON SCHEMA` you've always wished (yeah, right).

While this is not recommended, I wonder if we should go ahead and fix the problem by having the system automatically create toast tables on those system catalogs.

What do you think?

---
[View this page online](https://www.commandprompt.com/blog/grant_schema_usage_to_2500_users_no_can_do/)

---

# The hash code is: #PgEast (want 30% off?)

> It is 21 days to PostgreSQL Conference East (#PgEast), which is set once again to break attendance records of all the western world conferences. Hosted in NYC,…

It is 21 days to PostgreSQL Conference East (#PgEast), which is set once again to break attendance records of all the western world conferences. Hosted in NYC, we have large number of sessions, over 60 speakers, a full day of trainings, an excellent NYCPug meeting at the event, and an excessive number of sponsors (nahh... we need 3x more, sponsors ROCK!). I am truly humbled at the amazing level of positive response we have received for hosting PgEast in NYC. CMD and the conference has had so much support from the community we are considering making NYC a permanent home for #PgEast. 

I have been [going over the list of talks](<https://www.postgresqlconference.org/2011/east/talks>) wondering which I am going to visit or possibly even record. We definitely will not be recording them all this time. Here are a couple (outside of the [Foursquare](<https://www.foursquare.com/>) talk that I want to see: 

  * [Streaming databases: stepping outside of Postgres](<https://www.postgresqlconference.org/content/streaming-databases-stepping-outside-postgres>)
  * [Getting Started with PL/Proxy](<https://www.postgresqlconference.org/content/getting-started-plproxy>)

Theo Schlossnagle is giving the Streaming databases talk. Theo is always a speaker to attend. He explores interesting topics and as I have no professional experience with Streaming databases, I am excited to see what he has to offer. 

.Org core member Peter Eisentraut is giving the PL/Proxy talk. I gave a talk on Pl/Proxy at West 2007. I am excited to see how far PL/Proxy has come in the last 3.5 years. 

Of course thank you to all of our sponsors: 

  * [EnterpriseDB](<http://www.enterprisedb.com/>)
  * [10Gen](<http://www.10gen.com/>)
  * [Braintree](<http://www.braintreepaymentsolutions.com/>)
  * [Continuent](<http://www.continuent.com/>)
  * [Credativ](<http://www.credativ.com/>)
  * [EnovaFinancial](<http://www.enovafinancial.com/>)
  * [OpenSCG](<http://www.openscg.com/>)
  * [2ndQuadrant](<http://www.2ndquadrant.us/>)
  * [OmniTI](<http://www.omniti.com/>)
  * [OpenHosting](<http://www.openhosting.com/>)
  * [SQL Manager](<http://www.sqlmanager.net/>)



Now, if you read all the way do to the bottom of this post, the first 25 people that register with the [coupon code 21DAYSALE will receive 30% off the registration](<https://www.postgresqlconference.org/register>) to #PgEast .

---
[View this page online](https://www.commandprompt.com/blog/the_hash_code_is_pgeast_want_30_off/)

---

# Changes in PL/Perl

> 
I have been disappointed for a long time with the way PL/Perl handles array arguments. For example, let&#x27;s consider a simple Perl function that takes a value …

I have been disappointed for a long time with the way PL/Perl handles array arguments. For example, let's consider a simple Perl function that takes a value and a list and checks whether the value is present in the list.
    
    
    CREATE FUNCTION check_values
    {
        my $val = shift;
        my $aref = shift;
    	
        foreach (@$aref) {
            return true if $val eq $_ 
        }
        return false;
    }
    

A practical use for this function would be a CHECK constraint ensuring that only a limited set of value can be assigned to a particular column (of course, in real life one can as well use [enums](<http://www.postgresql.org/docs/current/static/datatype-enum.html>)).

Even when the function itself is very simple there's no way to translate it directly into the PL/Perl code for PostgreSQL 9.0 and below. The main obstacle to such translation is the conversion of input arguments to strings in PL/Perl functions. This means that an input array of '{1,2,3,4}', passed into a PL/Perl function, will be accessible as a string literal '{1,2,3,4}' and not as an array of 4 elements.

In the past, one way to handle that was writing Perl code to parse the array represented as a string:
    
    
    CREATE OR REPLACE FUNCTION check_values(TEXT, TEXT[]) RETURNS BOOLEAN AS
    $fn$
        my $val = shift;
        my $list = shift;
        $list =~ s/^{(.*)}$/\1/;
        foreach (split /,/, $list) {
            return true if $_ eq $val;
        }
        return false;	
    $fn$ LANGUAGE plperl;
    
    SELECT check_values('a', '{a,b,c,d}');
    check_values 
    --------------
     t
    (1 row)
    

While this code works for simple cases, it fails for more complex ones, such as when the array argument has more than one dimension, or one of the elements contains a comma:
    
    
    SELECT check_values('a,b,c', ARRAY['a,b,c','e,f,g']);
     check_values 
    --------------
     f
    (1 row)
    

I thought that PL/Perl should be smarter on handling the input arguments, and the changes I was working on, which have been submitted [as a patch](<https://commitfest.postgresql.org/action/patch_view?id=491>) for the [current commitfest](<https://commitfest.postgresql.org/action/commitfest_view?id=9>), teach PL/Perl to handle input arrays properly. Here's how the check function would look with this patch applied.
    
    
    CREATE OR REPLACE FUNCTION check_values (TEXT, TEXT[]) RETURNS BOOLEAN AS 
    $fn$
        my $val = shift;
        my $aref = shift;
    	
        foreach (@$aref) {
            return true if $val eq $_;
        }
        return false;
    $fn$ LANGUAGE plperl; 
    
    SELECT check_values('a,b,c', ARRAY['a,b,c','e,f,g']);
     check_values 
    --------------
     t
    (1 row)
    

Alex Hunsaker did a great review by not only providing valuable comments and bug fixes, but also by extending the patch to generate both a reference and a string representation of array arguments, depending on whether or not they are used in a string context, so the changes won't break existing PL/Perl code. Additionally, he enabled SPI functions in PL/Perl to receive composite type and array arguments directly as Perl hash or array references, without converting them to a string first:
    
    
    CREATE TYPE foo AS (bar int, baz int);
    CREATE TYPE
    DO $$
        my $x = {bar => 9, baz => 1}; # composite type represented as a hash ref
        my $plan = spi_prepare('SELECT $1 as foo','foo'); 
        my $rv = spi_exec_prepared($plan, {}, $x); 
        elog(NOTICE, $rv->{rows}->[0]->{foo}->{bar}); 
    $$ LANGUAGE plperl;
    
    NOTICE:  9
    CONTEXT:  PL/Perl anonymous code block
    DO
    

I look forward for this functionality to be added to 9.1 and to work on other useful features for PL/Perl and PostgreSQL.

---
[View this page online](https://www.commandprompt.com/blog/changes_in_plperl/)

---

# PgEast: Talks up and Registration open!

> That&#x27;s right folks, the PostgreSQL Conference East has listed 98% of its talks. We have a lot of great talks, mini-tutorials and trainings. 

A simple agenda…

That's right folks, the [PostgreSQL Conference East has listed 98% of its talks](<https://www.postgresqlconference.org/2011/east/talks>). We have a lot of great talks, mini-tutorials and [trainings.](<https://www.postgresqlconference.org/register>)

A simple agenda follows: 

  * March 22nd is training day.   
Trainings range from 199.00 to 349.00 depending on half or full day. 
  * March 23rd - 25th is the conference.   
The registration is 249.00 

In particular I am interested to see how [Four Square](<http://www.foursquare.com/>) is using MongoDB and PostgreSQL to compliment each other. 

I also want to give a shout out to all of our very gracious sponsors. This has been a banner year for supporting the conference. It is great to see how we are growing! 

  * [EnterpriseDB](<http://www.enterprisedb.com/>)
  * [10Gen](<http://www.10gen.com/>)
  * [Braintree](<http://www.braintreepaymentsolutions.com/>)
  * [Continuent](<http://www.continuent.com/>)
  * [EnovaFinancial](<http://www.enovafinancial.com/>)
  * [OpenSCG](<http://www.openscg.com/>)
  * [2ndQuadrant](<http://www.2ndquadrant.us/>)
  * [OmniTI](<http://www.omniti.com/>)
  * [OpenHosting](<http://www.openhosting.com/>)
  * [SQL Manager](<http://www.sqlmanager.net/>)

---
[View this page online](https://www.commandprompt.com/blog/pgeast_talks_up_and_registration_open/)

---

# PgEast: CFP closes, TODAY!

> Alright folks, last call. It is beer thirty. CFP closes today. Let&#x27;s get those talks in:

Submit Talk to PgEast

Alright folks, last call. It is beer thirty. CFP closes today. Let's get those talks in: 

# [Submit Talk to PgEast](<https://www.postgresqlconference.org/talk_types>)

---
[View this page online](https://www.commandprompt.com/blog/pgeast_cfp_closes_today/)

---

# PgEast: 2011 CFP closes in 3 days!

> Alright slackers, you know who you are. The constant presence at every conference. The speaker, that submits their talk at 11:59PM before the CFP closes, I am …

Alright slackers, you know who you are. The constant presence at every conference. The speaker, that submits their talk at 11:59PM before the CFP closes, I am talking to YOU! In three days, the CFP for what is going to be the largest PostgreSQL Conference in the Western World to date (I say Western because JPUG kicks U.S. butt in attendance just at their user meetings alone), is going to close. 

We will then start an accelerated process to approve those worthy! 

Perhaps you are not one of those I speak of, you are not a slacker. You are just a person who would like to speak but you are not sure if you have a decent topic to speak on. If that is the case, email me: 
    
    
    jd < at > commandprompt < . > com

I will be happy to help you. 

Perhaps you have never spoke before. If you haven't, the PostgreSQL Conference is a great place to start. We are a friendly community that is helpful. Let us be your first jump into the world of conference speaking! 

No matter your reason, now is the time to get those talks in! 

[PostgreSQL Conference East](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/pgeast_2011_cfp_closes_in_3_days/)

---

# MongoDB at PgEast.... say what?

> I was surprised at first too but I have been talking to quite a few community members for MongoDB and due to the positive responses, PostgreSQL Conference East…

I was surprised at first too but I have been talking to quite a few community members for MongoDB and due to the positive responses, PostgreSQL Conference East is going to be host to the excellent MongoDB community. 

> JD, Why would you do this? Why do we care? We are relational, they -- well I don't know what they are. 

One of the goals of [The PostgreSQL Conference Series](<http://www.postgresqlconference.org/>) is the expand the knowledge of the community and to extend a hand to secondary communities, inviting them learn, collaborate and drink with us. By inviting MongoDB, we are doing exactly that. It is my sincerest hope that we can get a lot of the MongoDB users to better understand our ways, as cranky and old-school as they may be and in return, we will learn some of their ways, perhaps making PostgreSQL even better. 

Consider, what if our upcoming SQL/MED support in 9.1 had a foreign data wrapper that was optimized for MongoDB? 

Remember folks, [CFP is still open](<https://www.postgresqlconference.org/talk_types>)

And of course, many thanks to the PostgreSQL Conference Sponsors: 

  * Command Prompt, Inc. (Us) 
  * [EnterpriseDB](<http://www.enterprisedb.com/>)
  * [Continuent](<http://www.continuent.com/>)
  * [2nd Quadrant](<http://www.2ndquadrant.com/>)
  * [SQL Manager](<http://www.sqlmanager.net/>)

---
[View this page online](https://www.commandprompt.com/blog/mongodb_at_pgeast_say_what/)

---

# PostgreSQL vs MySQL @ Oracle NYC Head Quarters NYC (my brain just broke)

> In my quest to insure an incredible turnout for PostgreSQL Conference, I contacted the MySQL meetup group in NYC. Of course my reasons were simple, I want MySQ…

In my quest to insure an incredible turnout for [PostgreSQL Conference](<http://www.postgresqlconference.org/>), I contacted the MySQL meetup group in NYC. Of course my reasons were simple, I want MySQL people to show up and see the value of PostgreSQL. However, I learned a couple of new things. 

  * There is a PHP [framework called Vork](<http://www.vork.us/>) that supports PostgreSQL. 
  * Ed Boyajian of [EnterpriseDB](<http://www.enterprisedb.com/>) (the new [Drupal](<http://www.drupal.org/>) Enterprise [PostgreSQL](<http://www.postgresql.org/>) [Company](<http://www.commandprompt.com/>)) gave a talk on PostgreSQL vs MySQL @ the Oracle NYC Head Quarters. The video of which is [available here.](<http://www.leadit.us/hands-on-tech/PostgreSQL-vs-MySQL-Pros-Cons>)



I have seen Ed speak on occasion at [East and West.](<http://www.postgresql.org/>) He has some interesting (if not so technical points) he makes in the video. I will let you folks analyze it for your own edification. One thing I didn't know was Ed's relationship to the failed [Red Hat Database](<http://sourceware.org/rhdb/>) initiative (which makes sense, not the failure but why he is involved in PostgreSQL). The failure of Red Hat Database was simple, they were trying to charge 1995.00 (or was it 2995.00?) for PostgreSQL 7.1. Red Hat Database was based on PostgreSQL and essentially caused the death of Great Bridge (yeah..... how many of you have been around long enough to remember that?). Great Bridge once employed Tom Lane and Bruce Momjian. Red Hat now employs Tom Lane and EnterpriseDB now employs Bruce Momjian. Wrap your heads around that chaos theory. 

Of course [The PostgreSQL Company](<http://www.commandprompt.com/>) has been around longer than any of the other "initiatives" and remains independent, debt and V.C. free. Is this a great time to be alive or what? Let's rock!

---
[View this page online](https://www.commandprompt.com/blog/postgresql_vs_mysql__oracle_nyc_head_quarters_nyc_my_brain_just_broke/)

---

# Fixing foreign key deadlocks  submitted

> A week ago, I submitted my patch to fix the foreign key lock problem. What I propose is almost exactly what was described in my previous blog posts, with a cou…

A week ago, [I submitted my patch](<http://archives.postgresql.org/message-id/1294953201-sup-2099@alvh.no-ip.org>) to fix the foreign key lock problem. What I propose is almost exactly what was described in my previous blog posts, with a couple of differences.

The first is that I decided to only check unique indexes, not all indexes. This is good because you can have other indexes for performance and they will not affect locking for foreign keys. I noticed that it could be done easily without performance impact, and it had been requested by at least two independent people.

(For the hardcore hackers among you, the way I did this was by adding a second bitmapset to the relcache RelationData struct, which lists columns part of unique indexes. This second bms is computed in parallel of the bms used to do the HOT checks, and both are cached at the same time in the relcache entry, and the uniqueness info was already available there, so there are no extra catalog lookups to do this.)

The other difference, as I commented on [a previous post](<http://www.commandprompt.com/blogs/alvaro_herrera/2010/11/fixing_foreign_key_deadlocks_part_2__revisited/>), is that `FOR KEY LOCK` does not conflict with `FOR SHARE`. This shouldn't be too problematic, although there is one catch: if a tuple is share-locked, and then there's a constant stream for key-lockers, someone trying to update the tuple might be locked out for a long time, even if the share-locker goes away.

Now the patch is waiting for review on [the commitfest](<https://commitfest.postgresql.org/action/commitfest_view?id=9>). If you have a pet test case that could be affected by this patch, please try it out and let me know your thoughts and/or results.

---
[View this page online](https://www.commandprompt.com/blog/fixing_foreign_key_deadlocks__submitted/)

---

# PgEast: 2011, Second call for papers!

> January 18th, 2011: Celebrating 15 years of PostgreSQL, early.

That&#x27;s right folks, it is time for second call. Content is being submitted steadily. At PgWes…

January 18th, 2011: Celebrating 15 years of PostgreSQL, early. 

That's right folks, it is time for second call. Content is being submitted steadily. At PgWest last year, we received well over our capacity of content and we would like to keep that trend going. 

The PostgreSQL Conference for Developers,End Users and Decision Makers, is being held at the Hotel Pennsylvania,in New York City from March 22nd through 25th 2011. Please join us in continuing to make this the largest PostgreSQL Conference series! 

  * [PostgreSQL Conference](<http://www.postgresqlconference.org/>)
  * [Call for papers](<https://www.postgresqlconference.org/talk_types
>)

**Thank you to our sponsors:**  


  * [Command Prompt, Inc.](<http://www.commandprompt.com/>)
  * [EnterpriseDB](<http://www.enterprisedb.com/>)

**Time line:**   


> Dec 16th: Talk submission opens  
>  Feb 10th: Talk submission closes  
>  Feb 15th: Speaker notification  
> 

This year we will be continuing our trend of covering the entire PostgreSQL ecosystem. We would like to see talks and tutorials on the following topics: 
    
              * General PostgreSQL: 
                  * Administration 
                  * Performance 
                  * High Availability 
                  * Migration 
                  * GIS 
                  * Integration 
                  * Solutions and White Papers 
          * The Stack: 
                  * Python/Django/Pylons/TurboGears/Custom 
                  * Perl5/Catalyst/Bricolage 
                  * Ruby/Rails 
                  * Java (PLJava would be great)/Groovy/Grails 
                  * Operating System optimization
                    (Linux/FBSD/Solaris/Windows) 
                  * Solutions and White Papers

---
[View this page online](https://www.commandprompt.com/blog/pgeast_2011_second_call_for_papers/)

---

# Recent Updates to postgres.js

> We&#x27;ve been a bit quiet on the postgres.js front lately, but there&#x27;s a couple of exciting new announcements that we&#x27;d like to go over with Postgres.js

Firstl…

We've been a bit quiet on the postgres.js front lately, but there's a couple of exciting new announcements that we'd like to go over with Postgres.js Firstly, we've plugged in LISTEN/NOTIFY support. This is huge, as it allows you to register asynchronous callbacks based on events from Postgres, outside of any transactional context. Additionally, as of PG 9.0, NOTIFY messages from the Postgres server can contain an arbitrary text payload. Combined with JSON parsing in Node, you can easily pass formatted objects from Postgres to your application code, without an intermediate query stage. Here's an example from our test case on how to use it: 
    
    
    var pg = require("postgres");
    
    var db = new pg.connect("pgsql://test:12345@localhost:5432/template1");
    var db2 = new pg.connect("pgsql://test:12345@localhost:5432/template1");
    
    // Request notification for "test" messages
    
    db.notify("test", function (err, payload) {
        // I got a payload!
        console.log(payload);
    });
    
    // On connection, run the notification.
    
    db2.on("connection", function () {
        db2.query("NOTIFY test 'myPayload'", function (err,rs) {}); // Null
        db2.close();
    });
    db.close();
    
    

Which, on 9.0, will have the callback called with "payload." Pre 9.0, you'd get an error on the NOTIFY command, and a blank string for the payload contents. 

### Empty resultsets

Next up, we fixed the bug whereby an empty resultset from a SELECT statement (or really any statement) would throw an error. Now, if you get an empty set, your callback will receive a zero-length array, just like you'd expect: 
    
    
    var pg = require("postgres");
    
    var db = new pg.connect("pgsql://test:12345@localhost:5432/template1");
    db.query("SELECT * FROM empty_table;", function (err, rs) {
        console.log(rs.length); // will be 0
    });
    db.close();
    

### REPL support, and the "connection" event

Finally, the last big thing is we cleared up is the driver bug where, after the initial connection, new query events weren't getting executed, if the internal query buffer was ever drained. This would cause the driver to appear to hang, and was pretty much a major, show-stopping bug. Fortunately, this issue has now been fixed - Draining the event buffer will now have newly added items re-start the drain, and all queries buffered afterwards will be run on the wire, as expected. This should resolve any lingering effects or bugs with queries making it to PG. Additionally, to take advantage of and test this, you can listen for the "connection" event from the driver: 
    
    
    var db = new pg.connect("pgsql://test:12345@localhost:5432/template1");
    db.on("connection", function () {
        db.query("SELECT 1::int", function (err, rs, tx) {
            // err should be null
            console.log(eq(err, null));
            // Test if the returned value is what we think it is.
            console.log(eq(rs[0]['int4'], 1));
        });
        db.close();
    });
    

With these latest fixes, we've inched forward to Release Candidate 2 - the driver should be just about stable enough for production use. As always, you can get it at: <https://github.com/commandprompt/postgres-js> and report bugs at <https://public.commandprompt.com/projects/postgresjs>

---
[View this page online](https://www.commandprompt.com/blog/recent_updates_to_postgresjs/)

---

# PgEast 2011: NYC Call for papers

> December 16th, 2010: Celebrating 15 years of PostgreSQL, early.

Following on the smashing success of PostgreSQL Conference West,
PostgreSQL Conference West…

December 16th, 2010: Celebrating 15 years of PostgreSQL, early. 

Following on the smashing success of PostgreSQL Conference West, PostgreSQL Conference West, The PostgreSQL Conference for Developers, End Users and Decision Makers, is being held at the Hotel Pennsylvania, in New York City from March 22nd through 25th 2011. Please join us in continuing to make this the largest PostgreSQL Conference series! 

  * [PostgreSQL Conference](<http://www.postgresqlconference.org/>)
  * [Call for papers](<https://www.postgresqlconference.org/talk_types
>)

**Thank you to our sponsors:**  


  * [Command Prompt, Inc.](<http://www.commandprompt.com/>)
  * [EnterpriseDB](<http://www.enterprisedb.com/>)

**Time line:**   


> Dec 16th: Talk submission opens  
>  Feb 10th: Talk submission closes  
>  Feb 15th: Speaker notification  
> 

This year we will be continuing our trend of covering the entire PostgreSQL ecosystem. We would like to see talks and tutorials on the following topics: 
    
              * General PostgreSQL: 
                  * Administration 
                  * Performance 
                  * High Availability 
                  * Migration 
                  * GIS 
                  * Integration 
                  * Solutions and White Papers 
          * The Stack: 
                  * Python/Django/Pylons/TurboGears/Custom 
                  * Perl5/Catalyst/Bricolage 
                  * Ruby/Rails 
                  * Java (PLJava would be great)/Groovy/Grails 
                  * Operating System optimization
                    (Linux/FBSD/Solaris/Windows) 
                  * Solutions and White Papers

---
[View this page online](https://www.commandprompt.com/blog/pgeast_2011_nyc_call_for_papers/)

---

# R.I.P. PostgreSQL (Mammoth) Replicator

> In 2004, PostgreSQL Core Team member Josh Berkus wrote[1]:

&quot;Slony-I is undoubtedly our most popular replication tool.   It supports Master-Slave High Availa…

In 2004, PostgreSQL Core Team member Josh Berkus wrote[1]: 

"Slony-I is undoubtedly our most popular replication tool. It supports Master-Slave High Availability Replication. However, there are a number of other solutions, such as dbMirror, eRServer, pgPool, C-JDBC, and the proprietary Mammoth Replicator, all of which are in wide use because they solve different replication problems than Slony-I does. Replication is not a single solution for a single problem; it is several solutions for a wide array of different problems. That's why no one replication tool will ever be the "default" replication for PostgreSQL." 

I believed well before then it was a fallacy and a bad community decision to not put support behind a single, integrated solution. I also believe it has been one of the single most important policy failures of the .Org community and has lead PostgreSQL to grow much more slowly than it otherwise could have. 

From a business standpoint it opened the door for many other solutions, a lot of learning experiences and a lot of professional services consulting (Thank you: Slony). It also opened the door for the only solution to look at being integrated into Core. Mammoth PostgreSQL Replicator (Replicator). 

Replicator opened the door for CMD in many ways. Although it was never a huge commercial success we did have early customers (Cisco) and there was quite a few deployments over time. Eventually, we Open Sourced Replicator hoping to generate some external interest, and although quite a few hackers talked to me about participating, none of it actually materialized into anything useful. 

To this day, nothing can touch the usability of Replicator for PostgreSQL replication. It is the easiest to configure, the easiest to run, the easiest to manage. Alas that is not enough, as we needed to re-architect to eliminate the one single point of failure (as well as some other issues, crash safety I am looking at you). Further with the emergence of the Hot Standby technology that is in 9.0, the need for Replicator has become even less. 

Although there were design decisions originally made that were incorrect, I still believe that the overall architecture of Replicator was sound. Implementation, perhaps not but architecture yes. I also believe that the in development version (1.9) would have been a game changer as a whole. Unfortunately we were not able to execute for a number of reasons that don't really matter anymore. 

Everyone who worked on replicator should be proud of what they did. It should be looked on as a learning experience. We built something, nobody else did, even now. We built integrated and flexible PostgreSQL replication. Was it perfect? No. Should we have open sourced it sooner and tried harder to integrate it into the community? Probably. Were there design decisions that should have been different? Yes. Were there components we should have changed (MCP SPOF)? Yes. 

Of course, we can say all of that about the current state of PostgreSQL. Let alone Replicator, Slony or any other project. Just read -hackers. We are not perfect, but our team did something good. 

It took until 2010, 7 years? after Replicator first released for the community to figure out they were wrong. We were pioneers for PostgreSQL and our team should be proud of that. 

**R.I.P. PostgreSQL (Mammoth) Replicator (12/10/2010)**

1\. http://archives.postgresql.org/pgsql-advocacy/2004-11/msg00063.php

---
[View this page online](https://www.commandprompt.com/blog/rip_postgresql_mammoth_replicator/)

---

# Looking for an Intermediate Sysadmin + Junior DBA

> Command Prompt, Inc. is looking for an intermediate systems administrator and junior PostgreSQL administrator. 

Command Prompt has provided PostgreSQL suppo…

Command Prompt, Inc. is looking for an intermediate systems administrator and junior PostgreSQL administrator. 

Command Prompt has provided PostgreSQL support, development, and hosting since 1997. We are looking for another person to join our stellar group of PostgreSQL systems experts. 

We seek someone who has a deep knowledge of at least one UNIX-like system, and who knows how to manage heterogeneous systems well. You can demonstrate strong skills in basic systems administration. You have a clear understanding of how to administer several systems that are mostly the same, but that have small local differences. If you do not feel comfortable saying, "I'm not familiar with that in your environment," then reading the man page, and coming back with a test plan for deployment that will reveal problems with your strategy, this is not a job for you. The ability to imagine, propose, test, and deliver perfectly-integrated and easily-maintained solutions to users' problems is the key to success in this position. You work well in a team: you don't have to work 24 hours a day, because other people can always log into any system you maintain and know where everything is, how it got there, and how to add new things if they're needed. 

You must know basic PostgreSQL administration, and understand how to set up, operate, and tune Postgres in elementary ways, such as installing from a package manager. You do not have to be a PostgreSQL guru, but if you are, that is a bonus. 

You have systems administration capability with shell scripts, as well as either Perl or Python. As well as understanding (or quick to pick up) technologies such as DRBD and LVM2. 

You have an interest in working on varied projects that use varied (and sometimes legacy) technologies. 

Command Prompt is a professional services company. You will be interfacing with customers, therefore customer service and professionalism is key. 

Command Prompt employees usually work from their home offices. The position normally requires minimal travel. For this position, the successful candidate will be able to communicate effectively in English. English as a spoken second language is fine as long as the written skills are clear and effective. 

This is a remote position and does not require residence in the United States. 

Applicants should send a resume to Joshua D. Drake, jd(at)commandprompt(dot)com, with the words "intermediate administrator" in the Subject line. Please include any text by way of a cover letter in the body of your email and not as a separate attachment.

---
[View this page online](https://www.commandprompt.com/blog/looking_for_an_intermediate_sysadmin__junior_dba/)

---

# Automatically pulling into a committer's Git repository

> I was a bit unhappy because I couldn&#x27;t keep my &quot;bare&quot; Git repository up-to-date unattended — I needed to be at my workstation to be able to do a git fetch, bec…

I was a bit unhappy because I couldn't keep my "bare" Git repository up-to-date unattended -- I needed to be at my workstation to be able to do a `git fetch`, because it needs my SSH passphrase.

I didn't have this problem with CVS because I kept an rsync copy of the anonymous CVS repository, from which my regular trees where checked out. (My committer's checkouts were separate, which was annoying, but I considered that problem solved with the jump to Git.)

Yesterday I had an epiphany that this could be solved very easily: just add a new remote to the anonymous clone, which doesn't require any SSH key to be involved, and so can run unattended. This sounds quite trivial, but I couldn't make it work at first for reasons that appeared quite obscure; and indeed they were :-)

The full solution looks like this:
    
    
    git remote add anon-origin git://git.postgresql.org/git/postgresql.git
    

This adds the new remote, from which you can "git fetch anon-origin"; but while it will pick up the objects when you do, it won't update the branches. To make it update the branches, you have to fetch into each branch explicitely:
    
    
    git fetch anon-origin \
        master:master REL9_0_STABLE:REL9_0_STABLE \
        REL8_4_STABLE:REL8_4_STABLE REL8_3_STABLE:REL8_3_STABLE \
        REL8_2_STABLE:REL8_2_STABLE
    

Now I can have this in my crontab and be confident that the repository will be always reasonably up to date.

Why this doesn't work without this trick is beyond me, but I don't really care all that much. I'm not into Git internals enough, it seems (and I don't think I want to be anyway).

Of course, non-committers don't have this problem, because they can always run "git fetch" or "git pull" without worrying about being asked for a passphrase.

---
[View this page online](https://www.commandprompt.com/blog/automatically_pulling_into_a_committers_git_repository/)

---

# Fixing foreign key deadlocks, part 2  revisited

> While trying to implement SELECT FOR KEY LOCK at the lock manager level, I stumbled across the problem that I need to represent the lock faithfully in the lock…

While trying to implement `SELECT FOR KEY LOCK` at the lock manager level, I stumbled across the problem that I need to represent the lock faithfully in the lock manager's terms. And since I previously mentioned that `FOR KEY LOCK` would conflict with `FOR SHARE`, I get in trouble -- it's not easy to see which lock mode to use (if there is one, which I doubt).

So I revisited that decision: a `FOR KEY LOCK` does not conflict with `FOR SHARE`, and this allows them to use the same ShareLock mode.

This has two consequences: 

  1. After the tuple is locked by two transactions or more in the two different modes, there's no way to figure out which one has which lock.
  2. The `HEAP_XMAX_SHARED_LOCK` infomask bit needs to be carried forward in an `UPDATE`, just like `HEAP_XMAX_KEY_LOCK` bit was going to be.



None of these is a problem, as far as I can see. Just a little bit different. But the basic fact that `FOR SHARE` and `FOR KEY LOCK` do not conflict could take someone by surprise.

---
[View this page online](https://www.commandprompt.com/blog/fixing_foreign_key_deadlocks_part_2__revisited/)

---

# Fixing foreign key deadlocks, part 2

> In the previous article,
I explained the problem with foreign key checks checks obtaining
too strong of a lock, and promised that we would be attempting to fix…

In the [previous article](<http://www.commandprompt.com/blogs/alvaro_herrera/2010/11/fixing_foreign_key_deadlocks/>), I explained the problem with foreign key checks checks obtaining too strong of a lock, and promised that we would be attempting to fix it.

Here is my proposal: 

  1. Create a new `SELECT` locking clause. For now, we're calling it `SELECT FOR KEY LOCK`
  2. This will acquire a new type of lock in the tuple, dubbed a "keylock". 
  3. This lock will conflict with `DELETE`, `SELECT FOR UPDATE`, and `SELECT FOR SHARE`. 
  4. It also conflicts with `UPDATE` if the `UPDATE` modifies an indexed attribute. 



That's the gist of it. The end effect is that you are allowed to UPDATE a tuple that's being used in a foreign key check, as long as you don't change any indexed columns.

This idea was suggested by [Simon Riggs](<http://archives.postgresql.org/message-id/1282730008.3865.47.camel@ebony>) in the pgsql-hackers thread referenced in my previous article, and further debugged and improved by the developers in the ensuing discussion to a reasonably workable level — though it remains ticklish.

The interesting implementation details are: 

  1. We need to use a new bit in t_infomask. `0x0010` is currently unused so we will grab that. 
  2. Key-locking a tuple means setting the `XMAX_KEY_LOCK` bit, and setting the Xmax to the locker. If the tuple is already key-locked, a MultiXactId needs to be created from the original locker(s) and the new transaction. 
  3. The original tuple needs to be marked with the Cmax of the locking command, to prevent it from being seen in the same transaction. 
  4. A non-conflicting update to the tuple must carry forward some fields from the original tuple into the updated copy. Those include `Xmax`, `XMAX_IS_MULTI`, `XMAX_KEY_LOCK`, and the `CommandId` and `COMBO_CID` flag. 



If you're curious about also carrying forward `COMBO_CID`: at first I thought this wasn't necessary, because the only transaction that might care about those bits is the one creating the tuple, thus no transaction can do the necessary UPDATE. However, if a transaction creates the tuple, then modifies it in a subtransaction, then aborts the subtransaction, then key-locks the tuple, and finally updates it again, the last version of the tuple needs to have the correct `CommandId` information. This is fairly corner case and I would be surprised to see it happen in reality. But this is no excuse for not supporting the case.

(Offhand, I don't see any other fields that need to be carried forward, but I'm open to the possibility that I'm missing some.)

Note that the lock would be even more granular if instead of checking for an attribute of any index, we were to check for the particular `UNIQUE` index that implements the foreign key being verified. We choose not to do that for now, because it brings excessive modularisation breakage and possibly extra locking considerations.

---
[View this page online](https://www.commandprompt.com/blog/fixing_foreign_key_deadlocks_part_2/)

---

# Fixing foreign key deadlocks

> I&#x27;ve been commissioned to work on foreign keys.  More specifically, on the problem that when foreign keys are verified, they sometimes obtain locks that are st…

I've been commissioned to work on foreign keys. More specifically, on the problem that when foreign keys are verified, they sometimes obtain locks that are stronger than really needed. This causes some operations to block unnecessarily and, perhaps more aggravating, some other operations to deadlock.

This problem has been known for a very long time, and it affects many users to varying degrees. The most recent detailed discussion about this problem took place on [August 2010 on pgsql-hackers](<http://archives.postgresql.org/message-id/AANLkTimo9XVcEzfiBR-ut3KVNDkjm2Vxh+t8kAmWjPuv@mail.gmail.com>).

To recapitulate on this problem a bit: in the aboriginal code, foreign key checks obtained `FOR UPDATE` locks on referenced tuples, meaning that they were exclusively locked for the duration of the transaction doing the check. This was so strong a lock that it had a severe impact to the performance of applications that expected to concurrently access and modify tables with foreign key relationships. Consequently, many people used to drop their foreign keys just to get a reasonable concurrency level.

We partly fixed this by introducing `SELECT FOR SHARE` in 8.1, which allowed checks to be run concurrently. This had an enormous positive impact to concurrency, so people then began to use foreign keys more extensively.

But when you start raising the load level, at some point another problem becomes apparent: the locks taken are a stronger than strictly necessary, causing pauses and sometimes deadlocks.

Joel Jacobson of Glue Finance illustrated it with an example in the post referenced above, which can be seen in action in [this screencast](<http://screencast.com/t/NTk2Y2VhMW>). His test case was this: 
    
    
    DROP TABLE B;
    DROP TABLE A;
    
    CREATE TABLE A (
    AID integer not null,
    Col1 integer,
    PRIMARY KEY (AID)
    );
    
    
    CREATE TABLE B (
    BID integer not null,
    AID integer not null,
    Col2 integer,
    PRIMARY KEY (BID),
    FOREIGN KEY (AID) REFERENCES A(AID)
    );
    
    INSERT INTO A (AID) VALUES (1);
    INSERT INTO B (BID,AID) VALUES (2,1);
    
    Process 1:                             Process 2:
    BEGIN;
                                           BEGIN;
    UPDATE A SET Col1 = 1 WHERE AID = 1;
                                           UPDATE B SET Col2 = 1 WHERE BID = 2;
    UPDATE B SET Col2 = 1 WHERE BID = 2;
                                           UPDATE B SET Col2 = 1 WHERE BID = 2;
    

In Joel's example, he was getting an unexpected deadlock when session 2 updated the row the second time. Why, he asked, wasn't the process getting blocked the first time around? His initial explanation was incorrect, but the underlying reason for his problem was that that transaction was getting a shared lock on the referenced row (the one on table A), which it really didn't need except to ensure that the row didn't go away -- that is, to make sure the foreign key constraint remained satisfied until it could commit.

Put simply, certain operations are blocked when there is no need for it. Consider this simple example:  
Session 1: 
    
    
    CREATE TABLE foo (a int PRIMARY KEY, b text);
    CREATE TABLE bar (a int NOT NULL REFERENCES foo);
    INSERT INTO foo VALUES (42);
    
    BEGIN;
    INSERT INTO bar VALUES (42);
    

Session 2: 
    
    
    UPDATE foo SET b = 'Hello World' ;
    

Note that session 2 is now blocked. And the reason it's blocked is pretty simple: session 1 is holding a shared lock on the row in table foo, and the `UPDATE` in session 2 wants to acquire an exclusive lock to be able to modify it.

The `pgsql-hackers` discussion contained some very useful ideas on how to attack this problem, which is what I intend to do. If you've been affected by this problem and would like to discuss a solution, please let me know in a comment below. I'll be explaining my proposal in a forthcoming article.

---
[View this page online](https://www.commandprompt.com/blog/fixing_foreign_key_deadlocks/)

---

# Node and Postgres

> Or, two great tastes that work together.

PostgreSQL Conference West was last week, and we will be looking at East 2011 in a few short months. I was fortunat…

Or, two great tastes that work together. PostgreSQL Conference West was last week, and we will be looking at East 2011 in a few short months. I was fortunate enough to present a paper on Postgres.js, the driver I've been working on for Node.js for the past several months. I had a lot of great feedback in my talk, a lot of great questions, and even some immediate bug reports.  
But the feedback I received most often? "What is Node.js?"  


### What is Node?

[Node.js](<http://nodejs.org>) is a fast, server-side, event-driven JavaScript programming environment. For starters, this means we are talking about server side programming. Not, "web" programming. There are no cross browser problems, or fighting with IE. Node.js also uses V8, the very same JavaScript engine that Google Chrome uses. 

### Why do you need to care?

Node.JS, and JavaScript in particular is **huge**. Today, right now, it owns the frontend. There is more code being written in JavaScript, for all the Web2.0 magic we take for granted. Not only that, JavaScript is getting bigger every day. JavaScript is also the focus of a lot of language research and optimization. Google. Apple. Mozilla. Opera. Everyone cares about making JS better, faster. Check out [Mozilla's benchmark tracking page](<http://arewefastyet.com>). JavaScript runs on the server, quickly, with Node. JS already dominates the frontend. PL/V8 exists, and allows us to write stored procedures in JavaScript. Soon, you'll be able to develop entire infrastructures without learning a new language. People today who do not consider themselves programmers, know JavaScript, can build complex systems in JavaScript. Tomorrow, they'll be able to build new systems, leverage tighter coupling of browser and server and database. 

### Postgres and Node

So Node is an important step into tomorrow, but we still have our database systems, and tomorrow we will still be building new database systems. Further, Node's design and positioning as a network-first environment makes it a natural fit for working with Postgres. Data is simple, and communication is easy. Here's how: 
    
    
    var sys = require("sys");
    var pg = require("./lib/postgres-pure");
    
    var db = new pg.connect("pgsql://test:12345@localhost:5432/insert_test");
    db.query("SELECT 1::int;", function (error, rs, tx) {
        if (error) {
            console.log(error); // Will print the error statement
            console.log(error.code); 
        }
        else {
            console.log(sys.inspect(rs));
        }
    });
    

which returns: 
    
    
    [ { int4: 1 } ]
    

Or, to show off error handling: 
    
    
    db.query("SELECT 1::errortest;", function (error, rs, tx) {
        if (error) {
            console.log(error);
        }
        else {
            console.log(sys.inspect(rs));
        }
    });
    

which returns: 
    
    
    Error!
    { severity: 'ERROR'
    , code: '42704'
    , message: 'type "errortest" does not exist'
    , toString: [Function]
    }
    

### Prepared Statements and Parameterized Queries

The key part of good support for Postgres is in the Parameterized Queries. This feature allows Postgres itself to handle correct data transformations and replacements, preventing the possibility of most SQL injection attacks. Here's how to use prepared statements in postgres.js: 
    
    
    db.prepare("SELECT ?::int AS preparetest", function (sth, tx) {
        var logit = function (err, rs) {
            console.log(sys.inspect(rs));
        }
        sth.execute(1, logit);
        sth.execute(2, logit);
    });
    

which will return: 
    
    
    [ { preparetest: 1 } ]
    [ { preparetest: 2 } ]
    

The sth object passed by performing a prepare easily allows for the same query to be reused, saving time re-parsing the query on the server, as well as grouping all the execute statements into a single logical block. 

### The Future

The future of Postgres and Node is bright. We're looking to support LISTEN/NOTIFY transparently, allowing for very fast and very easy monitoring software to be written in Node. 
    
    
    var sys = require("sys");
    var pg = require("./lib/postgres-pure");
    
    var db = new pg.connect("pgsql://test:12345@localhost:5432/insert_test");
    db.on("YOUR_EVENT", function (payload) {
        // notify handler here
    });
    

And that's it; nothing more or less complex than a single function to handle your event. 

### The Caveats

Sadly, it's not entirely sunshine and roses on postgres.js. We have to post the disclaimer that this is very much alpha software, and shouldn't be used in a production context. But, we are working hard at stabilizing the driver, and Command Prompt is pleased to provide full support, and we welcome hearing from anyone using it. 

### How to Get It

postgres.js can be downloaded from one of two locations: <http://github.com/aurynn/postgres-js> for the bleeding-edge, most unstable variant. And: <http://github.com/commandprompt/postgres-js> for the stable, when-it-happens release fork.

---
[View this page online](https://www.commandprompt.com/blog/node_and_postgres/)

---

# Replication Poll results

> Back before PostgreSQL Conference West, there was a poll. That poll was replication. Here are the results. There were 367 respondents. Have fun with it!
   Qr…

Back before PostgreSQL Conference West, there was a poll. That poll was replication. Here are the results. There were 367 respondents. Have fun with it!

Q| responses  
---|---  
**1**|  **In what waydo you use PostgreSQL?**  
Development Only| 72  
As a hobby (or personaldevelopment)| 106  
Professionally| 325  
**2**|  **What versionof PostgreSQL are you running?**  
8.3| 117  
9.0| 175  
8.2| 50  
8.1| 36  
8.4| 251  
**3**|  **Do you use or plan to use replication?**  
No| 72  
Yes| 193  
Once I upgrade to 9.x| 102  
**4**|  **What type of replication do you use?**  
Londiste| 10  
Slony| 73  
Streaming Replication| 113  
Bucardo| 15  
Hot Standby| 90  
Home Grown / Custom| 34  
DRBD| 17  
**5**|  **If you don't use replication, why?**  
Backups are enough for me| 51  
Costs are too high (need more than one server)| 17  
It is a pain in the butt| 56  
Not a business requirement| 48

---
[View this page online](https://www.commandprompt.com/blog/replication_poll_results/)

---

# The old Berkeley Postgres code

> Some days ago, I was reading some patch from the in-progress commitfest, and happened to notice this comment in src/include/tcopprot.h:


 *    This file wa…

Some days ago, I was reading some patch from the in-progress commitfest, and happened to notice this comment in `src/include/tcopprot.h`:
    
    
     *    This file was created so that other c files could get the two
     *    function prototypes without having to include tcop.h which single
     *    handedly includes the whole f*cking tree -- mer 5 Nov. 1991
    

The weird thing about this was that there's no tcop.h file on the tree. I thought that it must have been removed somewhere along the long history of code cleanups and rearrangements. I was curious to see what this file looked like, so I went to the very first commit in our CVS, which turns out to be [this one in Git](<http://git.postgresql.org/gitweb?p=postgresql.git;a=tree;hb=d31084e9d1118b25fd16580d9d8c2924b5740dff>). However, it turns out that it's not there either!

So I turned to a quick web search, and found out that [Berkeley](<http://www.berkeley.edu>) (or rather the University of California) still has [the old tarballs for anyone to grab](<http://db.cs.berkeley.edu/postgres.html>).

I eventually found the file in the `postgres-v4r0` tarball; and as foretold in the old comment above, it clearly includes the whole source tree. Now that that file is long gone, I think it's time to remove that comment.

---
[View this page online](https://www.commandprompt.com/blog/the_old_berkeley_postgres_code/)

---

# MySQL: The Elephant in the room (Facebook?), oh and me.

> Rob Wultsch gave an interesting talk at PostgreSQL Conference West, about MySQL and why it doesn&#x27;t suck. Yes, this was a talk we accepted at a PostgreSQL Confe…

Rob Wultsch gave an interesting talk at PostgreSQL Conference West, about MySQL and why it doesn't suck. Yes, this was a talk we accepted at a PostgreSQL Conference. It was a good talk but some of the room was a little testy afterward. 

Outside of Rob's points which I found valid (you can see it in the video) the one thing that bugged me is the aggressiveness of Facebook. It appeared they felt we should be impressed that Facebook runs on MySQL not PostgreSQL. That somehow Facebook validates (or Google) the argument for MySQL.

The problem I have, is that Facebook data is worthless. It isn't worthless to them obviously. They make money selling your data (same as Google in a horizontal way). If Facebook loses your data. It is not a big deal. If your bank loses your data, **that is a big deal**. Financial institutions don't run on MySQL and for good reason. [They do however, run on PostgreSQL.](<http://www.enovafinancial.com/>)

To be fair, MySQL has its place and as you will see in my rebuttal, I don't hate MySQL. There is a lot of people that make this mistake. Never mistake apathy for disdain.

---
[View this page online](https://www.commandprompt.com/blog/mysql_the_elephant_in_the_room_facebook_oh_and_me/)

---

# You still don't need no stinking replication! (Replication Poll)

> So it appears my blog yesterday stirred a couple of coals. I love it. In response to Josh Berkus&#x27;s comment here, I offered up a poll. So here it is: Replicatio…

So it [appears my blog yesterday](<http://www.commandprompt.com/blogs/joshua_drake/2010/10/users_versus_customers_-_you_dont_need_no_stinking_replication/>) stirred a couple of coals. I love it. In response to [Josh Berkus's comment here](<http://archives.postgresql.org/pgsql-hackers/2010-10/msg01951.php>), I offered up a poll. So here it is: **[Replication Poll](<https://www.postgresqlconference.org/content/replication-poll>)**. You don't have to log in to take it but of course if you do, it helps track validity of results. Bring it on folks.

---
[View this page online](https://www.commandprompt.com/blog/you_still_dont_need_no_stinking_replication_replication_poll/)

---

# Users versus Customers - YOU DON'T NEED NO STINKING REPLICATION

> I was catching up on the max_wal_senders must die thread and I came across this very interesting post by fellow Josh Berkus.In the post, Josh Berkus makes the …

I was catching up on the [max_wal_senders must die](<http://archives.postgresql.org/pgsql-hackers/2010-10/msg01253.php>) thread and I came across this very [interesting post](<http://archives.postgresql.org/pgsql-hackers/2010-10/msg01948.php>) by fellow Josh Berkus.

In the post, Josh Berkus makes the assertion, "50% of PGX's active clients have either already converted to 9.0 replication or have scheduled a conversion with us".

I have no doubts of Josh's statement but it brings up an interesting point when arguing about features in PostgreSQL. Josh's response was in regards to a point made by Tom Lane that only a minority of our users are going to want replication. At this point people are going, "What? Of course we want replication!!!!" but you know what? You don't.

Yes, Command Prompt customers want replication. Yes, PostgreSQL Experts, EntepriseDB and OmniTI customers want replication. However, customers are *not* users. At least not in the community sense and the users in the community, the far majority of them do not need or want replication. A daily backup is more than enough for them.

I think we are going to see an increase in the disparity between customers and users as time goes on. I for example, do not see a real benefit to the 9.0 replication features. That is not to disparage the very hard work that the community members put in, just that we have already defined solutions to solve that problem, years ago. Solutions that work very well. I am more excited about things like SQL/med or PL/psm support.

[Want to argue with Josh Berkus or I about this? Catch us at PostgreSQL Conference West next week.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/users_versus_customers_-_you_dont_need_no_stinking_replication/)

---

# Are hump days, slow days? Wait ... what, No more Gnome for Ubuntu?

> There are so many things to consider when working through the week. You never send a  Press Release never on Monday or Friday. Scheduling meetings is always a …

There are so many things to consider when working through the week. You never send a Press Release never on Monday or Friday. Scheduling meetings is always a bad idea on Monday. Thursdays always seem to be busy, probably because people want to be lazy on Friday. Monday you never know what is going to happen, you might get slammed or you might be waiting for the next email to come in hoping it is important.

I am now completely off the above topic because I just got this in my email:

Canonical shook the Linux world yesterday when it announced that the next version of Ubuntu -- "Natty Narwhal," or version 11.04 -- will no longer use the GNOME interface by default. Instead, Natty will feature Unity, the multitouch and 3D-enabled interface that made its debut earlier this month in the distribution's netbook edition of Maverick Meerkat, or Ubuntu 10.10.

[Read whole article](<http://ifwnewsletters.newsletters.infoworld.com/t/6910772/122698007/333385/0/>)

I just started using Unity on my notebook. It is quite nice and quite a bit less clunky than default Gnome but... WOW!

 **Oh and[Register for PostgreSQL Conference West](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/are_hump_days_slow_days_wait__what_no_more_gnome_for_ubuntu/)

---

# INSERT..RETURNING in postgres.js

> So as you all know, we&#x27;ve been working on postgres support for the up-and-coming node.js environment, and we just got a great new example of Postgres&#x27; function…

So as you all know, we've been working on postgres support for the up-and-coming [node.js](<http://nodejs.org/>) environment, and we just got a great new example of Postgres' functionality that we're proud to say we support - specifically, the query format INSERT..RETURNING. For those unfamiliar with INSERT..RETURNING, this type of query allows us to do just what it says - return a value, or set of values, after an INSERT statement. This is really useful when dealing with sequences, as your application layer can be notified of new primary keys, or other values that might be interesting. Here's how it works: 
    
    
    -- SQL for setup.
    CREATE TABLE returning_test (id serial not null, val text);
    
    // postgres.js code
    
    var sys = require("sys");
    var pg = require("./lib/postgres-pure");
    
    var db = new pg.connect("pgsql://test:12345@localhost:5432/returning_test");
    db.prepare("INSERT INTO returning_test (val) VALUES (?) RETURNING id", 
        function (sth) {
            sth.execute("text value", function(rs) {
                if (rs === undefined) {
                    console.log("No data.");
                }
                else {
                    console.log(sys.inspect(rs));
                }
            });
    });
    
    // And our output:
    $ node demo.js
    [ { id: 4 } ]
    
    // Subsequent runs, as expected:  
    [ { id: 5 } ]
    [ { id: 6 } ]
    [ { id: 7 } ]
    [ { id: 8 } ]
    

Easily done, and using the exact same prepared syntax that postgres.js uses for SELECT statements - exactly as you'd expect a query returning data to operate. Postgres also does complex RETURNING, which would be: 
    
    
    
    var db = new pg.connect("pgsql://test:12345@localhost:5432/returning_test");
    db.prepare("INSERT INTO returning_test (val) VALUES (?) RETURNING id, val", 
        function (sth) {
            sth.execute("text value", function(rs) {
                if (rs === undefined) {
                    console.log("No data.");
                }
                else {
                    console.log(sys.inspect(rs));
                }
            });
    });
    
    [ { id: 9, val: 'text value' } ]
    
    

Postgres.js is MIT-licensed and available from github. Check out the [reasonably stable version](<http://github.com/commandprompt/postgres-js>), or help out with development on the [development branch](<http://github.com/aurynn/postgres-js>). Patches are always appreciated!

---
[View this page online](https://www.commandprompt.com/blog/insertreturning_in_postgresjs/)

---

# PgWest 2010: Officially larger that PgEast 2010

> As of 5:00PM PST PostgreSQL Conference West 2010 became the largest PostgreSQL Conference in the series. The conference is also still growing as registrations …

As of 5:00PM PST PostgreSQL Conference West 2010 became the largest PostgreSQL Conference in the series. The conference is also still growing as registrations continue to come in.

Not only do we have more attendees coming to West than we did East, we have more content than we did at East. It seems that with every 6 months comes a new milestone for the series. PgWest 2010 has 3 full days, 53 speakers and 61 sessions. To top that off, PgEast 2011, is setting up to be 4 full days with an expectation of at least 30% more content and as much as 50% more attendees.

[Have you registered for West yet?](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_officially_larger_that_pgeast_2010/)

---

# PgWest 2010: 8 Days and counting

> I can&#x27;t believe how far we have come from a single day, Saturday &quot;PgDay&quot; in 2007 to a full blown three day conference in the middle of the week. Twice a year, …

I can't believe how far we have come from a single day, Saturday "PgDay" in 2007 to a full blown three day conference in the middle of the week. Twice a year, every year we have grown, adding content, reaching out to users, bringing the entire ecosystem together. The PgWest and PgEast conferences have grown to comprise the largest PostgreSQL conferences, anywhere.

Now that West is upon us in just a short while, I am beginning to think about East. What can we do for East to make it even larger? Another 50% attendance would be a huge win. I do know that East will be a 4 day conference, with full day trainings the first day. I am considering pushing the tutorials to the last day, so the two days in the middle would be sessions. [Anyway, now is the time to register for West if you haven't yet.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_8_days_and_counting/)

---

# PgWest 2010: Party Announced and Training Added!

> PostgreSQL Conference West 2010 also known as PgWest, is having a party for attendees from 5:30pm to 8:30pm on November 3rd. Located on the 21st floor of the S…

[PostgreSQL Conference West 2010](<http://www.postgresqlconference.org/>) also known as PgWest, is having a party for attendees from 5:30pm to 8:30pm on November 3rd. Located on the 21st floor of the Sir Francis Drake Hotel, the 360-degree view from the Starlight Room is as breathtaking as any in the world, encompassing brilliant sunsets or rolling fog, city lights, and landmarks from Telegraph Hill to the Bay Bridge. Harry Denton's Starlight Room is the perfect setting for a total DBA Geek Party!

 **[Register now.](<https://www.postgresqlconference.org/content/pgwest-2010-registration>)**

We have also added a full day training on the 5th. The training, is a repeat of the very successful Mastering PostgreSQL Administration held at PostgreSQL Conference East 2010. It being taught by PostgreSQL.org Core team member, Bruce Momjian. [You can register for the class at Platinum Sponsor EnterpriseDB's website.](<http://www.enterprisedb.com/tservices/training/postgresql-mastering.do>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_party_announced_and_training_added/)

---

# PgWest 2010: Anticipated talk, How To Say Yes To NoSQL: Using Redis With Postgres

> There has been a lot of talk lately about this idea of &quot;NoSQL&quot;. A lot of database traditionalists have been very down on the idea that something else is a bett…

There has been a lot of talk lately about this idea of "NoSQL". A lot of database traditionalists have been very down on the idea that something else is a better way to extract and store data. I have been in SQL land for so long that I can't even form a credible opinion on the matter. I know that SQL (for the most part) is logical. It makes sense for the paradigm in which it is used.

I also know that programmers who don't really know anything about databases have been trying to "fix" them for decades only to eventually come back to earth and realize our way is the best way (thus why all your decent ORMs now support natural keys). Redis has a lot of momentum. I look forward to seeing what they have to offer.

  * [Talk description](<https://www.postgresqlconference.org/content/how-say-yes-nosql-using-redis-postgres>)
  * [Register](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_anticipated_talk_how_to_say_yes_to_nosql_using_redis_with_postgres/)

---

# PgWest 2010 anticipated talk: Source Forge

> PostgreSQL Conference West is continuing to shape up as the largest PostgreSQL Conference, ever. We have a significant, solid and eclectic range of talks.One o…

[PostgreSQL Conference West](<https://www.postgresqlconference.org/>) is continuing to shape up as the largest PostgreSQL Conference, ever. We have a significant, solid and [eclectic range of talks.](<https://www.postgresqlconference.org/2010/west/talks>)

One of the talks that was just finalized today is, [Deployment Best Practices](<https://www.postgresqlconference.org/content/deployment-best-practices>). This is a great beginner talk. What I like about this talk is that is is from a tried and true, in the trenches company that has been using PostgreSQL since the 6.x days. That company is [SourceForge](<http://www.sf.net/>), the Big Papa of Open Source and Free Software project hosting.

[Register for PgWest 2010](<https://www.postgresqlconference.org/content/pgwest-2010-registration>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_anticipated_talk_source_forge/)

---

# PgWest 2010 Keynote speaker is: Sun Microsystems Founder, Scott McNealy

> PostgreSQL Conference West (PgWest) 2010, the premiere PostgreSQL Conference for developers, users and decision makers is pleased to welcome Sun Microsystems f…

PostgreSQL Conference West (PgWest) 2010, the premiere PostgreSQL Conference for developers, users and decision makers is pleased to welcome Sun Microsystems founder, Scott McNealy as Key Note Speaker.

Please join us November 2nd - 4th at the Sir Francis Drake Hotel in sunny San Francisco for three days of networking, education, geeks, food and fun!

[Registration is now open.](<https://www.postgresqlconference.org/content/pgwest-2010-registration>) [The Agenda is available.](<https://www.postgresqlconference.org/2010/west/agenda>) As are [the full talk descriptions!](<https://www.postgresqlconference.org/2010/west/talks>)

And of course, thank you to our sponsors:

  * [Command Prompt, Inc.](< http://www.commandprompt.com/>)
  * [EnterpriseDB](<http://www.enterprisedb.com/>)
  * [2ndQuadrant](<http://www.2ndquadrant.com/>)
  * [Continuent](<http://www.continuent.com/>)
  * [JasperSoft](<http://www.jaspersoft.com/>)
  * [EnovaFinancial](<http://www.enovafinancial.com/>)
  * [Redhat](<http://www.redhat.com/>)
  * [PgExperts](<http://www.pgexperts.com/>)
  * [Credativ](<http://www.credativ.com/>)
  * [Emma](<http://www.myemma.com/>)
  * [ReadWriteWeb](<http://www.readwriteweb.com/>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_keynote_speaker_is_sun_microsystems_founder_scott_mcnealy/)

---

# Evisceration: Learning from colorful mistakes

> Most people are aware that we use Drupal for the PostgreSQL Conference. We are loud advocates of the platform, because it works -- mostly. In terms of being ab…

Most people are aware that we use Drupal for the [PostgreSQL Conference](<http://www.postgresqlconference.org/>). We are loud advocates of the platform, because it works -- mostly. In terms of being able to run a conference it is flexible enough to make it quirks bearable. However the one place that Drupal is severely lacking is event/scheduling. What is available is either lacking, broken, or just not yet done. Because of this we have always used Google Calendar to do our scheduling. We have also always gotten grief for it. So this year I tried to put a pretty face on top of Google Calendar.

The change lead to the removal of all of my vital organs except my heart. The community informed me that I was able to keep my heart because they wanted me to feel the sorrow and anguish they felt when they saw the changes I made.

Anyway, thanks to Magnus and a full day of hacking and bashing by myself, we now have a much better [front end to the schedule.](<http://www.postgresqlconference.org/2010/west/agenda>) Now, if you all wouldn't be [too shy to register](<https://www.postgresqlconference.org/content/pgwest-2010-registration>) that would be great. Thanks!

---
[View this page online](https://www.commandprompt.com/blog/evisceration_learning_from_colorful_mistakes/)

---

# Do I get to attend a talk?

> While at PgEast or PgWest I normally don&#x27;t attend talks. Usually I am running around checking on rooms, making sure cameras are working or just generally recov…

While at [PgEast or PgWest](<http://www.postgresqlconference.org/>) I normally don't attend talks. Usually I am running around checking on rooms, making sure cameras are working or just generally recovering from yet another round of social interaction with everyone that is there. Do not kid yourself, it is exhausting.

This year at West I am hoping to attend a couple of talks. There are a few that are particularly interesting to me. The first is: [PostgreSQL and Node.JS](<https://www.postgresqlconference.org/content/postgresql-and-nodejs>). Granted I am biased because it is one of my team members speaking but this is a truly interesting thing that she is working on. The ability to write postgresql driven Javascript applications using node.js is 100% buzzword compliant and useful. 

Of course this also coincides with the recent Alpha release of the driver which can be forked or pulled from its [github home.](<http://github.com/commandprompt/postgres-js>).

If you are up for it, you could also talk to Aurynn in person about the project either on irc in #postgresql or at [PostgreSQL Conference West 2010](<http://www.postgresqlconference.org/>).

---
[View this page online](https://www.commandprompt.com/blog/do_i_get_to_attend_a_talk/)

---

# Headed to Utah Open Source Conference

> The Utah Open Source Conference is coming up next week and I will be speaking on PostgreSQL. The presentation I was selected to give is my Dumb Simple PostgreS…

The [Utah Open Source Conference](<http://www.utosc.org/>) is coming up next week and I will be speaking on PostgreSQL. The presentation I was selected to give is my Dumb Simple PostgreSQL Performance talk.

This talk aims to solve the performance (and maintenance) problems most associated with a default install of PostgreSQL. The depth of the talk is limited and is designed specifically for people who are *not* database people, e.g; Web Developers and System Administrators.

The week after I will be headed to Boston to attend [OpenSQL Camp 2010](<http://www.opensqlcamp.org/Events/Boston2010/>) where I will be giving the same talk. Hope to see some community there!

---
[View this page online](https://www.commandprompt.com/blog/headed_to_utah_open_source_conference/)

---

# MySQL does what? (Division by integers and 0)

> I was sitting in #postgresql today (no not the twitter, the irc) talking to some of the community peeps and I came across this tidbit. MySQL casts integers to …

I was sitting in #postgresql today (no not the twitter, the irc) talking to some of the community peeps and I came across this tidbit. MySQL casts integers to float before division[1]. Say what? 
    
    
    mysql> SELECT 3/5;
            -> 0.60
    

To be honest, I can't fault MySQL for this behavior. It falls in line with the MySQL mantra of make it easy, not "necessarily" correct. A division of 3/5 in a numeric or float would return 0.60. It makes the math easy and normal human consumable. 

PostgreSQL and Python on the other hand would give you this:
    
    
    postgres=# select 3/5;
     ?column? 
    ----------
            0
    (1 row)
    
    Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
    [GCC 4.4.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 3/5;
    0
    >>> 
    

To get the similar human consumable response you would want:
    
    
    postgres=# select 3/5.0;
            ?column?        
    ------------------------
     0.60000000000000000000
    (1 row)
    
    Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
    [GCC 4.4.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 3/5.0;
    0.59999999999999998
    

Python is using float versus numeric here which explains the disparity. However, MySQL does do something that violates a very basic, as in elementary school math mistake. MySQL defines division by zero as NULL. Yes, you read that correctly.
    
    
    mysql> SELECT 102/(1-1);
            -> NULL
    

What should happen is:
    
    
    postgres=# select 102/(1-1);
    ERROR:  division by zero
    
    >>> 102/(1-1);
    Traceback (most recent call last):
      File "", line 1, in 
    ZeroDivisionError: integer division or modulo by zero
    

That's correct, an **ERROR** or **EXCEPTION** 1\. http://dev.mysql.com/doc/refman/5.0/en/arithmetic-functions.html#operator_divide 2\. http://en.wikipedia.org/wiki/Division_by_zero

---
[View this page online](https://www.commandprompt.com/blog/mysql_does_what_division_by_integers_and_0/)

---

# PGXN: Are you a benefactor?

> O.k. so I have been pushing on everyone I know to support PGXN. Command Prompt, (you know, us) hadn&#x27;t bothered to donate. Mainly we hadn&#x27;t donated because we w…

O.k. so I have been pushing on everyone I know to support [PGXN](<http://www.pgxn.org/>). Command Prompt, (you know, us) hadn't bothered to donate. Mainly we hadn't donated because we wanted to be a founding sponsor but just didn't have the budget for it, with the whole [PostgreSQL Conference](<https://www.postgresqlconference.org/>) thing going on.

Today, we put our money where our rather obnoxious mouth is and became a benefactor (at the tune of 1k). So with that, step up people. Don't you want to be able to do this: 
    
    
    pgxn --install py-postgresql
    

Instead of downloading, compiling, finding missing dependencies, screwing around for an hour doing nothing but swearing at the fact that you don't have what you need to use Python + PostgreSQL? No. You don't want to do that. You want to [**donate to PGXN**](<http://www.pgxn.org/>), so you don't have to.

---
[View this page online](https://www.commandprompt.com/blog/pgxn_are_you_a_benefactor/)

---

# PgWest 2010: Talk Descriptions are up

> The talk descriptions for PgWest 2010 are now up. As you can see, there is a lot of content that will be presented over the three days. There is a great mix of…

The talk descriptions for [PgWest 2010 are now up.](<https://www.postgresqlconference.org/2010/west/talks>) As you can see, there is a lot of content that will be presented over the three days. There is a great mix of developer and user (DBA) content. If you haven't done so already, [now is the time to register.](<https://www.postgresqlconference.org/content/pgwest-2010-registration>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_talk_descriptions_are_up/)

---

# PgWest, have you booked your room? 

> If you have not booked your room for PgWest, now is the time. There is a very real possibility that the cost of the hotel will go up in the next week. Now is n…

If you have not [booked your room for PgWest](<https://www.postgresqlconference.org/2010/west/accommodations>), now is the time. There is a very real possibility that the cost of the hotel will go up in the next week. Now is not the time to be a traditional geek procrastinator.

---
[View this page online](https://www.commandprompt.com/blog/pgwest_have_you_booked_your_room_/)

---

# Oracle MySQL increasing support pricing

> Oracle MySQL recently started sending letters to their current clients about upcoming price changes[1]. It is certainly expected that Oracle would increase pri…

Oracle MySQL recently started sending letters to their current clients about upcoming price changes[1]. It is certainly expected that Oracle would increase pricing, but I wonder by how much?

Oracle owns another fairly well known Open Source database, BerkeleyDB. [The pricing for BerkeleyDB.](<http://www.oracle.com/corporate/pricing/technology-price-list.pdf>) suggests that MySQL may be in for a culture shock. MySQL appears to have removed their support pricing from its website (a move that should not provide comfort to any customer) but as I recall (please correct me if I am wrong) it used to be anywhere from 2500.00 USD to 5000.00 USD, per installation. Whereas Oracle pricing is per processor. Oracle does give you a break if it is a [multi-core machine but it isn't huge.](<http://oraclestore.oracle.com/OA_HTML/ibeCCtpSctDspRte.jsp?section=11365&media=os_g_english_help_licensing&minisite=10021&respid=22372&grp=STORE&language=US>)

If we use the BerkeleyDB Transactional pricing as a model for what MySQL "could be" a quad core machine would cost a MySQL customer 11,600.00-23,200.00 per year. This is a guess because I don't know the calculation for a Xeon quad core, it would be somewhere between .25 and .75 per core. Oracle is not known for making their pricing clear.

Where am I going with all of this? It should be obvious, moving to PostgreSQL with support from a long standing, [transparent support and pricing schedule](</support/support_options>) can do nothing but benefit you in the future.

> Updated: 09/29/2010 12:19: [Current MySQL Pricing](<http://mysql.com/products/enterprise/features.html>)

**1.**
    
    
    "Hello Customer,
    
    I am writing as way of introduction.  My name is Juliet and I am your
    MySQL contact at Oracle.  It is my understanding that you are the most
    appropriate person to speak with at your organization regarding MySQL.
     If you have any MySQL requirements, questions on the products,
    support, consulting or training we provide, please do not hesitate in
    contacting me.
    
    I'm sure you are aware that Oracle purchased Sun and therefore MySQL
    last February.  We're being told that there will be changes to MYSQL's
    pricing and possibly pricing model soon and wanted to let you know.
    We have not had a price increase for over 6 years but there will be an
    increase in the next price list that will be available soon.  We've
    been expecting the increase for the past couple of months but I'm told
    it the new price list will be released soon.
    
    For those of you using Basic and Silver support we're being told those
    options will no longer be available.  If you wish to continue with
    Basic or Silver you will need to sign a multi-year agreement and you
    would be able to keep using Basic or Silver for up to another 3 years.
    
    If you are considering purchasing additional licenses for MySQL
    support subscription, please let me know, because you can save money
    if you do it before the changes take place, some time in the next
    month or two.   You can also sign multi-year agreements and lock down
    current prices for up to 3 years.
    
    You can receive up to a 30% discount for a 3 yr. commitments pre-pay
    but annual payments are available as well for multi-year agreements.
    
    If you would like to speak to someone about MySQL Cluster, please let
    me know and I can arrange for an expert to call you within the next
    week.
    
    Please let me know if you have any questions.

---
[View this page online](https://www.commandprompt.com/blog/oracle_mysql_increasing_support_pricing/)

---

# Break out your credit card, support #PGXN

> PGXN is the stuff. It is going to enable a whole new ecosystem of software for PostgreSQL complete with easy install, easy search, modular design and yeah unfo…

PGXN is the stuff. It is going to enable a whole new ecosystem of software for PostgreSQL complete with easy install, easy search, modular design and yeah unfortunately Perl.

That said, it is time to pony up. David Wheeler has put in some serious effort, well thought out, professionally designed and peer reviewed effort on delivering a new architecture for PostgreSQL software and modules. He needs our financial support.

[Go here and contribute, today.](<http://www.pgxn.org/>) He is less than [7k away from his goal.](<http://www.pgxn.org/>)

---
[View this page online](https://www.commandprompt.com/blog/break_out_your_credit_card_support_pgxn/)

---

# Interviewed by Linux.com

> So, I broke down at purchased my Linux Foundation membership. Shortly thereafter I was requested to be interviewed. Here it is.

So, I broke down at purchased my Linux Foundation membership. Shortly thereafter I was requested to be interviewed. [Here it is.](<http://www.linux.com/news/featured-blogs/185-jennifer-cloer/364435-the-people-who-support-linux-my-heart-for-open-source-began-with-linux>)

---
[View this page online](https://www.commandprompt.com/blog/interviewed_by_linuxcom/)

---

# PgWest 2010 Early Bird Registration Open!

> We are still finalizing the three days of content but the first tutorials of the conference have been accepted and 
early bird registration is now open.
Tuto…

We are still finalizing the three days of content but the first tutorials of the conference have been accepted and [early bird registration is now open.](<https://www.postgresqlconference.org/content/pgwest-2010-registration>)

**Tutorials:**

  * Test Driven 
  * Database Development 
  * Building an Open Geospatial Analysis Technology Stack 
  * Normalization Workshop 
  * GUCs: a Three-Hour Tour 
  * Django and PostgreSQL

**Mini-tutorials:**

  * PostgreSQL Backup and Recovery Methods 
  * MVCC Unmasked 
  * The PostgreSQL Query Planner 
  * Writing C Functions and C User Defined Types on Windows Using Visual 
  * Studio (C++) 
  * Using the PostgreSQL System Catalogs 
  * HTSQL NoSQL for PostgreSQL 
  * Blue skies: Replication using Skytools and Londiste 
  * Using LVM2 to provide copies of production data for testing



The PostgreSQL Conference provides an opportunity for the Postgres community to come together to share and celebrate the most recent advances to the product. If you are currently a Postgres user, or are considering deploying the world's most advanced open source database within your organization, you can't miss this show. This is a cost effective way to receive training, build your skills, hear from your peers and other end users about their implementations, and network with the community leaders to discuss future product directions. (And have some fun, too!)

Many thanks to our sponsors:

  * Founding: [Command Prompt, Inc. ](<http://www.commandprompt.com/>)
  * Diamond: [EnterpriseDB](<http://www.enterprisedb.com/>)
  * Gold: [2ndQuadrant](<http://www.2ndquadrant.us>)
  * Silver: [Enova Financial](<http://www.enovafinancial.com/>)
  * Silver: [PgExperts](<http://www.pgexperts.com>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_early_bird_registration_open/)

---

# Is your PgWest 2010 presentation submitted?

> One of the aspects of the Open Source community I love is the agile, on demand nature of getting things done. If a feature is missing, you can just add it and …

One of the aspects of the Open Source community I love is the agile, on demand nature of getting things done. If a feature is missing, you can just add it and you can add it on demand, as you need it. If a bug is present, you can fix it yourself or pay someone else like [CMD](<http://www.commandprompt.com>) to fix it for you.

Unlike other communities that are closed where requirements and demands can fester for years in an oblivion of "marketability".

There is however a downside to this aspect of the Open Source community.

 **[We like to wait until the last minute.](<https://www.postgresqlconference.org/2010/west/cfp/>)**

 **Well, now is the[last minute!](<https://www.postgresqlconference.org/2010/west/cfp/>)**

 **[Get your talk in today and be part of the largest PostgreSQL Conference to date!](<https://www.postgresqlconference.org/2010/west/cfp/>)**

---
[View this page online](https://www.commandprompt.com/blog/is_your_pgwest_2010_presentation_submitted/)

---

# PgWest 2010, CFP about to close!

> Yes, we said it was the 5th that the CFP would be closing but then we belatedly realized that a good portion of the United States would be having a BBQ and dri…

Yes, we said it was the 5th that the CFP would be closing but then we belatedly realized that a good portion of the United States would be having a BBQ and drinking whatever their favorite beverage is over the weekend. Thus in true PostgreSQL fashion, PgWest is missing its CFP release date but only for a week! That means, [**submit your paper, now.**](<https://www.postgresqlconference.org/2010/west/cfp/>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_cfp_about_to_close/)

---

# PgWest: 2010 Call for Papers (2nd call)

> Yes, it is the second call. That means some of you haven&#x27;t submitted after the first call. Of course, I haven&#x27;t submitted mine either; so it is time for everyo…

Yes, it is the second call. That means some of you haven't submitted after the first call. Of course, I haven't submitted mine either; so it is time for everyone to get on it. West is just around the corner and from all observations this West stands to be the largest PostgreSQL Conference, ever. (O.k. we might not over take Brazil).

Here is the announcement for everyone to review, enjoy and click on the CFP link:

Following on the smashing success of PostgreSQL Conference East, PostgreSQL Conference West, The PostgreSQL Conference for Decision Makers, End Users and Developers, is being held at the Sir Francis Drake Hotel in San Francisco from November 2nd through 4th 2010. Please join us in making this the largest PostgreSQL Conference to date!

  * [Main conference site](<http://www.postgresqlconference.org/>)
  * [Call for Papers](<http://www.postgresqlconference.org/2010/west/cfp>)

**Thank you to our sponsors:** Founding: [Command Prompt](<http://www.commandprompt.com/>) Diamond: [EnterpriseDB](<http://www.enterprisedb.com/>)

**Time line:**

> July 14th: Talk submission opens Sept 5th: Talk submission closes Sept 10th: Speaker notification 

This year we will be continuing our trend of covering the entire PostgreSQL ecosystem. We would like to see talks and tutorials on the following topics:
    
              * General PostgreSQL: 
                  * Administration 
                  * Performance 
                  * High Availability 
                  * Migration 
                  * GIS 
                  * Integration 
                  * Solutions and White Papers 
          * The Stack: 
                  * Python/Django/Pylons/TurboGears/Custom 
                  * Perl5/Catalyst/Bricolage 
                  * Ruby/Rails 
                  * Java (PLJava would be great)/Groovy/Grails 
                  * Operating System optimization
                    (Linux/FBSD/Solaris/Windows) 
                  * Solutions and White Papers

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_call_for_papers_2nd_call/)

---

# An update on Replicator

> This is my first post on Replicator, I&#x27;m going to start by describing the terminology we use, bringing some analogies from other replication systems.Replicator…

This is my first post on Replicator, I'm going to start by describing the terminology we use, bringing some analogies from other replication systems.

Replicator is an asynchronous master-to-multiple-slaves replication system. It works by propagating binary changes from a single read-write node (called master) to one or more read-only nodes (called slaves) through an intermediary (forwarder) process. The data changes are stored in binary transaction files on a per-transaction basis. Additionally, each file contains a list of replication tables the data belongs to. Every slave has a distinct set of tables to replicate. Finally, transaction files are addressed by a special data structure called replication queue.

After connecting to the forwarder for the first time each slave node performs an initial sync (full dump) by requesting a complete up-to-date snapshot of replication tables. The forwarder doesn't necessarily resend such request to a master process. Instead, it checks the queue for past full dumps and reuses them if appropriate.

To reduce the bandwidth and disk space consumption per each slave the set of tables replicated by the slave is compared with the set of current transaction's tables, and the forwarder decides to send a transaction to the slave only when these 2 sets intersects; thus, each slave receives data only for those tables it replicates. So far, there was an important exception to this rule: full dump transactions were always sent to every slave. The original justification for this was the fact that full dump was required after addition of a new replicated table, and every slave had to be aware of this addition. 

In 1.8 we introduced a new feature called 'per-table dumps', which allowed a slave to request a snapshot of a single table, instead of requesting a full dump. Currently, when a new table is added to the replication, only a single per-table dump is requested, and there's no need for a full dump. This made possible for a slave to 'skip' a full dump, and changes committed last week implement exactly this: if the slave is in sync (i.e. doesn't wait for a dump, or recovering from an error), the forwarder just skips sending full dump transactions to this slave, therefore avoiding most bandwidth-consuming transactions. It's a clear win!

Additionally there is another related positive change. When a slave restores full dump transaction it replaces the data of each replicated table with the one from the dump, leaving the table inconsistent for some period of time (which is usually short, but depends on table size and other factors). By reducing the average number of dumps per each slave we also reduced the number of these 'inconsistency gaps'. Double win!

The next version, 1.9, is still in development. We put it (as well as [other open-source projects](<http://github.com/commandprompt>)) on [github](<http://github.com/commandprompt/PostgreSQL-Replicator>), so you are welcome to check it out and join the [replicator mailing list](<https://lists.commandprompt.com/mailman/listinfo/replicator-general>).

Stay tuned for further updates!

---
[View this page online](https://www.commandprompt.com/blog/an_update_on_replicator/)

---

# FOSSExperts, day 2

> I expected feedback from the community on FOSSExperts. I did not expect feedback with such immediacy. All the feedback I have received so far is positive. Whic…

I expected feedback from the community on [FOSSExperts](<https://www.fossexperts.com/>). I did not expect feedback with such immediacy. All the feedback I have received so far is positive. Which is a great feeling. Here are the key points that are coming back.

 **How do deal with disagreement about the deliverable:**

This is an interesting one. I wanted to keep FOSSExperts simple. That is why the deliverable on the [ALTER TABLE](<https://www.fossexperts.com/content/postgresql-alter-table-column-position>) project is simple, committed to PostgreSQL Core. 

That may not work in all circumstances. So I am considering one of two options. The first option is courtesy of Josh Berkus. The idea would be to have a board of people that determine whether or not the deliverable has been met. This has merit because you have a panel of experts that make the determination. It can make the review process painless but is also takes the power out of both the funders and developers.

The second one is to take a vote. It would work something like this.

  * Developer states project is complete and demonstrates completeness based on the deliverable. 
  * Every person who funded the project votes on whether or not the project is complete.

    * If 66% vote the project complete, developer gets their money. 
    * If less than 66% vote project incomplete, developer doesn't get their money. 

There would have to be some caveats. First the funders need to be able to communicate with the developer because they may not have understood part of the spec. Further as we are working with Open Source, the end deliverable may have been changed based on the will of the community versus the developer (see the Hot Standby work with PostgreSQL).

The voting would also need to be limited to a period of time. I was thinking 14 days. The 66% would be tallied against those that voted in that 14 days.

I like this idea because it removes the third party and it stops a single funder from calling foul as they are part of a collective vote. What do you think? 


Other than that the feedback has been extremely positive. I even posted to the LedgerSMB list and multiple people are excited to see this opportunity. If you have ideas, [please share them. We have setup a flame page just for this.](<https://www.fossexperts.com/content/love-and-hate-fossexperts>)

Remember a lot of your questions [can be answered in the FAQ as well.](<https://www.fossexperts.com/faq>)

---
[View this page online](https://www.commandprompt.com/blog/fossexperts_day_2/)

---

# FOSSExperts, a new way to fund Open Source (Beta)

> The cat is out of the proverbial bag. I originally planned to have a quiet roll out with a few close contributors but that has gone by the wayside. Now I am go…

The cat is out of the proverbial bag. I originally planned to have a quiet roll out with a few close contributors but that has gone by the wayside. Now I am going to be pushing hard for people to test, beat on, object to, argue about, flame upon, scream at, praise and hopefully help us build out something that is truly useful for the FOSS Community. What am I blathering on about? [FOSSExperts](<https://www.fossexperts.com>) of course. 

FOSSExperts is a new site specifically engineered to allow FOSS developers to raise money for projects they are trying to develop. The idea stemmed from the very cool [Kickstarter](<http://www.kickstarter.com/>). With our focus obviously being on a different kind of creative.

This is long overdue in the FOSS Community. There are a great deal of communities out there ([LedgerSMB](<http://www.ledgersmb.org/>) for example) that can use a place for their developers to try and raise funds for a specific feature. LedgerSMB just recently had a discussion on developing a Payroll module. Developing a Payroll module will be expensive for a single small company to absorb, but 20 small companies? Not nearly as expensive.

What FOSSExperts is not, is a place to send money to global projects such as Debian or PostgreSQL.org. It is for specific, well defined proposals and has a specific and defined delivery as well as refund policies etc.

Right now, we are in closed Beta. If you have a project or proposal you would like to try out you need to email me directly but we are interested. [So take a look, and let the rage begin!](<https://www.fossexperts.com/>) If you like, you can [review one of the larger proposals](<https://www.fossexperts.com/content/postgresql-alter-table-column-position>) already on the site as well.

---
[View this page online](https://www.commandprompt.com/blog/fossexperts_a_new_way_to_fund_open_source_beta/)

---

# A better backup with PostgreSQL using pg_dump

> This is generously borrowed from the PostgreSQL Docs, and updated to something that represents a modern approach to PostgreSQL backups. This documentation has …

> This is generously borrowed from the PostgreSQL Docs, and updated to something that represents a modern approach to PostgreSQL backups. This documentation has always bothered me because it should have been re-written years ago. Yes I plan on submitting a more comprehensive version as a patch but I don't have time to push it into DocBook right now. If someone else wants to grab it, please do. Yes, I really do believe the use of plain text backups is a mistake. Yes I realize PostgreSQL has the limitation of not being able to backup the cluster in anyway but plain text.

The standard for portable backups with PostgreSQL is pg_dump and pg_dumpall. When used properly pg_dump will create a portable and highly customizable backup file that can be used to restore all or part of a single database. The pg_dump application acts as a standard PostgreSQL client. This means that you can perform this backup procedure from any remote host that has access to the database. You do not need to be a super user to use pg_dump but you must have read (and EXECUTE for functions) access to every object within the database. Backups created by pg_dump are internally consistent, meaning, the dump represents a snapshot of the database at the time pg_dump began running. The backup will not block other operations on the database while it is working. (Exceptions are those operations that need to operate with an exclusive lock, such as most forms of ALTER TABLE.) The minimum useful syntax for pg_dump is:

> pg_dump dbname > outfile

However, the backup created from this method has limited usefulness. It can be used to restore a single database in full. A more useful and proper form of PostgreSQL backup syntax looks like this:

> pg_dump -U $username --format=c --file=$mydatabase.sqlc $dbname

The options in detail are:

>   
>  -U, --username=NAME connect as specified database user   
>  -F, --format=c|t|p output file format (custom, tar, plain text)   
>  -f, --file=FILENAME output file name   
> 

The most important of which is --format. By default pg_dump uses the plain text format. The plain text format is useful for very small databases with a minimal number of objects but other than that, it should be avoided. The custom format allows for a wealth of customizability. Using the custom format you are able to restore single objects from a backup. For example to restore only a specified index from a backup file:

>   
> pg_restore -U $username --dbname=$dbname --index=$indexname   
> 

If you wanted to restore only a single function:

>   
> pg_restore -U $username --dbname=$dbname --function=$functionname(args)   
> 

If you wanted to restore only a single table:

>   
> pg_restore -U $username --dbname=$dbname --table=$tablename   
> 

For more information on all the pg_dump options, please see [the reference page.](<http://www.postgresql.org/docs/8.4/static/app-pgdump.html>) **Restoring the dump** The command used to restore a backup file is pg_restore. It has similar options to pg_dump. A simple restore:

> pg_restore -U$username --dbname=$databasename $filename

Where filename is the name of the backup file.

> Do not confuse --file with $filename. The --file option is used to turn a custom format backup into a plain text backup. The value of --file will be used as the output file for that transformation.

If you make the mistake of creating a plain text backup, pg_restore can not be used as a restoration mechanism. You can use psql to restore it:

> psql $dbname < $backupfile

 **Backing up every database** The "postgresql" way of backing up every database is to use the command pg_dumpall. Unfortunately pg_dumpall can only create plain text backups and should be considered deprecated. However it is the only way to backup the globals in your cluster. A reasonable backup strategy to backup your globals and produce a flexible backup of every database in the cluster would look like this:

>   
>   
> pg_dumpall -g -U$username --file=$globals.sql;   
> psql -AtU postgres -c "SELECT datname FROM pg_database \   
>  WHERE NOT datistemplate"| \   
> while read f;   
>  do pg_dump -Upostgres --format=c --file=$f.sqlc $f;   
> done;  
> 

If someone knows of some Windows code that produces a similar result, it would be great if you would share.

> Remember, pg_dumpall creates a plain text backup. This means you will need to use psql to restore the globals backup file.

After restoring a backup, make sure you run ANALYZE to update the statistics. I know this isn't as comprehensive as it could be, but hey, its just a blog.

---
[View this page online](https://www.commandprompt.com/blog/a_better_backup_with_postgresql_using_pg_dump/)

---

# Multiple Drupal installations, single login, 10 steps

> We have several Drupal sites, no I am not typing this blog on one. We needed a way to have single sign on with these Drupal sites. One of which is PostgreSQL C…

We have several [Drupal](<http://www.drupal.org/>) sites, no I am not typing this blog on one. We needed a way to have single sign on with these Drupal sites. One of which is [PostgreSQL Conference](<http://www.postgresqlconference.org/>). There are a few modules out there that can do it, some don't work with PostgreSQL, some are usable but not user friendly (HTTP AUTH) and still others use external services such as OAuth. I didn't want any of these. I wanted a simpler, more flexible solution. I found it with a little PostgreSQL know-how and a modification to the Drupal settings.php file. The following is ten steps that assume we have three sites. At the end of the steps we will have single login between the three sites.. **Step 1: Create users**
    
    
    psql -U postgres;
    create user one with encrypted password 'foo';
    create user two with encrypted password 'bar'
    create user three with encrypted password 'baz';
    

**Step 2: Create database and schemas**
    
    
    create database drupal;
    \c drupal -- (assumes the use of psql)
    create schema one authorization one;
    create schema two authorization two;
    create schema three authorization three;
    

**Step 3: Sandbox users**
    
    
    alter user one set search_path = 'one';
    alter user two set search_path = 'two';
    alter user three set search_path = 'three';
    

**Step 4: Install Drupal** For the sake of brevity I am going to assume you have unpacked three copies of drupal in the same directory. Perhaps /home/www/one, /home/www/two, /home/www/three . At this point you would use your web browser and set up drupal normally. Just assign your users appropriately to each install and set your database to drupal. **Step 5: Turn off caching (for testing)** Go into the Drupal Administration pages and turn off caching for every install. **Step 6: Alter users and sessions location** This will break your installs initially. Don't fret. It does not really matter which one you pick but for consistency we will assume that the drupal install **one** is the canonical version.
    
    
    alter table one.users set schema public;
    alter table one.sessions set schema public;
    

**Step 7: Fix perms**
    
    
    create role drupal user one,two,three;
    alter table users owner to drupal;
    alter table sessions owner to drupal;
    grant insert,update,delete on users to drupal;
    grant insert,update,delete on sessions to drupal;
    

**Step 8: Modify settings.php** Drupal offers the ability to use a single database for multiple installs using an array called db_prefix. Modify the value in each install to:
    
    
    $db_prefix = array('users' => 'public.',
                     'sessions' => 'public.',);
    

**Step 9: Test** At this point you should be able to login to each site using the user/pass from the **one** install. To test it further add a new user to any of the installs and see if you can login on a different one. **Step 10: Marvel (Oh and turn back on caching)** That's right, marvel. No obnoxious plugins. Simple overhead. Works even if the installs aren't on the same machine (although you would need to modify pg_hba.conf and possibly postgresql.conf).

---
[View this page online](https://www.commandprompt.com/blog/multiple_drupal_installations_single_login_10_steps/)

---

# Let the jokes begin! PostgreSQL Conference West has changed locations.

> About a week ago I announced PostgreSQL Conference West 2010 CFP. In that CFP I also announced the location. A nice place, the Westin at Union Square in San Fr…

About a week ago I announced [PostgreSQL Conference West 2010 CFP.](<http://www.postgresqlconference.org/>) In that CFP I also announced the location. A nice place, the Westin at Union Square in San Francisco. We were excited, the hotel was top knotch.

Then on Monday I received notice, the hotel acquisitions team ([EDB](<http://www.enterprisedb.com/>)) has received an amazing counter offer from a competing hotel.

The hotel is still in San Francisco, it is a four star hotel and the rate is much better for attendees (159.00 vs. 199.00). Here is the catch, which if you are reading on Planet you have to wait until after the jump.... 

The hotel is the Sir. Francis Drake hotel. Yes, A Drake Hotel. Now, it doesn't matter that I didn't pick this hotel. I have already received remarks from one particularly, getting older every day, [sailing for the next three weeks Swede.](<http://picasaweb.google.com/postgresconf/East2010Speakers#5459462258104388930>) I of course have posted this after he has already left, hopefully the post will be buried beneath 30 other blogs by the time he gets back. 

Now let the fun begin. [If you have not submitted a paper, get on it.](<http://www.postgresqlconference.org/>) West at all indications is going to be twice as big as East (that puts us over 300).

---
[View this page online](https://www.commandprompt.com/blog/let_the_jokes_begin_postgresql_conference_west_has_changed_locations/)

---

# Simpycity now available on Github

> Following up on our brand-new Simpycity 0.3.1 release from earlier today, you&#x27;re now able to get hold of Simpycity via the ever-popular code-sharing platform G…

Following up on our brand-new Simpycity 0.3.1 release from earlier today, you're now able to get hold of Simpycity via the ever-popular code-sharing platform GitHub. Check us out @ [GitHub](<http://github.com/commandprompt/Simpycity>), and track all the [Command Prompt projects](<http://github.com/commandprompt/>)!

---
[View this page online](https://www.commandprompt.com/blog/simpycity_now_available_on_github/)

---

# Announcement: Simpycity 0.3.1 Released

> Following up on the blog post covering the new coolness in 0.3, and better docs on working with Simpycity, we&#x27;ve just released Simpycity 0.3.1, our best releas…

Following up on the blog post covering the new coolness in 0.3, and better docs on working with Simpycity, we've just released Simpycity 0.3.1, our best release yet! Simpycity can be [downloaded from our Wiki](<http://public.commandprompt.com/projects/simpycity/wiki>), and our code is available from the [Subversion repository.](<https://public.commandprompt.com/projects/simpycity/repository>) Finally, starting today, all new releases of Simpycity are available on the [PyPI package index](<http://pypi.python.org/pypi/Simpycity/0.3.1>), and Simpycity installable via: 
    
    
    $ easy_install Simpycity

---
[View this page online](https://www.commandprompt.com/blog/announcement_simpycity_031_released/)

---

# Active Object in Simpycity

> Simpycity is, as we&#x27;ve previously covered, a small library that permits for the direct mapping of arbitrary SQL statements to Python callables. This power allo…

Simpycity is, as we've previously covered, a small library that permits for the direct mapping of arbitrary SQL statements to Python callables. This power allows for the development of complex representations that do not need to directly map to the underlying database representation. This differs from most conventional ORM technology, which follows the ActiveRecord pattern. Simpycity was implemented in this way for a great many reasons, first and foremost that the Active Record pattern is not the best representation of your data to your application logic. Should the application need to be aware of underlying data relationships? Should the application be aware of foreign keys, structures, and other underlying constructs? Or should the application be able to interact with the data in a form that is logical, and sensible to the application, without needing deep knowledge of underlying representations? We thought so, and Simpycity, and a concept more along the lines of Active Object is our result. 

#### Disparate Representations

Simpycity, instead of writing SQL for you via query generators, requires that the developer write SQL by hand. The reason for this is that database representations are not generalizable into object relations - this disconnect is the entire reason behind the object-relational difficulties. A proper object representation encapsulates all the possible information about a method in a single location, as well as all the necessary methods to act on that data. A single object then represents a single quantum of data. However, for a relational system, normal form requires that disparate pieces of information are further broken down, into points of absolute truth about the data. A person's name, for instance, is a point of absolute truth, and should exist in only a single place in the database, whereas a person's name could exist in several places in an Object system, in a sensible manner. The disparity comes in that a Person, in terms of business requirements, is rather different from a Person in SQL terms, to the point where it would not be sensible to represent a database Person as an object Person - Address information, birthdate, all sorts of ancillary data that would normally be present isn't, per correct normal form. Simpycity works to avoid this, by allowing for business models that have little if anything in common with the underlying table structure, allowing for proper normalization as well as useful business objects. 

#### Forging Anew

As Simpycity does not impose the database structure on your objects, it can't immediately provide the functionalities of .new() in the way a conventional ORM can - even though we've seen Simpycity handle the .save() feature brilliantly. Instead, if you instance a Simpycity model, not from the database, you get precisely and only a Simpycity instance. As it's not connected to a known set of database data, all the functions and other associated items have no way of operating, and the model just sits there, forlorn and empty. But since we have to match the Active Record pattern, how would we go about providing .new() in Simpycity? Here's how we do it: Given a standard model that looks like this, 
    
    
    class model(ctx.Model()):
         table = ['id','name']
         __load__ = ctx.Function("load_obj", ['id'])
    

We're able to do simple and basic load operations. Right? But, to create a new object, the pattern more resembles: 
    
    
    class model(ctx.Model()):
    ...
    
    new = ctx.Function("new_obj",['name'], return_type=model)
    

Which allows for the external interface of: 
    
    
    import yourmodel
    o = yourmodel.new("Some name")
    o.commit()
    

Providing a clean and sensible model API, following the ActiveRecord pattern, but still offering all the power of Simpycity. 

#### Twisty Little Properties

Another very nifty capability of ActiveRecord systems is that of reflection, automatically retrieving the far end of a foreign key constraint. This allows for useful functionality like 
    
    
    aModel.comments
    

correctly reaching across the one-to-many relationship and pulling all the comments. As Simpycity doesn't directly map tables, capabilities such as this aren't directly implemented in Simpycity. However, since we do realize that business objects need to perform similar tricks and load data in via properties, we added specific support for this into Simpycity. But, since Simpycity is entirely callable based, we had to be able to support this feature with our existing metaphors. To that end, we included a simple function that will take any Simpycity callable (or any callable, really), interrogate its argument list, and handle argument mapping as you'd expect. Using this feature is as simple as: 
    
    
        from simpycity.helpers import prop
        
        class myTextObject( ctx.Model() ):
            table = ['id', 'value']
            __load__ = ctx.Function("textobject.by_id",['id'])
            comments = prop( get=ctx.Function("textobject.comments", ['id']) )
            
        mto = myText(1)
        comments = mto.comments
    

Easily allowing for sensible properties to be created, based entirely on clean Simpycity code. Properties created in this way even support set and delete functionality, identical to a standard property, allowing for property accessors to easily manipulate the database layer. As a note, prop() is a new feature in 0.3.1. 0.3.0 and below should use 
    
    
        from simpycity.helpers import sprop
        
        class myTextObject( ctx.Model() ):
            ...
            comments = property(sprop( get=ctx.Function("textobject.comments", ['id']) ))
    

Obviously not as clean, and not as capable. You should upgrade ASAP. 

#### Next

We've stabilized the API, made everything work through the consistent Context interface, and have built a powerful callable-based model infrastructure for all sorts of application development. So what's next for Simpycity? Well, some of the things we're planning on include breaking the Model object away from [psycopg2](<http://initd.org/psycopg/>) dependency, allowing us to use other PG drivers (such as pg8000), as well as opening up the Model protocol we've defined for other contexts - file access, for instance. Anywhere that an application needs to represent a complex underlying structure as a simple object, the Model could be used. More in the future, we're really looking forward to integrating Simpycity callables with Django and SQLAlchemy model objects, using Simpycity to provide strong, clean functional and raw query support in those environments. And vice-versa as well: Binding a SQLAlchemy or Django ORM chain to a Simpycity object, using it to populate an object, and building even more complex, effective business objects for your application. Even farther afield, we've been looking at integrating query generation to Simpycity. There's a lot of boilerplate SQL that needs writing, and being able to hand it to an elegant, PostgreSQL-focussed abstraction would be, we think, ideal. As always, Simpycity is [available on our Wiki](<http://public.commandprompt.com/projects/simpycity/wiki>), and our code can always be checked out from [our Subversion repository.](<https://public.commandprompt.com/projects/simpycity/repository>) Finally, Simpycity is easily installed from the [PyPI ](<http://pypi.python.org/pypi/Simpycity/0.3.1>) index, using easy_install Simpycity.

---
[View this page online](https://www.commandprompt.com/blog/active_object_in_simpycity/)

---

# PgWest 2010: Call for Papers

> PostgreSQL Conference West, The PostgreSQL Conference for Decision Makers, End Users and Developers, is being held at the St. Francis, Westin Hotel in San Fran…

PostgreSQL Conference West, The PostgreSQL Conference for Decision Makers, End Users and Developers, is being held at the St. Francis, Westin Hotel in San Francisco from November 2nd through 4th 2010. [Submit your talk.](<http://www.postgresqlconference.org/2010/west/cfp>)

### Time line:

> July 14th: Talk submission opens Sept 5th: Talk submission closes Sept 10th: Speaker notification 

This year we will be continuing our trend of covering the entire PostgreSQL ecosystem. We would like to see talks and tutorials on the following topics: 

  * General PostgreSQL: 
    * Administration 
    * Performance 
    * High Availability 
    * Migration 
    * GIS 
    * Integration 
    * Solutions and White Papers 
  * The Stack: 
    * Python/Django/Pylons/TurboGears/Custom 
    * Perl5/Catalyst/Bricolage 
    * Ruby/Rails 
    * Java (PLJava would be great)/Groovy/Grails 
    * Operating System optimization (Linux/FBSD/Solaris/Windows) 
    * Solutions and White Papers 
[Submit your talk.](<http://www.postgresqlconference.org/2010/west/cfp/>)

---
[View this page online](https://www.commandprompt.com/blog/pgwest_2010_call_for_papers/)

---

# Cool Features I'm Looking Forward to in PostgreSQL 9.0

> Recently, I was able to attend the local PostgreSQL community meeting here in Portland, and the topic du jour was covering the nifty and interesting features t…

Recently, I was able to attend the local PostgreSQL community meeting here in Portland, and the topic du jour was covering the nifty and interesting features that are found in PG 9.0. Confessing that I haven't really been paying close attention to what's new in 9.0, the talk was incredibly interesting - covering a range of new features in 9.0.The ones I'm really excited about are: **/contrib/passwordcheck** This newly-added contrib module adds that feature that sysadmins are going to love - being able to add stronger password-based restrictions to the default PG password requirements. You know the sort I mean - must be a mixture of capitalized and non, must be at least one number, must be at least _n_ digits long.  
  
This is exceptionally useful if you're in an environment with strong password requirements. **samehost and samenet** These pg_hba.conf administration conveniences allow you to match any IP address that the server owns (same host) or any subnet that the server is a part of (same net). This'll be very useful for any multi-homed DB server that needs to listen on all its interfaces; as well as providing an easy way to just say "all my peers" without explicitly needing to remember and declare the IP subnet. **Parameter change logging** This is a fairly useful change for anyone who's tried to figure out what changed during the last reload of PG. Instead of wondering, you can now configure a logging setting to report what parameters from the config were changed, what they were changed to, and what changes require a full restart before they can be used. **EXPLAIN now machine-readable** This is an amazingly useful feature, especially when combined with auto_explain - you'll now be able to get explain output in XML, JSON or YAML, allowing for easy parsing, manipulation and comparison of the EXPLAIN output.   
  
This also allows for transformation of the output - easily converting it to HTML, for instance. Easy comparison before and after an index is created, simplifying programmatic discovery of indexes. **WHEN clause in triggers** WHEN clauses in triggers add a new level of power to the trigger system, by allowing PG to handle the large block of IF statements we always have in our triggers. This should allow us to see a major performance boost for any conditional triggers, since PG doesn't have to descend to the trigger stored procedure for every modification. **NOTIFY now takes a string argument** Instead of just getting the notification from your database, you'll now be able to pass an optional string. With a clever sproc and some clever string formatting, you can now pass useful information to the NOTIFY receiver, saving yourself from excess work in figuring out what's changed. Simpler event-driven programming? Never a bad thing. **Named parameters in stored procedures** This is huge for Simpycity. On 9.0, we can now handle argument naming in a whole new way: 
    
    
    SELECT * FROM my_func(param='string', another_param=3);
    

Being able to run queries like this will easily simplify Simpycity - just name your arguments the same in both Python and PostgreSQL, and everything will Just Work, clean and simple. Keep an eye out for this update - I can't wait to add support in Simpcyity. Keep an eye out for the updates on the [Simpycity project page](<http://public.commandprompt.com/projects/simpycity/>) **So Much More!** Of course, this is just a subset of the interesting things - the bits I'm really looking forward to. You should go have a look at the whole list, easily found on [the Illustrated Postgres 9.0 Wiki](<http://wiki.postgresql.org/wiki/Illustrated_9_0>).

---
[View this page online](https://www.commandprompt.com/blog/cool_features_im_looking_forward_to_in_postgresql_90/)

---

# PostgreSQL High Availability options

> PostgreSQL is widely accepted as the most scalable and stable Open Source database in the industry. It is also known to hold its own against any of the proprie…

PostgreSQL is widely accepted as the most scalable and stable Open Source database in the industry. It is also known to hold its own against any of the proprietary databases as well. There are a plethora of High Availability options available for every workload and business requirement. Below is a brief listing of the common High Availability options for PostgreSQL. This is by no means an exhaustive list but it does provide some starting points. (and before anyone yelps, 9.0 isn't out yet) **Log Shipping:** Also known as streaming replication and Point in Time Recovery, log shipping is a great mechanism for creating a Highly Available requirement. Log shipping is the least administrative overhead solution for a number of business requirements including: 

  * DDL Replication 
  * Zero load backups 
  * Failover 
  * Geographically disparate servers 
  * You have an existing application that can not be modified 
  * No read-only slave requirement



> Solutions include: PITRTools, Walmgr 

**Async Replication:** Asynchronous Replication provides a Master->Slave (also known as Origin->Subscriber) model of replication. Asynchronous Replication for PostgreSQL is an excellent option if your business requirements include: 

  * Few DDL changes (or Managed DDL changes) 
  * Read from Slaves 
  * Geographically disparate servers 
  * Failover or Switchover capability 
  * Zero load backups



> Solutions include: Replicator, Londiste, Slony 

**Block Replication:** Block level replication can be Synchronous or Asynchronous. It provides the lowest level of replication between two (or more) systems. In short it replicates disk blocks as they are modified, over the network the the receiving system. This type of replication is particularly useful for a true HA zero data loss scenario. Consider this option if your business requirements include: 

  * Zero data loss 
  * You do not need to read from the slave 
  * You do not want to offload backups 
  * Your slave/standby is in the same data center (synchronous)



> Solutions include: DRBD (Linux) 

Also note that any of the solutions may be used in conjunction with another solution. Thus you may use Block replication, but also have log shipping for a warm standby. If you have further questions, please do not hesitate to [contact us.](<http://www.commandprompt.com/contact>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_high_availability_options/)

---

# Scala... really?

> I am not writing this to jump all over Big Jim&#x27;s post but after reading it and seeing the syntax of Scala (and Java), I can&#x27;t help but wonder, why anyone would…

I am not writing this to jump all over [Big Jim's post](<http://blogs.enterprisedb.com/2010/07/08/scala-postgresql-access/>) but after reading it and seeing the syntax of Scala (and Java), I can't help but wonder, why anyone would use either language (based on syntax). Yes I know it is a matter of taste and everyone has an opinion. Let's just say my taste lean toward more succinct code. 
    
    
    #!/usr/bin/python
    #
    # Set up initial work
    #
    
    import psycopg2
    conn = psycopg2.connect("dbname='postgres' user='postgres'")
    cur = conn.cursor()
    cur.execute("SELECT * FROM pg_database")
    
    def output(cur):
    #Run two queries, one for headers, one for data
        tuples = cur.fetchall()
        
        colname = [x[0] for x in cur.description]
        buff = "\t" + "\t".join(colname[0:4]) + "\n"
    
        for row in tuples:
             # This is a little one liner but could easily be expanded 
             # for readability
             buff += "\t" + "\t".join([str(i) for i in row[0:4]]) + "\n"
        return buff
    
    print output(cur)
    

I keep looking back at Java merged/derived/munged/glued languages, [Groovy](<http://http://groovy.codehaus.org/>) looks interesting and of course there is [Jython](<http://www.jython.org/>) but I think I will stick with good old fashion CPython just as I am sure that [MST](<http://www.shadowcat.co.uk/blog/matt-s-trout/>) will stick with Perl.

---
[View this page online](https://www.commandprompt.com/blog/scala_really/)

---

# PostgreSQL 7.4, 8.0 and 8.1 END OF LIFE

> If you are running any version of PostgreSQL 7.4, 8.0 or 8.1, it is now time to upgrade to 8.3 or 8.4. The versions 7.4 and 8.0 are slated for end of life at t…

If you are running any version of PostgreSQL 7.4, 8.0 or 8.1, it is now time to upgrade to 8.3 or 8.4. The versions 7.4 and 8.0 are slated for end of life at the end of this month. The 8.1 version is slated for end of life in November. This is not an item to take lightly. Once a version is end of life you will not be able to get support (easily), there will be no more security updates and no bug fixes even if they are data loss bugs. I often find it disturbing how many people will run older releases. I am not talking about someone running 8.2 when 8.4 is out but we still see the occasional post on the lists about someone running 7.3! Remember folks, at a minimum keep your dot releases updated. The community does not release dot releases on a whim, it is for the protection of your data. Of course, if you need any help with [upgrading don't hesitate to ask.](</contact>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_74_80_and_81_end_of_life/)

---

# WHERE bing = 't'

> I was on #postgresql today and someone asked an interesting question: (edited for readability)I&#x27;m trying to write a constraint for a table. The constraint shou…

I was on #postgresql today and someone asked an interesting question: (edited for readability)

> I'm trying to write a constraint for a table. The constraint should check for unique-ness of two columns, one string and one boolean. However I have special logic, I can have only one row with a given string and true attribute. I can have multiple rows with the same string but with false attribute. For example, I can have many {"abc",false}, but only one {"abc",true}. 

Now why anyone would need this isn't important. This is a great example of PostgreSQL and flexibility. PostgreSQL has the ability to [create partial indices.](<http://www.postgresql.org/docs/8.4/static/indexes-partial.html>) The solution I came up with is below: 
    
    
    create table foo(bar text, bing boolean);
    create unique index baz_index on foobar(bar,bing) where bing = 't';
    insert into foobar values('1','t');
    insert into foobar values('2','t');
    insert into foobar values('1','f');
    insert into foobar values('1','f');
    insert into foobar values('1','t');
    ERROR:  duplicate key value violates unique constraint "baz_index"
    

Exactly as it should be. Excellent.

---
[View this page online](https://www.commandprompt.com/blog/where_bing__t/)

---

# Controlling per-column updates with deny_updates

> One of my favorite features of the upcoming PostgreSQL release is conditional triggers. With minimum efforts one can build per-column triggers by adding a colu…

One of my favorite features of the upcoming PostgreSQL release is conditional triggers. With minimum efforts one can build per-column triggers by adding a column check into the triggering condition. This functionality is already available with [Beta 2 of PostgreSQL 9.0](<http://www.postgresql.org/about/news.1210>). Alas, PostgreSQL doesn't backport features, in order to gain similar functionality in earlier releases you can use deny_updates.

The [deny_updates project on PgFoundry](<http://pgfoundry.org/projects/deny-updates/>) contains PL/Perl and PL/PerlU functions that can be installed as triggers to allow or deny certain types of operations. deny_updates function can block updates to individual table columns. In the example below we'll create 2 tables to model the data for an airport timetable:

`CREATE TABLE flights (flight_no TEXT PRIMARY KEY, departure TEXT, arrival TEXT);`

`CREATE TABLE timetable(flight_no TEXT REFERENCES flights ON UPDATE CASCADE, time TIMESTAMP, status TEXT);`

Let's populate them with test data:

`INSERT INTO flights VALUES('WU917', 'KBP', 'SIP');`

`INSERT INTO timetable VALUES('WU917', '2010-06-19 16:50', 'pending');`

In practice we don't want a flight number in the timetable to be updated for an already existing departure/arrival time and status. With deny_updates we can easily add this constraint to our model:

`CREATE TRIGGER deny_flightno_updates ON UPDATE TO timetable FOR EACH ROW EXECUTE PROCEDURE deny_updates('ALLOW_LIST', time, status);`

Now all attempts to update the flight number will be denied:

`UPDATE timetable SET flight_no='WU918' WHERE flight_no='WU917';`

`ERROR: error from Perl function "deny_updates": update of attribute 'flight_no' denied by the trigger deny_flightno_updates at line 79.`

The value 'ALLOW_LIST' of the first argument indicates that the rest of the argument list contains columns allowed to be updated, and updates to non-listed columns will be denied. To get the opposite, we should leave the first argument empty. Let's use this form to construct a trigger to disallow changes of departure and arrival airports for an already added flight:

`CREATE TRIGGER deny_airport_changes ON UPDATE TO flights FOR EACH ROW EXECUTE PROCEDURE deny_updates('', departure, arrival);`

In practice, sometimes a trigger function has to check values of the OLD and NEW tuples to decide on allowing or blocking the triggering operation. deny_updates project provides a function called 'allow_on_condition', which does exactly that:

`CREATE TRIGGER lock_cancelled_status BEFORE UPDATE ON timetable FOR EACH ROW EXECUTE PROCEDURE allow_on_condition('%s != ''cancelled''', 'OLD.status');`

The first argument of allow_on_condition is a condition, which is evaluated to decide whether the trigger operation should be allowed. The '%s' placeholders are replaced in order with arguments starting from the second, just like in printf. Note that these arguments should be quoted as strings, otherwise PostgreSQL won't recognize them as valid literals due to NEW and OLD prefixes.

The function above forbids changing a flight status once it's set to 'cancelled':

`UPDATE timetable SET status='cancelled';`

`UPDATE 1`

`UPDATE timetable SET status='in flight';`

`ERROR: error from Perl function "allow_on_condition": expression SELECT E'cancelled' != 'cancelled' AS result is false, UPDATE is not allowed at line 71.`

These functions were created by Command Prompt, Inc for [Enova Financial](<http://www.enovafinancial.com>), which kindly decided to open-source them. You can download them and/or leave your feedback at the [project's page on PgFoundry](<http://pgfoundry.org/projects/deny-updates/>)

---
[View this page online](https://www.commandprompt.com/blog/controlling_per-column_updates_with_deny_updates/)

---

# Entering 9 days of PostgreSQL Dimension

> On the 6th, I leave town, travelling again to an unknown land. A land of mystery, a land of great mobster movies and incredible picture opportunities. Of cours…

On the 6th, I leave town, travelling again to an unknown land. A land of mystery, a land of great mobster movies and incredible picture opportunities. Of course, I speak of Chicago where I will be delivering a 5 day training on our illustrious database, PostgreSQL. After the 5 day training, I will be taking a short jaunt to [South East Linux Fest](<http://www.southeastlinuxfest.org/>) where I will be speaking on PostgreSQL Performance. The PostgreSQL Performance talk has been getting increasingly popular. I attribute the popularity to a couple of things. One, I don't get mired in the academics of performance. It isn't about finding that final Gentoo inspired 2%. It is about solving the 90% problem. What are the meat and potatoes of PostgreSQL performance and provisioning? It seems especially popular with those who don't want to be a DBA but still want to be confident that their installation is doing a above average job of being configured. A lot of database people at this point are going, "Excuse me? Above Average? It must be exacting in its performance profile!". I say bosh. Give me a great performing database that is above average so I can actually be productive chasing squirrels through New York's central park over agonizing over that 2% any day. Here is a tip. If you want that extra 2% and you want it quickly, buy new hardware. Don't spend weeks of man hours trying to find it.

---
[View this page online](https://www.commandprompt.com/blog/entering_9_days_of_postgresql_dimension/)

---

# Simpycity 0.3.0

> It&#x27;s been a long time since we shipped the first version of Simpycity, a long time since we&#x27;ve really discussed how it works and how to get the most of it.

…

It's been a long time since we shipped the first version of Simpycity, a long time since we've really discussed how it works and how to get the most of it. Over the next couple of articles, I'm going to be discussing how we're using Simpycity internally, some ideas that we have going forward, and how you too can benefit. Since we're just shipping Simpycity 0.3 now, we should go over some of the excellent new features available now. 

### Contexts

A bug we kept running into in Simpycity was related to Python's object lifecycle. Time and time again, our connections weren't being closed properly, held on to for far longer than they were useful. We tried to fix this in 0.2 with the Manager, but that wasn't successful. While excellent in theory, a Manager would only run at the end of a given transaction, while a particular loop that spawned a lot of Simpycity objects could still easily exhaust our connection pool. To combat this, we have implemented the Context. A Context is the object from which all modern Simpycity functionality derives, and it is used like this: 
    
    
    from simpycity.context import Context
    
    ctx = Context(dsn="database=%s user=%s password=%s" % (database, username, 
    password))
    

Now, any standard Simpycity object can be constructed through the Context, and a single Context will keep all objects spawned from it under a single database connection. No more weirdness with resource exhaustion, and no more using the admittedly inconsistent simpycity.config object system. **Basic Queries** Now that we have a single, unified Context, spawning our basic primitives is just as easy, simply: 
    
    
    my_sproc = ctx.Function("my_getter",['id'])
    

or, for raw SQL: 
    
    
    my_raw = ctx.Raw("SELECT * FROM my_table")
    

Just as easy as Simpycity has ever been. 

### Models

Spawning models is, again, just as easy in Simpycity 0.3 as it has been in previous versions, though we now have some truly useful knowledge on how to use a Simpycity model effectively and with even greater ease than before. For starters, the ability to get a column value from a model was limited at best. There was no default mechanism to load the value on a simple **model.column** request. As of 0.3.1, this has changed. **model.column** is now supported by default on all Simpycity models. Not only that, but we now support setting columns in the same fashion: 
    
    
    model.column = "a new value"
    

But, it doesn't normally propagate to the database. We're only manipulating an object within Python itself, not the underlying schema. For that, we require a save mechanism. Classically, Simpycity models assumed that manipulating the underlying database would occur via procedures, .Raw or .Function methods bound to the object. While this is still an excellent metaphor, it does incur a penalty of several modifications each requiring a round-trip to the database; hardly an efficient mechanism. 

### A Save Mechanism

To add a more efficient mechanism to Simpycity, models now, by default, offer the .save() mechanism. This functionality works in two simple, easy parts. The first requires that the model have a new bound method, specifically: 
    
    
    class myModel(ctx.Model()):
         table = ['id','value']
    
         __save__ = ctx.Function("update_table",['id','value'])
    

Then, on a model, one may: 
    
    
    >>> m = myModel(1)
    >>> m.value
    'a Value'
    >>> m.value = 'New Value'
    >>> m.value
    'New Value'
    >>> m.save()
    >>> ctx.commit()
    

Thusly updating a simple model, to the database, easily and compactly. By defining __save__ on a Simpycity model, it is simple and easy to succinctly save data in a consistent fashion. For more complex save mechanisms, the standard Simpycity bind functionality remains, allowing for a model to host arbitrary functions that are able to read the underlying columns, as so: 
    
    
    class model(ctx.Model()):
       table = ['id','value']
    
       comments = ctx.Raw("SELECT * FROM comments WHERE table_id = %s",['id'])
    

Which is then called via: 
    
    
    m = model(1)
    comments = m.comments()
    

### Loading from the Database

As demonstrated above, Simpycity's models are able to save easily and quickly, in a fully customized fashion. But what of loading data, an equally crucial part of the Model interface? In this instance, Simpycity offers several mechanisms to allow for easy loading of data from your database. First, each Model allows for a method to be run when the model is instanced, IF the model is instanced with an argument. Therefore, a model instanced as: 
    
    
    m = model()
    

would create an empty object from the base class, and would in general be unable to save itself to the database with any ease. However, if we were to do this: 
    
    
    class model(ctx.Model()):
       table = ['id','value']
       comments = ctx.Raw("SELECT * FROM comments WHERE table_id = %s",['id'])
       __load__ = ctx.Raw("SELECT * FROM my_table WHERE id = %s",['id'])
    
    
    m = model(1)
    

then Simpycity will execute __load__ during the model instance, loading the record from the database as expected. This model is now able to be modified as described above, via the normal save functionality. The second method that Simpycity provides for loading data is via the standard primitives, Raw and Function. By providing a "model=" argument (previously "return_type"), returned rows from the query will be mapped into the provided model object. This functionality can be used in multiple ways; first, to add functions to a model that return other models, such as: 
    
    
    class Comment(ctx.Model()):
         table = ['id','owner','user']
    
    class table(ctx.Model()):
         table = ['id','value']
         comments = ctx.Raw("SELECT * FROM comments WHERE table_id = ?", 
    ['id'], model=Comment)
    

And thus, by doing: 
    
    
    m = table(1)
    cmts = m.comments()
    for comment in cmts:
         # Something interesting with each comment object.
    

allowing for many-to-many relationships to be easily and elegantly expressed. Furthermore, the model= argument to a primitive can be used to implement alterative loading mechanisms, bypassing the general __load__ method. By performing: 
    
    
    class table(ctx.Model())
         table = ['id','value']
    
    by_id = ctx.Function("table.by_id",['id']. model=table)
    by_value = ctx.Function("table.by_value",['value'],model=table)
    

it is easy to declare alternative instancing mechanisms, that fully match your business model requirements. Next, we'll be covering to the best practises for full model packages, providing additional loading methods cleanly and easily - a structure we've taken to calling Active Object, as opposed to Active Record. And, as always, you can get Simpycity from [the Wiki](<https://public.commandprompt.com/projects/simpycity>) or [the repository](<https://projects.commandprompt.com/public/simpycity/repo/>).

---
[View this page online](https://www.commandprompt.com/blog/simpycity_030/)

---

# Ubuntu LTS 10.04 is here! Well not really but I thought I would sound excited.

> I am an avid Ubuntu user. I like their philosophy. I like their code of conduct. I like what they are trying to do with Linux as a whole. I invite everyone to …

I am an avid Ubuntu user. I like their philosophy. I like their code of conduct. I like what they are trying to do with Linux as a whole. I invite everyone to use Ubuntu. Unfortunately I have been unable to upgrade from Karmic. Why? Well, update-manager -d doesn't work because of some error with ubunut-minimal which (yes I researched it) was supposedly fixed, but it isn't. Yay!

I figured, no big deal. I will just download the ISO. I have 20Mb here, it only takes a couple of minutes. Download, burn, reboot, hit F8, select CDROM, ooohhhh, prettty purple.

Wait, what? What do you mean there are no operating systems on this computer!? (Minor heart attack) Oh, that's right, Ubuntu is still ignorant about Software RAID unless you are using the server ISO.

Sigh, I don't have time for this. You know what... My Windows 7 Laptop "just works".

---
[View this page online](https://www.commandprompt.com/blog/ubuntu_lts_1004_is_here_well_not_really_but_i_thought_i_would_sound_excited/)

---

# CodeCamp PL/Perl talk

> Last week I delivered a PL/Perl talk at CodeCamp conference in Kyiv, Ukraine.
The conference has been held at Kyiv Polytechnic Institute, which is one of
the…

Last week I delivered a PL/Perl talk at [CodeCamp](<http://codecamp.org.ua/>) conference in Kyiv, Ukraine. The conference has been held at Kyiv Polytechnic Institute, which is one of the top technical schools in Ukraine, so there were both really smart students and seasoned engineers. I talked about Perl inside PostgreSQL, deciding to highlight interesting features of PL/Perl with examples, hopefully covering most of them. Some of the attendees used PostgreSQL in production for years and were really impressed with its reliability and effectiveness, but most of them were not very familiar with it. I feel that PUGs are almost non-existent in CIS (with a nice exception of Moscow PostgreSQL user group, kudos to Nikolay), so we still have a lot of work to do on that front :) The slides are [here](<http://files.me.com/alexeyk/r6h9jv>) (in Russian, but most of them are PL/Perl examples, so language doesn't matter that much as long as you understand Perl :) ). I had a couple of very interesting conversations after the talk about upcoming features in 9.0, and one of the students was actually inspired to develop a a new PL/ language. I'm looking forward for more opportunities to make PostgreSQL more popular in Ukraine and CIS !

---
[View this page online](https://www.commandprompt.com/blog/codecamp_plperl_talk/)

---

# Off to Linux Fest Northwest

> The great folks of Linux Fest Nortwest are hosting a PostgreSQL Track again this year. I will be speaking twice. First on what has ended up being a very popula…

The great folks of [Linux Fest Nortwest](<http://www.linuxfestnorthwest.org>) are hosting a PostgreSQL Track again this year. I will be speaking twice. First on what has ended up being a very popular utility, [PITRTools](<https://public.commandprompt.com/projects/pitrtools/wiki>). My second talk will be on Dumb Simple PostgreSQL Performance, which has been very popular with user groups. I look forward to seeing everyone again.

---
[View this page online](https://www.commandprompt.com/blog/off_to_linux_fest_northwest/)

---

# PgEast... over and an exciting announcement from the .Org infrastructure team

> So PgEast is over. You wouldn&#x27;t know it yet by looking at the website, but it is. We maxed out at ~ 160 people. That is an almost 2x increase over last year at…

So PgEast is over. You wouldn't know it yet by looking at the website, but it is. We maxed out at ~ 160 people. That is an almost 2x increase over last year at East. It is also a significant increase over West last October. This is an exciting time for this conference series. 

The trainings were also successful, I had 19 (of a max 20) show for my Performance and Maintenance class, and I know the other classes had similar attendance. 

Due to the success of East, we are going to be moving West to a hotel as well. There was overwhelming support for not returning to a college. Although most were supportive of the reason we used colleges in the past, they were also firm in their belief that further growth of the conferences will require a step up into the professional realm. That means a hotel. 

There was also an exciting infrastructure announcement from the .Org sysadmin team. Core team member, Dave Page announced in his talk that .Org will be moving from FreeBSD and jails to Debian Linux and virtualization. This is a long time needed change and I am very glad to be part of the team that will be assisting in this move. I believe that this change will help us entice more people to be part of the sysadmins team and allow for a more diversified and flexible infrastructure.

---
[View this page online](https://www.commandprompt.com/blog/pgeast_over_and_an_exciting_announcement_from_the_org_infrastructure_team/)

---

# 14 days... and the Hotel is almost full for PostgreSQL Conference East

> I called the our hotel representative today because I was confused about why we had a deadline of 03/11 on the room discount. I was trying to push them to exte…

I called the our hotel representative today because I was confused about why we had a deadline of 03/11 on the room discount. I was trying to push them to extend the date because we had met our room quota and I was wondering why they were trying to shut down the discount. Apparently, not only have we met our room quota, but the hotel is reaching capacity!

If you have not booked your hotel room for [PostgreSQL Conference East 2010](<http://www.postgresqlconference.org/>), now is definitely the time! If you do not book soon, you will be staying at another hotel (of course, you are still welcome to the conference). 

  * [Hotel Information](<http://www.postgresqlconference.org/east/2010/accommodations>)
  * [Register](<https://www.postgresql.us/purchase>)

---
[View this page online](https://www.commandprompt.com/blog/14_days_and_the_hotel_is_almost_full_for_postgresql_conference_east/)

---

# 15 days... and it all begins, PostgreSQL Conference East

> As we continue the countdown to the largest community and user conference in PostgreSQL history I am reminded of all the great content we have had in the past.…

As we continue the countdown to the largest community and user conference in PostgreSQL history I am reminded of all the great content we have had in the past. Today while I was reviewing the curriculum for the [PostgreSQL Performance and Maintenance](<http://www.postgresqlconference.org/2010/east/training/postgresql_performance_maintenance>) class, I came across this great talk by Bruce Momjian as a further example of the high quality information you will receive not only from the various trainings but also all the other (over 50!) sessions at [PostgreSQL Conference East!](<http://www.postgresqlconference.org/>)

Inside PostgreSQL Shared Memory

---
[View this page online](https://www.commandprompt.com/blog/15_days_and_it_all_begins_postgresql_conference_east/)

---

# PostgreSQL Conference East, Hotel Deadline!

> PostgreSQL Conference East, the largest PostgreSQL Conference for Users, Developers, Decision makers and anyone using PostgreSQL arranged for a hotel discount …

PostgreSQL Conference East, the largest PostgreSQL Conference for Users, Developers, Decision makers and anyone using PostgreSQL arranged for a hotel discount for attendees from the Radisson Warwick Hotel (the location of the conference).

The retail price of a double room is ~ 199.00. The discount rate is 132.00.

If you are attending PostgreSQL Conference East and you would like the discount you must register by the 11th of March. For more information:

  * [Accommodations](<http://www.postgresqlconference.org/east/2010/accommodations>)
  * [Agenda](<http://www.postgresqlconference.org/2010/east/agenda>)
  * [List of talks](<http://www.postgresqlconference.org/2010/east/talks>)
  * [Register](<https://www.postgresql.us/purchase>)

Many thanks to our Premiere and Gold Sponsors:

  * [Command Prompt, Inc.](<http://www.commandprompt.com/>)
  * [EnterpriseDB](<http://www.enterprisedb.com/>)
  * [OmniTI](<http://www.omniti.com/>)
  * [OTG](<http://www.otg-nc.com/>)
  * [Red Hat](<http://www.redhat.com/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_hotel_deadline/)

---

# 5 Steps to PostgreSQL Performance

> As we inch closer to PostgreSQL Conference East, I have been reviewing some of the great talks given at PostgreSQL Conference West. One of those talks was Josh…

As we inch closer to [PostgreSQL Conference East](<http://www.postgresqlconference.org/>), I have been reviewing some of the great talks given at PostgreSQL Conference West. One of those talks was Josh Berkus's great, "5 Steps to PostgreSQL Performance". Here it is below:

---
[View this page online](https://www.commandprompt.com/blog/5_steps_to_postgresql_performance/)

---

# PgEast Talks posted

> I blogged last week about a small list of content being up for the conference. I am now pleased to announce that 99% of the topics are up. I would say 100% but…

I blogged last week about a small list of content being up for the conference. I am now pleased to announce that 99% of the topics are up. I would say 100% but I keep getting new talks that look good and am trying to accommodate them as the schedule allows. When I review the talks, I see a lot of good content. Of particular interest to me is the talk from the FAA (yes that FAA) as well as Kevin Grittner's talk on Transaction Isolation. I am also keen on seeing Chander's training class on HS/SR/PITR but unfortunately I will also be teaching on Sunday. I won't be giving the keynote this year. Instead Ed Boyajian, President and CEO of EnterpriseDB will be. This is probably a good choice considering my Keynote is always somewhat of an Un-Keynote. I am curious to see where Ed thinks things are moving and how quickly. I will be doing the Conference launch and closing session. This year we will continue the trend of having a raffle at the end of the conference. If you [haven't registered yet, now is the time.](<http://www.postgresql.us/>)

---
[View this page online](https://www.commandprompt.com/blog/pgeast_talks_posted/)

---

# Content, Content, Content... Oh My! (PgEast)

> When we moved PostgreSQL Conference East (register here)from a three day to a four day conference, I was concerned about our ability to pull it off. Primarily …

When we moved PostgreSQL Conference East ([register here](<http://www.postgresql.us/purchase>))from a three day to a four day conference, I was concerned about our ability to pull it off. Primarily our conferences have been centered about the who's who of PostgreSQL. A nice mix of known contributors and avid users. A lot of the users, we would already knew as they contribute on the lists.   
The migration to four days caused a need to expand our base. We actively starting soliciting from decision makers, educators, users and community contributors. I also know that several of our sponsors have been doing the same. So far it has paid off, we have more registrations at this point, than we have had at any other point historically for one of the PostgreSQL Conferences. The change seems to have been a true blessing.   
The influx of talks has been amazing. We don't have them [all up yet but you can get a taste here.](<http://www.postgresqlconference.org/2010/east/talks>) What I find truly great, is the amount of diversity in the talks. We have case studies from [Vonage](<http://www.vonage.com/>), in depth security talks from Magnus Hagander, Advanced talks on Transaction Isolation; even Core member Dave Page is crossing the pond to talk about the PostgreSQL Infrastructure. There seems no better time to hit [the PostgreSQL Conference series](<http://www.postgresqlconference.org/>) than now. There is going to be content for everyone.   
We have also kept up our promise to integrate tertiary communities into the conference with content on PostGIS, PHP, Python, Ruby and Grails.   
I was truly skeptical of the conference change. My hat is off to Platinum Sponsor [EnterpriseDB](<http://www.enterprisedb.com/>) for convincing me it was a good idea.

---
[View this page online](https://www.commandprompt.com/blog/content_content_content_oh_my_pgeast/)

---

# PostgreSQL Conference East: Early Bird registration is open, classes announced

> As everyone already knows, PostgreSQL Conference East is happening on March 25th through March 28th in Philadelphia. However, what is new is, early bird regist…

As everyone already knows, [PostgreSQL Conference East](<http://www.postgresqlconference.org/>) is happening on March 25th through March 28th in Philadelphia. However, what is new is, [early bird registration is now open](<http://www.postgresql.us/purchase>) and we have confirmed the three classes that will be taught on Sunday the 28th. 

  * [PostgreSQL Administration](<http://www.postgresqlconference.org/2010/east/training/postgresql_administration>) by Bruce Momjian. 
  * [PostgreSQL Performance and Maintenance](<http://www.postgresqlconference.org/2010/east/training/postgresql_performance_maintenance>) by Joshua D. Drake (yes me) 
  * [Point and Time Recovery and Hot Standby](<http://www.postgresqlconference.org/2010/east/training/pitr_hs>) by Chander Ganesan. 

The conference is shaping up to be the largest and most successful U.S. PostgreSQL Conference Yet. I hope you will join us. The [link to register](<http://www.postgresqlconference.org/>) can be found on the main [PostgreSQL Conference site.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_early_bird_registration_is_open_classes_announced/)

---

# Is the response to PgEast a sign of things to come?

> We announced the CFP for PostgreSQL Conference East back in December. Since that time, we have been working diligently to make this the best PostgreSQL Confere…

We announced the [CFP for PostgreSQL Conference East](<http://www.postgresqlconference.org/>) back in December. Since that time, we have been working diligently to make this the best PostgreSQL Conference ever presented in the United States. The signing of Platinum partner [EnterpriseDB](<http://www.enterprisedb.com/>) and the subsequent change of venue has been an exciting foray into a new phase of the PostgreSQL Conference series.

However, what has really surprised me is the number of individual emails I have received from people. Generally speaking, the Conferences East and West are self populating. The community knows the conferences exist. They know it generates funds for [PgUS](<http://www.postgresql.us/>) and [.Org](<http://www.postgresql.org/>). They also know that it is a chance to meet a lot of the contributors, learn and generally just have a good time.

What is new, is the people that are contacting me are not normal members of the community. You are not going to see them on -general or -hackers. These are true End Users. They represent the community, outside the community. What I want to know is where these people are coming from? Are they new to PostgreSQL? Are they exploring new alternatives to legacy databases such as MySQL? Perhaps PostgreSQL is just growing up.

Don't get me wrong, PostgreSQL for many years has far surpassed any open source database in overall capability, performance, management and features. However, the community as a whole has only recently realized the importance of cross pollination to other user groups and not being so anal retentive that all we do is turn off potential users. I think we are starting to see actual pay off there.

As an example, I know SelenaD and JoshB are both speaking at non-traditional conferences about PostgreSQL. For my part, I have been actively speaking at user groups around the Pacific Northwest, including Django, Python and next week Perl. My topic of course is, PostgreSQL Performance.

So, with all the changes in our ecosystem, I invite anyone to contact me about the conference, PgUS or .Org. I would love to just chat, possibly visit your user group or help you find a speaker for your user group.

Don't forget to come to [East. This conference is going to rock!](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/is_the_response_to_pgeast_a_sign_of_things_to_come/)

---

# PostgreSQL Conference East: Change of Venue and Dates

> East 2010 is taking it up a notch! This year, along with Platinum Partner EnterpriseDB, we will be making an aggressive marketing campaign not only to communit…

East 2010 is taking it up a notch! This year, along with Platinum Partner EnterpriseDB, we will be making an aggressive marketing campaign not only to community but also professionals, and decision makers. With this aggressive marketing campaign we have adjusted the conference to be four days, March 25th - 28th. We have also moved from Drexel University to the Radison Plaza, Warwick Hotel. This is to better allow for business professionals outside of our normal community to attend the conference. It is also to allow for the most exposure to potential exhibitors. Yes, I said exhibitors. This year, PostgreSQL Conference East will have a limited exhibit space (13 (of 15) currently available). The exhibit space is within the main hall, where the Keynote, Social area and Food/Beverages will be provided. Please join Command Prompt and EnterpriseDB in making this the largest, most successful PostgreSQL conference ever!

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_change_of_venue_and_dates/)

---

# PostgreSQL Conference East: 2010 Call for Papers

> Call for papers.December 14th, 2009, the PostgreSQL Conference U.S. team is pleased to announce the East 2010 venue and call for papers. This year the premiere…

# Call for papers.

December 14th, 2009, the PostgreSQL Conference U.S. team is pleased to announce the East 2010 venue and call for papers. This year the premiere East Coast PostgreSQL Conference will be returning to history Drexel University in Philadelphia. The event this year is being held at Drexel University in Philadelphia from March 26th through 28th. Following previously successful United States PostgreSQL conferences, we will be hosting a series of 3-4 hour tutorials, 90 minute mini-tutorials, 45 minute talks, 5 minute lightning talks and a new 30 minute presentation time slot. 

# Time line:

  * December 14th: Talk submission opens
  * January 30th: Talk submission closes
  * February 15th: Speaker notification



## [Submit Paper (You must be logged in)](<http://www.postgresqlconference.org/talksubmission>)

This year we will be continuing our trend of covering the entire PostgreSQL ecosystem. We would like to see talks and tutorials on the following topics: 

  * General PostgreSQL: 
    * Administration 
    * Performance 
    * High Availability 
    * Migration 
    * GIS 
    * Integration 
    * Solutions and White Papers 
  * The Stack: 
    * Python/Django/Pylons/TurboGears/Custom 
    * Perl5/Catalyst/Bricolage 
    * Ruby/Rails 
    * Java (PLJava would be great)/Groovy/Grails 
    * Operating System optimization (Linux/FBSD/Solaris/Windows) 
    * Solutions and White Papers 

If you are using PostgreSQL as your platform, you need to be presenting at this conference! [Submit Paper](<http://www.postgresqlconference.org/talksubmission>). (You must be logged in)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_2010_call_for_papers/)

---

# PDXDjango roundup: I finally got my Martini

> Shout out to Mark Long and Lacey Powers for showing up to support a Pg dude in a foreign land. Preceding my talk on PostgreSQL Performance, Adam Lowry gave and…

Shout out to Mark Long and Lacey Powers for showing up to support a Pg dude in a foreign land. Preceding my talk on PostgreSQL Performance, Adam Lowry gave and interesting intro to a database connection pooling module he wrote for Django. Essentially they bolted SQLAlchemy's pooler into Django. He then gave some metrics, showing that through the connection pooler they dropped overall request time in half. It was a basic and good indicator of why connection pooling is good, even on smaller applications. Of course I had to ask, "Why are you doing connection pooling in Django?" and pointed them to pgBouncer. It will be interesting to see if they metric against SQLAlchemy's pooler versus pgBouncer. 

I haven't given a talk since I updated my laptop to Karmic Koala. I was a little concerned, every new release of Ubuntu brings about new surprises on the add a monitor, is the projector working, what is wrong with my laptop front. I will say that this was the easiest talk (in terms of facilities) I have ever given. I plugged in the projector, clicked the display icon, selected accept and it just.... worked. Yes, really. 

Even better, I started OOImpress 3.1, clicked slide show and guess what? The projector displayed my presentation, not my laptop screen. Which means that I can now have notes in the presentation for the me (the speaker) and the presentation on a separate screen. Yes, Mac fan boys I know you have been doing this with Keynote for years but now there is yet another reason I don't have to move to Mac OS X. 

This was the first time I have given the PostgreSQL Performance talk. It went a little faster than I expected so I will have to flesh it out a bit but that is good because there are items I didn't cover. 

The PDXDjango guys seemed very happy with the talk, they even bought me a Martini at Vault. In case you haven't heard my rant yet, France apparently doesn't know how to make a Martini. I was there for 11 days, looking forward to a proper European Martini. France makes some fruity weird thing with an orange. Its not a Martini. I don't know what it is. I even asked on multiple occasions if they could make a real Martini, I even told the waiter how. They just said, "no". Sigh.

---
[View this page online](https://www.commandprompt.com/blog/pdxdjango_roundup_i_finally_got_my_martini/)

---

# Speaking at PDXDjango Tonight on PostgreSQL Performance

> I have the unexpected pleasure of speaking at PDXDjango tonight on PostgreSQL performance. Their meetings are 90 minutes with about 60 minutes (in theory) for …

I have the unexpected pleasure of speaking at PDXDjango tonight on PostgreSQL performance. Their meetings are 90 minutes with about 60 minutes (in theory) for the main speaker. The talk I am giving is a quick introduction to PostgreSQL Performance. The description I gave to the group was:

  * I am a Django developer not a DBA. 
  * I know nothing about PostgreSQL performance. 
  * What 10 things (it will be more) can I change to make PostgreSQL faster? 

I am being as thorough as possible based on the time constraints and explaining what each option is and how it works. I didn't want to just say, "Change it to 10". If you are in the neighborhood, stop by and let me know all the things I say that are wrong. The meeting starts at 7:00PM. 
    
    
    PIE
    1227 NW Davis St
    Portland, Oregon
    (At the corner of NW Davis & NW 12th).

---
[View this page online](https://www.commandprompt.com/blog/speaking_at_pdxdjango_tonight_on_postgresql_performance/)

---

# West wrap up and some videos

> I am back home and done recovering from Pg West 2009. I can now provide some closing thoughts. I think the conference as a whole went very well. This is the fi…

I am back home and done recovering from Pg West 2009. I can now provide some closing thoughts. I think the conference as a whole went very well. This is the first time we did a zero swag conference and the majority of people didn't seem to mind. SWAG is probably the single largest contributor to time spent organizing a conference (in a single block). By not having swag has allowed the team is able to organize the conference from a single Rubbermaid. We had some scheduling snafus, mostly based around two different versions of the schedule being printed (my bad) and a certain speaker (yeah you Robert Hodges;)) not following the speakers list. In all though these were minor and the attendees took it all in stride. It was great. The Keynote was fun. I wrote the talk late, just finishing right before walking into the room. While writing the talk I was chatting with Big Jim (Jimbo from EDB). He made it a point to request special treatment for the EDB boss from Red Hat. You can get his name [from the slides.](<http://www.postgresqlconference.org/2009/west/talks/welcome_to_postgresql_conference_west_2009>) When the video is up, you will see the particular ribbing that was provided. It was all in good fun of course and EDB was a great partner in the festivities. This time around I purchased SDHC based cameras which has enabled me to already start getting videos up. In fact the only thing stopping me from having them all up is that I have a quota on the account. [You can check here for videos and slides that we currently have up.](<http://www.postgresqlconference.org/2009/west/talks>) One thing that didn't happen was a closing session and I did hear some grumbling about that. I want to apologize to the attendees that wanted one. It is a good idea to have that and we didn't. In closing, I am glad it is over. I am glad I muscled through it (I strongly considered not having West this year). I am most glad that I focused on family during the after hours versus going to the various parties. No offense to the speakers or attendees. It is just what I needed this time around. We are already starting to talk about East as well as a Denver or Austin. Stay tuned!

---
[View this page online](https://www.commandprompt.com/blog/west_wrap_up_and_some_videos/)

---

# 87 people on a Friday

> What an amazing Friday. Normally on Fridays, PgWest and East are sparsely populated. Usually running in the mid 50s. Today was a great day with 87 people atten…

What an amazing Friday. Normally on Fridays, PgWest and East are sparsely populated. Usually running in the mid 50s. Today was a great day with 87 people attending and many more slated to attend on Saturday. Even some unexpected contributors showed up such as Robert Bernier. If you are reasonably close, and if you are thinking about coming; now is the time to make the commitment. If you are here by Saturday, there is a great party planned by EnterpriseDB, Saturday night. If there are too many commas in this blog, it is the fault of my daughter. She said it was comma happy day. [Conference details here.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/87_people_on_a_friday/)

---

# In Seattle for PostgreSQL Conference West

> Well I made it to Seattle. It was a bit of disaster to get here with my Wife flatly stating she was suing a well known Mexican restaurant for hot beans and bad…

Well I made it to Seattle. It was a bit of disaster to get here with my Wife flatly stating she was suing a well known Mexican restaurant for hot beans and bad signing from a well known pop star. I have a meeting today with the college to verify facilities. I then pick up the programs. Of course the "suites" at Spring Hill Suites are not really suites but hey, the room is clean. Tomorrow I think I will be sitting in on the Howdah talk. It seems odd, but I have been so busy with PostgreSQL that outside of minor high level architecture discussions I am not aware of the supposed coolness that leaks from the pipes of Pylons + Howdah and PostgreSQL. Look forward to seeing everyone!

---
[View this page online](https://www.commandprompt.com/blog/in_seattle_for_postgresql_conference_west/)

---

# Loving community, PostgreSQL Conference West gets help

> I was very happy about the progress of PostgreSQL Conference West this year. We secured facilities earlier than we ever had before thanks to heroic efforts by …

I was very happy about the progress of [PostgreSQL Conference West this year.](<http://www.postgresqlconference.org/>) We secured facilities earlier than we ever had before thanks to heroic efforts by Lisa Sandoval of [Seattle Central Community College](<http://seattlecentral.edu/>). Communication about the conference has been flowing well. We have a [great talk line up.](<http://www.postgresqlconference.org/2009/west/talks>) [Registrations are on par with last year, even with the economic downturn.](<http://www.postgresql.us/purchase>) And then I got hit with a heavy six month contract that specifically requires my expertise. I am not complaining. The contract is a good one but it did cause me to be unable to do a lot of things all of a sudden. This is why I am loving community. A vacuum presented itself and the community automatically stepped up to fill the void. I am not organizing an after-party. [Gabrielle stepped in.](<http://www.baconandtech.com/2009/10/08/are-you-going-to-pgwest/>) For good measure, [Selena backed her up.](<http://www.chesnok.com/daily/2009/10/09/enterprising-pgwest-conference-speaker-makes-an-after-party-wiki-page/>) Then, EnterpriseDB being the great community member they are asked if they could help. I would also like to thank Kevin Kempter and Brent Friedman for their continued persistence in helping me get things done. Of course let's not forget [all the speakers who have stepped up to give us such a great round of content.](<http://www.postgresqlconference.org/2009/west/talks>)

---
[View this page online](https://www.commandprompt.com/blog/loving_community_postgresql_conference_west_gets_help/)

---

# Everybody loves parties! (Pg Conference West in Seattle next week)

> If there is one thing the Open Source community knows how to do, it is party. Well, and drink but those do not necessarily go together at all times. Luckily, t…

If there is one thing the Open Source community knows how to do, it is party. Well, and drink but those do not necessarily go together at all times. Luckily, the Open Source community is also good at re-inventing the wheel, improvisation and general hackery. With that in mind, it is time to announce the after party info for PostgreSQL Conference West. I am extremely enthusiastic with the idea that the PostgreSQL Conference attendees will be able to party to their hearts content, all night long. If need be, even if they have to speak at 9:00am the next morning. However, they will have to do so, without JD and JD is not planning any after party events. I invite everyone to [join the attendees list](<http://lists.postgresqlconference.org/mailman/listinfo/attendees>) to negotiate any party, dinner, better wheel making plans they may have. So why is JD not partying? Well I will be but I will be doing so with family. See you all at the conference! If you haven't [registered yet... go here.](<http://www.postgresql.us/purchase>) If you have been living under a rock, [here is the conference site.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/everybody_loves_parties_pg_conference_west_in_seattle_next_week/)

---

# PostgreSQL Conference West 2009 update and Replicator 1.8.1

> As mentioned over at the PgUS website, the PostgreSQL Conference West 2009 registration is now open.. I will be giving a talk on Replicator 1.8.1 (which was ju…

As mentioned over at the PgUS website, the PostgreSQL Conference West 2009 [registration is now open.](<https://www.postgresql.us/purchase>). I will be giving a talk on [Replicator 1.8.1](<https://public.commandprompt.com/projects/replicator>) (which was just updated to 8.3.8). I will also be giving a talk on [PITRTools](<https://public.commandprompt.com/projects/pitrtools>).

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_west_2009_update_and_replicator_181/)

---

# PostgreSQL Conference West: Talk submission deadline extended until September 5th.

> In order to make our talk slots available to all who would like to give a presentation at PostgreSQL Conference West 09, we have extended our talk deadline unt…

In order to make our talk slots available to all who would like to give a presentation at PostgreSQL Conference West 09, we have extended our talk deadline until September 5th. If you have already submitted a talk, you will be notified of your acceptance (or not) by September 1st. For those that submit talks after August 25th, you will be notified by September 7th. As always you can find more information on The PostgreSQL Conference Series here: [Conference website](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_west_talk_submission_deadline_extended_until_september_5th/)

---

# PostgreSQL Replicator 8.3.1-1.8 Released

> From the hackers:
Replicator 8.3-1.8.1 It is recommended to update your 8.3-1.8.0 installation. No changes required for replication databases or configuration…

From the hackers: 

> Replicator 8.3-1.8.1 It is recommended to update your 8.3-1.8.0 installation. No changes required for replication databases or configuration files. Release notes: - Fixed a bug that lead to occasional crashes of the master's backend when performing updates to a table with dropped columns. - Fixed a couple of minor mcp_stat problems. 
> 
>   * [Download it here.](<http://files.commandprompt.com/replicator/mammoth-replicator-8.3.7-1.8.1.tar.bz2>)
>   * [Project site](<https://public.commandprompt.com/projects/replicator>)
>

---
[View this page online](https://www.commandprompt.com/blog/postgresql_replicator_831-18_released/)

---

# 2nd Call for Papers: PostgreSQL Conference West

> Reminder: We are in the midst of the PostgreSQL Conference West call for papers. The call for papers ends 08/20/09. If you wish to be considered to present you…

Reminder: We are in the midst of the [PostgreSQL Conference West](<http://www.postgresqlconference.org/>) call for papers. The call for papers ends 08/20/09. If you wish to be considered to present you must [submit a talk.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/2nd_call_for_papers_postgresql_conference_west/)

---

# Replicator 8.3-1.8 Released!

> I am pleased to announce the immediate availability of Replicator 8.3-1.8. Everyone jump start their engines over here.

I am pleased to announce the immediate availability of Replicator 8.3-1.8. Everyone jump start [their engines over here.](<https://public.commandprompt.com/projects/replicator/wiki/Getting_replicator>)

---
[View this page online](https://www.commandprompt.com/blog/replicator_83-18_released/)

---

# PostgreSQL Conference West 2009 Call for Papers

> PostgreSQL Conference West 2009 Call for Papers

June 24th, 2009, the PostgreSQL Conference U.S. team is pleased to announce the West 2009 venue and call for p…

**PostgreSQL Conference West 2009 Call for Papers** June 24th, 2009, the PostgreSQL Conference U.S. team is pleased to announce the West 2009 venue and call for papers. This year the premiere West Coast PostgreSQL Conference will be leaving its roots at Portland State University and moving north to sunny Seattle, Washington. The event this year is being held at Seattle Central Community College from October 16th through 18th. The move to Seattle opens up a larger metropolitan area for continuing to expose databases users, developers, and administrators to the World's Most Advanced Open Source Database. Following previously successful West Coast conferences, we will be hosting a series of 3-4 hour tutorials, 90 minute mini-tutorials, and 45 minute talks. This year we will be continuing our trend of covering the entire PostgreSQL ecosystem. We would like to see talks and tutorials on the following topics: **General PostgreSQL:**

  * Administration 
  * Performance 
  * High Availability 
  * Migration 
  * GIS 
  * Integration 
  * Solutions and White Papers 

**The Stack:**

  * Python/Django/Pylons/TurboGears/Custom 
  * Perl5/Catalyst/Bricolage 
  * Potato 
  * Ruby/Rails 
  * Java (PLJava would be great)/Groovy/Grails 
  * Operating System optimization (Linux/FBSD/Solaris/Windows) 
  * Solutions and White Papers 

If you are using PostgreSQL as your platform, you need to be presenting at this conference! **

[Submit your talk](<http://www.postgresqlconference.org/talksubmission>) (You must be have an account on the site)

** *** The PostgreSQL Conference U.S. series is an autonomous Educational Project used to educate all comers on the use of The World's Most Advanced Open Source Database. Proceeds from the event are donated directly to United States PostgreSQL; the 501c3 non-profit for PostgreSQL education and advocacy in the United States.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_west_2009_call_for_papers/)

---

# Pylons, PostgreSQL, and Simpycity in 60 Minutes or Less

> This is a tutorial to show you the basics of creating a small project within Pylons, with Simpycity. This tutorial assumes that you have already set up a Linux…

This is a tutorial to show you the basics of creating a small project within Pylons, with Simpycity. This tutorial assumes that you have already set up a Linux development environment for Pylons. Preferably on Ubuntu, though these directions should be general enough for any other Linux environment, meaning that you have installed Apache2, Python, mod-wsgi, and PostgreSQL 8.3. Choose a working directory for your project. For this example, I am using "project" for my working directory. Create the working directory, if it doesn't already exist. 
    
    
    mkdir project
    

Move into the working directory. 
    
    
    cd project
    

Create your project: 
    
    
    paster create -t pylons helloworld
    

This should give you a set of choices. 
    
    
    Enter template_engine (mako/genshi/jinja2/etc: Template language) ['mako']: genshi
    

For templating, choose "genshi". 
    
    
    Enter sqlalchemy (True/False: Include SQLAlchemy 0.5 configuration) [False]: False
    

Include sqlalchemy. "False". We will be using Simpycity instead. You should have a directory that looks like this: 
    
    
    lacey@blinky:~/project$ ls -l
    total 4.0K
    drwxr-xr-x 5 lacey lacey 4.0K 2009-06-05 08:46 helloworld
    lacey@blinky:~/project$
    

cd into the helloworld project. 
    
    
    cd helloworld
    

The base directory should look like this: 
    
    
    lacey@blinky:~/project/helloworld$ ls -l
    total 48K
    -rw-r--r-- 1 lacey lacey 1.6K 2009-06-05 08:46 development.ini
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 docs
    -rw-r--r-- 1 lacey lacey 9.5K 2009-06-05 08:46 ez_setup.py
    drwxr-xr-x 9 lacey lacey 4.0K 2009-06-05 08:46 helloworld
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 helloworld.egg-info
    -rw-r--r-- 1 lacey lacey  125 2009-06-05 08:46 MANIFEST.in
    -rw-r--r-- 1 lacey lacey  463 2009-06-05 08:46 README.txt
    -rw-r--r-- 1 lacey lacey  597 2009-06-05 08:46 setup.cfg
    -rw-r--r-- 1 lacey lacey  959 2009-06-05 08:46 setup.py
    -rw-r--r-- 1 lacey lacey  509 2009-06-05 08:46 test.ini
    lacey@blinky:~/project/helloworld$
    

This is the basic enviroment for your "Hello World" project. There are several important files and directories here. To avoid confusion, I will only explain the most important, and most used files within the project. 
    
    
    setup.py -- A command and control file for the project. 
                  With setup.py, you can run unit tests, update the packages 
                  associated with the project, and package it into a Python .egg. 
    
    test.ini -- The test configuration file for the project. 
                This file mostly inherits from the development.ini file, but if 
                you want to have testing specific settings for this project, 
                you put them here. For now, this will just inherit 
                from development.ini.
    
    development.ini -- This file contains basic configuration of the project. 
                       This is where you toggle debugging settings, add database 
                       configuration information, and so forth.
    

We need to customize this environment to use Simpycity, a simple and effective ORM based on stored procedures and queries. First, we edit the "setup.py" file. You can use your preferred text editor to open this file, e.g. Vim, Emacs, Joe, Nano, Gedit, ect. For this example, we will use the basic editor "nano". 
    
    
    nano setup.py
    

There are only a few options that need to be modified in the base setup.py file. Note the section that looks like this: 
    
    
        install_requires=[
            "Pylons>=0.9.7",
            "Genshi>=0.4",
        ],
    

This section governs the requirements for your particular project. This currently shows that a version of Pylons of 0.9.7 or greater, and a version of Genshi of 0.4 or greater is required to for this project. Since we are using Simpycity for our ORM, we need to add a line for Simpycity. 
    
    
        install_requires=[
            "Pylons>=0.9.7",
            "Genshi>=0.4",
            "Simpycity>=0.2.1"
        ],
    

The number 0.2.1 is the current version of Simpycity. Since new features and bug fixes are added to Simpycity regularly, you should check for updated versions regularly. To check that the version of Simpycity is up to date, please go down in the middle of the page, there is an area marked "Download". The first item in the download area is the current version of Simpycity. (Which at the time of writing this tutorial is 0.2.1, so be sure to check.) 
    
    
    The current release version of Simpycity is 0.2.1, which can be [downloaded
    from here](<https://public.commandprompt.com/projects/simpycity>) 
    

All that you need to do to keep Simpycity up to date is copy that version number, and paste over the version number in the install_requires stanza in setup.py. After that, there is one last thing we need to add to the setup.py file Near the bottom, before the closing parenthesis, we need to add another snippet of code. 
    
    
        dependency_links=[
            "https://projects.commandprompt.com/public/simpycity/repo/dist/"
        ] 
    

This is the link to the Simpycity repository at Command Prompt. easy_install will use that URI, combined with the version number (in this case 0.2.1) to locate and install the proper Simpycity .egg file. Now, we save, and exit from setup.py. Following the insertion of those lines, we will do one last check. Sometimes, the newest python packages with easy_install require that they be built on the machine before they are deployed. This is the case with newer versions of psycopg2. To ensure that all of the build requirements are present, run the following command: 
    
    
    aptitude search postgresql-server-dev-8.3 python2.5-dev build-essential
    

Which should return like this: 
    
    
    lacey@blinky:~/project/helloworld$ aptitude search postgresql-server-dev-8.3 
    python2.5-dev build-essential
    i A build-essential                     - Informational list of build-essential packages                                                
    i   postgresql-server-dev-8.3           - development files for PostgreSQL 8.3 server-side programming                                  
    i   python2.5-dev                       - Header files and a static library for Python (v2.5)                                           
    lacey@blinky:~/project/helloworld$
    

If it does not, then running the following command: 
    
    
    sudo aptitude install postgresql-server-dev-8.3 python2.5-dev build-essential
    

Will install the essential libraries for you. Now, we run the following command: 
    
    
    sudo python setup.py develop
    

This will check and process all of the dependencies for your project, including Simpycity. This process will install the dependencies required for your project, so that they may be used within the project. Now that we have Simpycity installed, we pause to do a bit of database setup. With sudo become the postgres user. 
    
    
    sudo su - postgres
    

It will ask you for your password. Success should look something like this. 
    
    
    lacey@blinky:~/project/helloworld$ sudo su - postgres
    [sudo] password for lacey: 
    postgres@blinky:~$
    

Now, we run a PostgreSQL command to create a user. 
    
    
    postgres@blinky:~$ psql -U postgres
    Welcome to psql 8.3.7, the PostgreSQL interactive terminal.
    
    Type:  \copyright for distribution terms
           \h for help with SQL commands
           \? for help with psql commands
           \g or terminate with semicolon to execute query
           \q to quit
    
    postgres=# 
    

You are now on the postgresql command line. While there, run the following commands. 
    
    
    CREATE USER helloworld WITH ENCRYPTED PASSWORD '12345';
    CREATE DATABASE helloworld WITH OWNER helloworld;
    

The successful execution of these two commands should look like this: 
    
    
    postgres=# CREATE USER helloworld WITH ENCRYPTED PASSWORD '12345';
    CREATE ROLE
    postgres=# CREATE DATABASE helloworld WITH OWNER helloworld;
    CREATE DATABASE
    postgres=#
    

Exit PostgreSQL with the \q command. This should drop you back to the command line. 
    
    
    postgres=# \q
    postgres@blinky:~$
    

If you haven't already, take a moment to modify your pg_hba.conf so you can easily log in. 
    
    
    nano /etc/postgresql/8.3/main/pg_hba.conf
    

Near the bottom, there should be a line that looks like *exactly* like this. 
    
    
    local   all         all                               ident sameuser
    

The very last part, "ident sameuser" should be changed to md5, so that the line looks like this: 
    
    
    local   all         all                               md5
    

Save and quit. Now, execute the command: 
    
    
    /etc/init.d/postgresql-8.3 force-reload
    

This will reload the settings that you changed. 
    
    
    postgres@blinky:~$ /etc/init.d/postgresql-8.3 force-reload
    * Reloading PostgreSQL 8.3 database server [ OK ] 
    postgres@blinky:~$
    

Exit the postgres user environment with the exit command. 
    
    
    postgres@blinky:~$ exit
    logout
    lacey@blinky:~/project/helloworld$
    

Now we should be back in the "helloworld" project directory. Next, as a convenience, we will create a .pgpass file. cd to your home directory. 
    
    
    cd ~
    
    
    
    nano .pgpass
    

When the editor window comes up, add the following line. 
    
    
    localhost:5432:*:helloworld:12345
    

Save and quit. Following that, execute the following command. 
    
    
    chmod 600 .pgpass
    

This will appropriately set the permissions for your user. You can check them with the following command. 
    
    
    lacey@blinky:~$ ls -l .pgpass
    -rw------- 1 lacey lacey 135 2009-06-05 12:10 .pgpass
    lacey@blinky:~$
    

Now, there is the final test. Execute the following command. 
    
    
    psql -U helloworld
    

If everything has been successfully set up, your terminal screen should look like this: 
    
    
    lacey@blinky:~$ psql -U helloworld
    Welcome to psql 8.3.7, the PostgreSQL interactive terminal.
    
    Type:  \copyright for distribution terms
           \h for help with SQL commands
           \? for help with psql commands
           \g or terminate with semicolon to execute query
           \q to quit
    
    helloworld=>
    

With the command logging you in without issue, or a password prompt. While we are here, in PostgreSQL, we should issue the following command: 
    
    
    CREATE LANGUAGE plpgsql;
    

Again, success should look like this: 
    
    
    helloworld=> CREATE LANGUAGE plpgsql;
    CREATE LANGUAGE
    helloworld=>
    

And again, we exit with "\q". 
    
    
    helloworld=> \q
    lacey@blinky:~$
    

Now, we return to the project directory with the following command. 
    
    
    cd project/helloworld/
    

In this directory, we edit development.ini 
    
    
    nano development.ini
    

At line 36, uncomment the line set debug = false, and add the following lines so that the section of the configuration file looks like this: 
    
    
    db.database = helloworld
    db.user     = helloworld
    db.host     = localhost
    db.port     = 5432
    db.password = 12345
    

These are the values that Simpycity requires for the database connections. 
    
    
      database = a database that belongs to the user.
      user = the user that you are connecting as.
      host = the server being connected to. localhost for a development machine.
      port = the port that PostgreSQL expects you to connect on.
      password = the password for the user.
    

Before we go on, a little more explanation is needed, so that you better understand what is going on in later steps. You may have noticed the "helloworld" directory within the project earlier. 
    
    
    lacey@blinky:~/project/helloworld$ ls -l
    total 48K 
    -rw-r--r-- 1 lacey lacey 1.6K 2009-06-05 08:46 development.ini
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 docs
    -rw-r--r-- 1 lacey lacey 9.5K 2009-06-05 08:46 ez_setup.py
    drwxr-xr-x 9 lacey lacey 4.0K 2009-06-05 08:46 helloworld
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 helloworld.egg-info
    -rw-r--r-- 1 lacey lacey  125 2009-06-05 08:46 MANIFEST.in
    -rw-r--r-- 1 lacey lacey  463 2009-06-05 08:46 README.txt
    -rw-r--r-- 1 lacey lacey  597 2009-06-05 08:46 setup.cfg
    -rw-r--r-- 1 lacey lacey  959 2009-06-05 08:46 setup.py
    -rw-r--r-- 1 lacey lacey  509 2009-06-05 08:46 test.ini
    lacey@blinky:~/project/helloworld$
    

This directory contains all of your project specific code is placed. If you issue the following commands: 
    
    
    cd helloworld
    ls -l
    

You will note that the directory has the following structure: 
    
    
    lacey@blinky:~/project/helloworld/helloworld$ ls -l
    total 32K
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 config
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 controllers
    -rw-r--r-- 1 lacey lacey    0 2009-06-05 08:46 __init__.py
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 lib
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 model
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 public
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 templates
    drwxr-xr-x 3 lacey lacey 4.0K 2009-06-05 08:46 tests
    -rw-r--r-- 1 lacey lacey  296 2009-06-05 08:46 websetup.py
    lacey@blinky:~/project/helloworld/helloworld$ 
    

The directories here break down as follows: 
    
    
    config -- Configuration files for your application as a whole.
    
    controllers -- This is where most of the application logic goes. 
                  The files here control what you display, and how you display it.
    
    lib -- This is where miscellaneous files that are necessary for your 
           application, but have no distinct place go.
    
    model -- This is where the files related to the ORM go. 
             This will be where most of the files related 
             to the database and Simpycity will live.
    
    public -- This is where static html, docs, css, and such live. 
    
    templates -- This is where Genshi will create the dynamic html templates 
                 for the dynamic pages that you will use.
    
    __init__.py -- This is a helper file for packaging your application. 
                   That will be covered later in a different tutorial.
    
    tests -- This is where your unit tests live. 
             These test controllers and other application functionality.
    
    websetup.py -- This is another helper file for packaging your application. 
                   It too will be covered later in a different tutorial.
    

Now that you have an overview of the directories within a Pylons project, we can start making some changes within this directory and its child directories. First, we should make an important edit to lib/base.py, related to Simpycity. 
    
    
    nano lib/base.py
    

The contents of the file will look like this. 
    
    
    """The base Controller API
    
    Provides the BaseController class for subclassing.
    """
    from pylons.controllers import WSGIController
    from pylons.templating import render_genshi as render
    
    class BaseCoOne line ntroller(WSGIController):
    
        def __call__(self, environ, start_response):
            """Invoke the Controller"""
            # WSGIController.__call__ dispatches to the Controller method
            # the request is routed to. This routing information is
            # available in environ['pylons.routes_dict']
            return WSGIController.__call__(self, environ, start_response)
    

We will add the following lines, to fix a troublesome issue before it starts. For the curious, more detail can be found [here at Aurynn Shaw's blog](<../../../../blog/long_running_request_handlers_and_python_garbage_collection/>). For purposes of this tutorial, it should be sufficient to say that this will allow Pylons and mod_wsgi to properly close and clean up connections to the database, so that connections are not left hanging idle in transaction. So this is very important to include in any project. 
    
    
            import psycopg2
            import psycopg2.extensions
            psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
            from simpycity.handle import Manager
                
            m = Manager()
            try:
                return WSGIController.__call__(self, environ, start_response)
            finally:
                # Shut down *all* the extant handles.
                m.close()
    

We paste this in so that the controller code will look like this: 
    
    
    One line 
    """The base Controller API
    
    Provides the BaseController class for subclassing.
    """
    from pylons.controllers import WSGIController
    from pylons.templating import render_genshi as render
    
    class BaseController(WSGIController):
    
        def __call__(self, environ, start_response):
            """Invoke the Controller"""
            # WSGIController.__call__ dispatches to the Controller method
            # the request is routed to. This routing information is
            # available in environ['pylons.routes_dict']
            #return WSGIController.__call__(self, environ, start_response)
            import psycopg2
            import psycopg2.extensions
            psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
            from simpycity.handle import Manager
                    
            m = Manager()
            try:
                return WSGIController.__call__(self, environ, start_response)
            finally:
                # Shut down *all* the extant handles.
                m.close()
    

Save, and exit nano. Next we edit environment.py 
    
    
    One line 
    nano config/environment.py
    

Within this file, at the very end, below the lines: 
    
    
    # CONFIGURATION OPTIONS HERE (note: all config options will override
    # any Pylons config options)
    

we add the follwing lines, for Simpycity setup. 
    
    
    app_conf = config['app_conf']
    
    db_config.port = app_conf['db.port']
    db_config.database= app_conf['db.database']
    db_config.host= app_conf['db.host']
    db_config.user = app_conf['db.user']
    db_config.password = app_conf['db.password']
    db_config.debug = False
    

And at the top of environment.py, with the rest of the imports, we add the following line. 
    
    
    from simpycity import config as db_config
    

So that the proper configuration options are read. It should be noted here, if you need to see the debugging options from Simpycity itself, you should set db_config.debug to True. Having added the proper configuration parameters to base.py and environment.py, we can start looking at how to serve content from Pylons. There are two basic ways to serve content through Pylons: 
    
    
       1. To server static content from the public/ directory. 
       2. Use a controller, which contains the logic for what to control and how 
       to display it.
    

The trivially easy case is static content. Execute the following command. 
    
    
    nano helloworld/public/hello.html
    

Paste the following content. 
    
    
    <html>
       <body>
          Hello World!
       </body>
    </html>
    

Save and exit. This creates a basic static html file. Now, from our current directory, execute the following command 
    
    
    paster serve --reload development.ini
    

This command starts the Pylons server, and is great for a bit of quick debugging, or if you haven't got Apache installed or configured. Entering the following URI into your web browser: 
    
    
    http://localhost:5000/hello.html
    

You should see a simple page with the words "Hello World!". Now, stop the server on the command line with <ctrl>-<c>. We are moving on to the more interesting and complicated case of using a controller to serve content within Pylons. Execute the following command: 
    
    
    paster controller hello
    

Successful execution of this command should look something like this: 
    
    
    lacey@blinky:~/project/helloworld$ paster controller hello
    Creating /home/lacey/project/helloworld/helloworld/controllers/hello.py
    Creating /home/lacey/project/helloworld/helloworld/tests/functional/test_hello.py
    

This is an interesting and useful command. As expected, it created a file called hello.py in the helloworld/controllers directory, but it also did a wonderful thing for us, and created a file in helloworld/tests/functional/test_hello.py to contain the specific unit tests for the hello.py controller. Executing the following command: 
    
    
    nano helloworld/controller/hello.py
    

Shows us the contents of the hello.py controller, which are very basic. 
    
    
    import logging
    
    from pylons import request, response, session, tmpl_context as c
    from pylons.controllers.util import abort, redirect_to
    
    from helloworld.lib.base import BaseController, render
    
    log = logging.getLogger(__name__)
    
    class HelloController(BaseController):
    
        def index(self):
            # Return a rendered template
            #return render('/hello.mako')
            # or, return a response
            return 'Hello World'
    

Exiting from Nano, we can also have a look at test_hello.py by executing a similar command. 
    
    
    nano helloworld/tests/functional/test_hello.py
    

The contents of which are: 
    
    
    from helloworld.tests import *
    
    class TestHelloController(TestController):
    
        def test_index(self):
            response = self.app.get(url(controller='hello', action='index'))
            # Test response...
    

The paster command has created a basic framework for a unit test of the hello.py controller. We will come back to this later in the document. For right now, we want to see the controller in action. But there is a bit more setup that we need to do first. Execute the following command: 
    
    
    nano helloworld/config/routes.py
    

This should bring up a file that looks like this: 
    
    
    """Routes configuration
    
    The more specific and detailed routes should be defined first so they
    may take precedent over the more generic routes. For more information
    refer to the routes manual at http://routes.groovie.org/docs/
    """
    from pylons import config
    from routes import Mapper
    
    def make_map():
        """Create, configure and return the routes Mapper"""
        map = Mapper(directory=config['pylons.paths']['controllers'],
                     always_scan=config['debug'])
        map.minimization = False
    
        # The ErrorController route (handles 404/500 error pages); it should
        # likely stay at the top, ensuring it can always be resolved
        map.connect('/error/{action}', controller='error')
        map.connect('/error/{action}/{id}', controller='error')
    
        # CUSTOM ROUTES HERE
    
        map.connect('/{controller}/{action}')
        map.connect('/{controller}/{action}/{id}')
    
        return map
    

This is another relatively spartan, but highly important file. Within this file, the routes for the application are defined. Routes are what translates the URI within the browser into directions in the application, which point data at a specific controller, for manipulation. This may sound a bit obtuse right now, but at the end of this particular example, it should be clear. Currently, if you were to restart Pylons, with the aformentioned command... 
    
    
    paster serve --reload development.ini
    

And attempted to browse to the URI: 
    
    
    http://localhost:5000/hello
    

You would be presented with a very cheery orange-yellow, and black 404 page. This is because you haven't specified the route. Without a route, Pylons has no idea what you want. So, to let it know that we want to see what is within the HelloController (located in helloworld/controller/hello.py) we will add the following line to helloworld/config/routes.py : 
    
    
    map.connect('hello', '/hello', controller='hello', action='index')
    

The first item in map.connect gives the route the name "hello" (this will be handy later). The second part is what maps the part of the URI that you put in the search bar as in: 
    
    
    http://localhost:5000/hello
    

Now, when we run: 
    
    
    paster serve --reload development.ini
    

And attempted to browse to the URI: 
    
    
    http://localhost:5000/hello
    

We will see the words "Hello World". Note that this is different from our static html entry. 
    
    
    http://localhost:5000/hello.html
    

Which says "Hello World!". And both are available. Moving to a more generic route... 
    
    
    http://localhost:5000
    

Will show you a very cheery welcome page, with the same orange-yellow and black color scheme, with links. This is served from helloworld/public/public.html Now, that is all fine for an example, but in an actual production application, you don't want someone to see "Welcome To Pylons" when they browse to your root URI. So, lets fix this. First, stop the server on the command line with <ctrl>-<c>. Execute the command: 
    
    
    nano helloworld/config/routes.py
    

At the bottom, just before "return map", we will add the following line. 
    
    
    map.connect('root', '/', controller='hello', action='index')
    

Why do we add this way down there, you might ask? Because the Pylons developers left us with a handy comment at the top of this file. 
    
    
    The more specific and detailed routes should be defined first 
    so they may take precedent over the more generic routes.
    

Taking heed of this advice, and realizing that '/' is the most generic route that you can have, we place this at the very bottom so it is chosen last in the evaluation of routes. Again, we restart the server, from the ~/projects/hellworld directory. 
    
    
    paster serve --reload development.ini
    

And browse to: 
    
    
    http://localhost:5000
    

...We still see the cheery orange-yellow and black welcome page. (Be sure to shut down the server with <ctrl>-<c>) Why is that!?!? Well, there's an interesting thing about Pylons. It will evaluate the static content in helloworld/public first. In this case, it is index.html. If we poke around a bit, we find the culprit in helloworld/config/middleware.py on line 67. 
    
    
    app = Cascade([static_app, app])
    

This line basically says that, look for static content first, and evaluate that over the dynamic application content. There are two ways to solve this particular issue. 1. Execute the following command: 
    
    
    mv helloworld/public/index.html helloworld/public/index.html.dont_evaluate_me_pylons
    

If you do that, Pylons won't be able to find it, and will default to the route set in routes.py. In this case, if you restart the server, and browse to the aformentioned URI, you will see Hello World (without the exclamation point). 2. Swap the order of Cascade. Since the Cascade command defines whether or not you evaluate static content or dynamic content first, swapping the order will mean that dynamic content is evaluated first, and static content second. So, we execute the following command: 
    
    
    mv helloworld/public/index.html.dont_evaluate_me_pylons helloworld/public/index.html 
    

To return the file back to its original state. If we are incorrect, this will show us by displaying that cheery welcome page again. So, we execute the following command: 
    
    
    nano helloworld/config/middleware.py
    

Once there, we will copy line 67, and paste it directly below itself. Then we will comment out line 67 (we have the original line for reference), so that the file now looks like this: 
    
    
    #app = Cascade([static_app, app])
    app = Cascade([app, static_app])
    

With the order of app, and static_app swapped. In this case, if you restart the server, and browse to the aformentioned URI, you will see Hello World (without the exclamation point). And index.html is still happily sitting in helloworld/public 
    
    
    lacey@blinky:~/project/helloworld$ ls -l helloworld/public/index.html 
    -rw-r--r-- 1 lacey lacey 4.6K 2009-06-05 08:46 helloworld/public/index.html
    

Now, even though we're using the HelloController in hello.py, this is still little better than a static application. So, now, we will work on making hello.py dynamic, letting it read and write to and from the database by using Simpycity. First, we will need a simple set of tables and functions for use in PostgreSQL. We are currently still in the ~/project/helloworld directory. We are going to move one directory back. 
    
    
    cd ..
    

And make a new directory called 'sql'. 
    
    
    mkdir sql
    

Now, we consider the following table and functions, already designed and provided for you to use. These will be the examples that we use for the rest of the tutorial. This is a very simple table, that contains ways to say "Hello" in different languages. 
    
    
    CREATE TABLE hello
    (
      salutation text not null primary key,
      language text not null
    );
    
    -- Various formal ways of saying hello or good morning.
    INSERT INTO hello (salutation, language) VALUES ('hello','English');
    INSERT INTO hello (salutation, language) VALUES ('hola','Spanish');
    INSERT INTO hello (salutation, language) VALUES ('bonjour','French');
    INSERT INTO hello (salutation, language) VALUES ('merhaba selam','Turkish');
    INSERT INTO hello (salutation, language) VALUES ('zdravstvuyte','Russian');
    INSERT INTO hello (salutation, language) VALUES ('buon giorno','Italian');
    
    
    CREATE OR REPLACE FUNCTION add_salutation
    (in_salutation text, in_language text)
    RETURNS boolean AS $BODY$
      DECLARE
      BEGIN
        INSERT INTO hello (salutation, language) 
        VALUES (in_salutation, in_language);
        RETURN TRUE;
      END;
    $BODY$ LANGUAGE PLPGSQL;
    
    
    CREATE OR REPLACE FUNCTION remove_salutation
    (in_salutation text, in_language text)
    RETURNS boolean AS $BODY$
      DECLARE
      BEGIN
        DELETE FROM hello 
          WHERE salutation = in_salutation 
          AND language = in_language;
        RETURN TRUE;
      END;
    $BODY$ LANGUAGE PLPGSQL;
    
    
    CREATE OR REPLACE FUNCTION update_salutation
    (in_old_salutation text, in_new_salutation text)
    RETURNS boolean AS $BODY$
      DECLARE
      BEGIN
        UPDATE hello 
            SET salutation = in_new_salutation
            WHERE salutation = in_old_salutation;
        RETURN TRUE;
      END;
    $BODY$ LANGUAGE PLPGSQL;
    
    

Execute the following command, in your ~/project/sql directory. 
    
    
      nano hello.sql
    

Paste the above SQL code into that file, save and quit. Then run the following command. 
    
    
    psql -U helloworld helloworld -f hello.sql
    

Success should look like this. 
    
    
    lacey@blinky:~/project/sql$ psql -U helloworld helloworld -f hello.sql 
    psql:hello.sql:5: NOTICE:  CREATE TABLE / PRIMARY KEY will create 
    implicit index "hello_pkey" for table "hello"
    CREATE TABLE
    INSERT 0 1
    INSERT 0 1
    INSERT 0 1
    INSERT 0 1
    INSERT 0 1
    INSERT 0 1
    CREATE FUNCTION
    CREATE FUNCTION
    CREATE FUNCTION
    lacey@blinky:~/project/sql$
    

Now that the necessary tables, functions, and data are in place in PostgreSQL, we can move on to making our hello model. Execute the following command to move back into your helloworld project directory. 
    
    
    cd ../helloworld/helloworld
    

The directory you are in should look like this, if you execute the command ls -l : 
    
    
    lacey@blinky:~/project/helloworld/helloworld$ ls -l
    total 36K
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 16:52 config
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-06 18:57 controllers
    -rw-r--r-- 1 lacey lacey    0 2009-06-05 08:46 __init__.py
    -rw-r--r-- 1 lacey lacey  140 2009-06-05 15:07 __init__.pyc
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 15:26 lib
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-06 19:35 model
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 16:40 public
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 templates
    drwxr-xr-x 3 lacey lacey 4.0K 2009-06-05 08:46 tests
    -rw-r--r-- 1 lacey lacey  296 2009-06-05 08:46 websetup.py
    lacey@blinky:~/project/helloworld/helloworld$ 
    

Recall that earlier, when discussing the structure of the projects, that the "model" directory was where the files related to your ORM are placed. We are going to create our model for our Hello World project. Execute the following command: 
    
    
    nano model/hello_model.py
    

And paste the following code into it: 
    
    
    from simpycity.core import Function, Raw 
    from simpycity.model import SimpleModel, Function, Construct
    from simpycity.core import Raw 
    
    class HelloModel(SimpleModel):
    
       # Getters
       get_salutation = Raw("SELECT salutation 
                          FROM public.hello 
                            ORDER BY random() LIMIT 1")
    
       # Setters
       add_salutation = Function("public.add_salutation",
                                  ['salutation','language'])
       upd_salutation = Function("public.update_salutation",
                                  ['old_salutation','new_salutation'])
    
       # Deleters
       del_salutation = Function("public.remove_salutation",
                                  ['salutation','language'])                                                                          
    

This code sets up Simpycity for use in our application. At the top, are the required imports from Simpycity. There are two basic ways that Simpycity interacts with the PostgreSQL database beneath it. Function is how Simpycity maps Python to the stored procedures in the database. Looking at this line: 
    
    
    add_salutation = Function("public.add_salutation",['salutation','language'])
    

The double-quoted portion of this function, "public.add_salutation", is the schema qualified name of the stored procedure we are looking to map to. The bracketed portion of this function, ['salutation','language'], map the arguments to the function. For example, when we call this function: return_status = HelloModel.add_salutation("sawadee ka","Thai") Will map to "SELECT * FROM public.add_salutation('sawadee ka','Thai')", which will insert the salutation "namaste" and the language "hindi" into the database, and return true, which sets the value of "return_status" to true. Raw is the Simpycity way of mapping straight SQL to the database. 
    
    
    get_salutation = Raw("SELECT salutation 
                          FROM public.hello 
                          ORDER BY random() LIMIT 1")
    

For example, calling this function: return_item = HelloModel.get_salutation() Raw simply executes the provided query, which in this example, is: 
    
    
    SELECT salutation FROM public.hello ORDER BY random() LIMIT 1;
    

Returning a random way to say hello into the variable "return_item". Now, we need to modify the Hello Controller. Execute the command: 
    
    
    nano controller/hello.py
    

The contents of which are: 
    
    
    import logging
    
    from pylons import request, response, session, tmpl_context as c
    from pylons.controllers.util import abort, redirect_to
    
    from helloworld.lib.base import BaseController, render
    
    log = logging.getLogger(__name__)
    
    class HelloController(BaseController):
    
        def index(self):
            # Return a rendered template
            #return render('/hello.mako')
            # or, return a response
            return 'Hello World'
    

We will add: 
    
    
    from helloworld.model.hello_model import HelloModel
    

and: 
    
    
    salutation = HelloModel.get_salutation(options=dict(fold_output=True))
    return salutation
    

To the hello controller, and we will comment out the line "return 'Hello World'", so that our controller now looks like this: 
    
    
    import logging
    
    from pylons import request, response, session, tmpl_context as c
    from pylons.controllers.util import abort, redirect_to
    
    from helloworld.lib.base import BaseController, render
    
    from helloworld.model.hello_model import HelloModel
    
    log = logging.getLogger(__name__)
    
    class HelloController(BaseController):
    
        def index(self):
            # Return a rendered template
            #return render('/hello.mako')
            # or, return a response
            #return 'Hello World'
            salutation = HelloModel.get_salutation(options=dict(fold_output=True))
            return salutation
    

Now, combining the database functions we created, the HelloModel that we created, and this code, we will be able to query the database. To see the code in action, all we have to do is start the server again. So we execute the command 
    
    
    cd ..
    

And then execute: 
    
    
    paster serve --reload development.ini
    

And open our browsers to http://localhost:5000/ This should show you a randomly chosen way to say hello. Pressing the refresh button will show you another, and another. Now, let's add a bit to it with a Genshi Template. Press <ctrl>-<c> to stop your server. Now, we refer back to the directory layout of the project. 
    
    
    lacey@blinky:~/project/helloworld/helloworld$ ls -l
    total 36K
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 16:52 config
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-06 18:57 controllers
    -rw-r--r-- 1 lacey lacey    0 2009-06-05 08:46 __init__.py
    -rw-r--r-- 1 lacey lacey  140 2009-06-05 15:07 __init__.pyc
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 15:26 lib
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-06 19:35 model
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 16:40 public
    drwxr-xr-x 2 lacey lacey 4.0K 2009-06-05 08:46 templates
    drwxr-xr-x 3 lacey lacey 4.0K 2009-06-05 08:46 tests
    -rw-r--r-- 1 lacey lacey  296 2009-06-05 08:46 websetup.py
    lacey@blinky:~/project/helloworld/helloworld$ 
    

The templates directory is where all of our dynamically generated page templates (created by Genshi, as you recall from the very beginning of this tutorial). So we should execute the following command. 
    
    
    cd helloworld/templates
    

Now, we are going to look at the contents of this directory. 
    
    
    lacey@blinky:~/project/helloworld/helloworld/templates$ ls -l
    total 0
    -rw-r--r-- 1 lacey lacey    0 2009-06-05 08:46 __init__.py
    lacey@blinky:~/project/helloworld/helloworld/templates$ 
    

This only contains a blank __init__.py file. This is only because the Genshi templating engine within Pylons will ignore any template directories without an __init__.py in them. Armed with that knowledge, we will create our own directory. 
    
    
    mkdir hello
    

We will move into it: 
    
    
    cd hello
    

and we will make a blank __init__.py file. 
    
    
    touch __init__.py
    

We will also make another file. 
    
    
    nano hello.html
    

And within that we will paste the following contents. 
    
    
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>${c.hello}</title>
      </head>
      <body class="index">
        <div id="header">
          <h1>${c.hello}</h1>
        </div>
        <p>That is hello in: ${c.language}</p>
      </body>
    </html>
    

Save and quit. This is a very basic xHTML Genshi template. Aside from having syntax for dynamically setting variables, Genshi templates can be treated the same as any other xHTML page. Within this template are dynamically setting the title, a header, a small bit of content. ${c.hello} And ${c.language} are variables within the template, that we will set within our controller. For more information on the Genshi templates, please consult the documentation, found [here](<http://genshi.edgewall.org/wiki/Documentation>)But before we render this page, we need to make a few more modifications. We move out of this directory, into the model directory. 
    
    
    cd ../../model
    

And open the file hello_model.py. We will add the following content. 
    
    
    get_language = Raw("SELECT language 
                        FROM public.hello 
                        WHERE salutation = %s", ['salutation']);
    

This is another variation of the Raw function, in which we are able to substitute variables into the query. Save and quit. Lastly, we move to the controller directory, and modify our controller. 
    
    
    cd ../controller
    
    
    
    nano hello.py
    

We will add the following import: 
    
    
    from pylons.templating import render_genshi as render
    

Which now brings the render_genshi function into our controller, and aliases it to render. We will also comment out "return salutation" #return salutation We will add the following lines: 
    
    
    c.language = HelloModel.get_language(salutation, 
                            options=dict(fold_output=True))
    c.hello = salutation
    return render("hello/hello.html");
    

This should leave the file looking like this: 
    
    
    import logging
    
    from pylons import request, response, session, tmpl_context as c
    from pylons.controllers.util import abort, redirect_to
    
    from helloworld.lib.base import BaseController, render
    
    from helloworld.model.hello_model import HelloModel
    from pylons.templating import render_genshi as render
    
    log = logging.getLogger(__name__)
    
    class HelloController(BaseController):
    
        def index(self):
            # Return a rendered template
            #return render('/hello.mako')
            # or, return a response
            #return 'Hello World'
            salutation = HelloModel.get_salutation(options=dict(fold_output=True))
            c.language = HelloModel.get_language(salutation, 
                         options=dict(fold_output=True))
            c.hello = salutation
            return render("hello/hello.html");
            #return salutation
    

The c. prefix to the variables are special to Genshi, and let it know what variables it should be rendering. We are still getting a salutation from the HelloModel.get_salutation() function. Now, we are taking that result, and using it to get the language for the saluation, using the HelloModel.get_language() function. We are then setting the c.hello variable to the same value as the salutation variable. And the c.language variable is set to the return value of the HelloModel.get_language() function. return render("hello/hello.html") tells Genshi where the file we want to render is in relation to the template directory. If hello.html was simply in the template directory, the return statement would be: return render("hello.html") But since it is in the hello directory, we have to represent the rest of the path to the xHTML template. And for the HelloModel Simpycity functions, we add new parameter. options=dict(fold_output=True) Since we know these are going to return a single row only, we are collapsing the output of the query, causing it to return a value into the variable that is ready to be used by Python. Now, to test. Again, we back out of this directory to the outermost helloworld directory, in order to start the server. 
    
    
    cd ../..
    
    
    
    paster serve --reload development.ini
    

And again, we browse to the page http:://localhost:5000 in our browser. Which should now look something like this: 
    
    
    bonjour
    
    That is hello in: French
    

Now, displaying dynamic content is only one part of dealing with the database. We need to be able to manipulate the content. Deleting and updating content within the database are both crucial parts. So, we're going to add the remaining parts to make this a well-rounded example. So we stop the server (<ctrl>-<c>, again), and we move to the helloworld/public directory. 
    
    
    cd helloworld/public
    

And we copy/paste the following files: 
    
    
    nano add_salutation.html
    

And we paste the following code. 
    
    
    <html>
       <body>
        <form action="/hello/add_salutation" method="POST">
           <p> 
              Add Salutation:<br/>
              Salutation: <input type="text" name="salutation"><br/>
              Language: <input type="text" name="language"><br/>
              <input type="submit" value="submit">
           </p>
        </form>
       </body>
    </html>
    

Save and close. 
    
    
    nano modify_salutation.html
    

And we paste the following code. 
    
    
    <html>
       <body>
        <form action="/hello/modify_salutation" method="POST">
           <p> 
              Modify Salutation:<br/>
              Old Salutation: <input type="text" name="old_salutation"><br/>
              New Salutation: <input type="text" name="new_salutation"><br/>
              <input type="submit" value="submit">
           </p>
        </form>
       </body>
    </html>
    

Save and close. 
    
    
    nano remove_salutation.html
    

And we paste the following code. 
    
    
    <html>
       <body>
        <form action="/hello/remove_salutation" method="POST">
           <p> 
              Remove Salutation:<br/>
              Salutation: <input type="text" name="salutation"><br/>
              Language: <input type="text" name="language"><br/>
              <input type="submit" value="submit">
           </p>
        </form>
       </body>
    </html>
    

Save and close. Each of these files are simple, static pages, that submit forms to different actions in the hello controller. Each of the forms has two fields in which to specify the language and salutation. In the case of modify_salutation.html, we specify an old and new salutation. Plus, the ever helpful submit button. Currently, though, the hello controller only contains the index action. So we will need to modify that. We navigate to the controllers directory. 
    
    
    cd ../controllers
    

And open hello.py for editing 
    
    
    nano hello.py
    

We will add the following functions. 
    
    
        def add_salutation(self):
           if 'salutation' in request.params:
             if 'language' in request.params:
    
                salutation = request.params['salutation']
                language = request.params['language']
    
                rs = HelloModel.add_salutation(salutation, language)
                return_status = rs.next()[0]
                rs.commit()
    
                if return_status == True:
                   c.language = language
                   c.hello = salutation
                   response.status = '200 OK'
                   return render("hello/added_salutation.html")
                else:
                   c.language = language
                   c.hello = salutation
                   return render("hello/error.html")
    
             
        def remove_salutation(self):
          if 'salutation' in request.params:
             if 'language' in request.params:
                salutation = request.params['salutation']
                language = request.params['language']
    
                rs = HelloModel.del_salutation(salutation, language)
                return_status = rs.next()[0]
                rs.commit()
    
                if return_status == True:
                   c.hello = salutation
                   c.language = language
                   response.status = '200 OK'
                   return render("hello/removed_salutation.html")
                else:
                   c.hello = salutation
                   c.language = language
                   return render("hello/error.html")
    
    
        def modify_salutation(self):
          if 'old_salutation' in request.params:
             if 'old_salutation' in request.params:
                old_salutation = request.params['old_salutation']
                new_salutation = request.params['new_salutation']
                rs = HelloModel.upd_salutation(old_salutation, new_salutation)
                return_status = rs.next()[0]
                rs.commit()
    
                if return_status == True:
                   c.old = old_salutation
                   c.new = new_salutation
                   response.status = '200 OK'
                   return render("hello/modified_salutation.html")
                else:
                   c.old = old_salutation
                   c.new = new_salutation
                   return render("hello/error.html")
    

Each of these functions does basically the same thing, with small variations. They read the request parameters, and check for essential parameters in the request dict. Then they pull the parameters out, use them to insert, update, or delete fields in the database, and check for success. If the change is successful, there is a page showing what the change was, and if it was not successful, it gives you a very basic error message. Both pages redirect you back to the main page that shows the various salutations and languages. Now, in each of these functions, there are references to rendered pages that are returned. We will go construct those now. 
    
    
    cd ../templates/hello
    

And we will create several files here as well: 
    
    
    nano added_salutation.html
    

And we will paste the following code. 
    
    
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>SUCCESS</title>
      </head>
      <body class="index">
        <div id="header">
          <h1>SUCCESS: Added:</h1>
        </div>
        <p>${c.hello}</p>
        <p>${c.language}</p>
        <p/>
        <a href="/hello">Return home</a>
      </body>
    </html>
    

Save and quit. 
    
    
    nano modified_salutation.html
    

And we will paste the following code. 
    
    
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>SUCCESS</title>
      </head>
      <body class="index">
        <div id="header">
          <h1>SUCCESS: Modified:</h1>
        </div>
        <p>${c.old}</p>
        <p>${c.new}</p>
        <p/>
        <a href="/hello">Return home</a>
      </body>
    </html>
    

Save and quit. 
    
    
    nano removed_salutation.html
    

And we will paste the following code. 
    
    
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>SUCCESS</title>
      </head>
      <body class="index">
        <div id="header">
          <h1>SUCCESS: Removed:</h1>
        </div>
        <p>${c.hello}</p>
        <p>${c.language}</p>
        <p/>
        <a href="/hello">Return home</a>
      </body>
    </html>
    

Save and quit. We will also add a few links to hello.html 
    
    
    nano hello.html
    
    
    
     
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>${c.hello}</title>
      </head>
      <body class="index">
        <div id="header">
          <h1>${c.hello}</h1>
        </div>
        <p>That is hello in: ${c.language}</p>
        <p/>
        <a href="add_salutation.html">Add a salutation</a><br/>
        <a href="remove_salutation.html">Remove a salutation</a><br/>
        <a href="modify_salutation.html">Modify a salutation</a>
      </body>
    </html>
    

Save and quit. We will also add the following code to a new file called error.html 
    
    
    nano error.html
    

And we will paste the following code. 
    
    
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>ERROR</title>
      </head>
      <body class="index">
        <div id="header">
          <h1>ERROR: Failed to add/modify/delete</h1>
        </div>
        <p>${c.hello}</p>
        <p>${c.language}</p>
        <p/>
        <a href="/hello">Return home</a>
      </body>
    </html>
    

Save and quit. Finally, we add a couple of lines to hello.html 
    
    
    nano hello.html
    
    
    
     <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>${c.hello}</title>
      </head>
      <body class="index">
        <div id="header">
          <h1>${c.hello}</h1>
        </div>
        <p>That is hello in: ${c.language}</p>
        <p/>
        <a href="add_salutation.html">Add a salutation</a><br/>
        <a href="remove_salutation.html">Remove a salutation</a><br/>
        <a href="modify_salutation.html">Modify a salutation</a>
      </body>
    </html>
    

This allows us to access the static pages that are in helloworld/public. Now, if you recall from eariler, Pylons needs to know how to point these pages at the appropriate controller and action. And it does that through the routes defined in routing.py. So we now go modify that. 
    
    
    cd ../../config
    
    
    
    nano routing.py
    

And we add the following lines 
    
    
        map.connect('add_salutation', 
                    '/hello/add_salutation', 
                      controller='hello', 
                      action='add_salutation', 
                      conditions=dict(method=['POST']))
        map.connect('remove_salutation', 
                    '/hello/remove_salutation', 
                    controller='hello', 
                    action='remove_salutation', 
                    conditions=dict(method=['POST']))
        map.connect('modify_salutation', 
                    '/hello/modify_salutation', 
                    controller='hello', 
                    action='modify_salutation', 
                    conditions=dict(method=['POST']))
    

These routes will, point the pages at the appropriate controllers and actions, as advertised. The additional conditional dict specifies what sort of HTTP method (GET,POST,DELETE, ect) are supported for this URI. Here we are specifiying POST because all of the form methods associated with these URIs are POST. And this should be the last set of modifications that we need to do to the application. Now, we test our new code. 
    
    
    cd ../..
    

Which should put us into the outermost helloworld directory, with development.ini, so that we can start the server. 
    
    
    paster serve --reload development.ini
    

Now, browsing to 
    
    
    http://localhost:5000/hello
    

Should show you a page like this: 
    
    
    hello
    
    That is hello in: English
    
    Add a salutation
    Remove a salutation
    Modify a salutation
    

With the bottom text being HTML links. Refreshing should take you through various incarnations of "hello" in different languages. Now, we will add an additional greeting. Click the link for Add a salutation. This should take you to another very simple page with a form and a submit button. Here, we are going to add hello for the Thai language. Saluation: sawadee ka Language: Thai So we copy those words into the appropriate form boxes, and click "Submit". We should be taken to a page that looks like this. 
    
    
    SUCCESS: Added:
    
    sawadee ka
    
    Thai
    
    Return home
    

And if we were to look in the database at this time, we would see the entry has been successfully entered into the database. 
    
    
    lacey@blinky:~/project/sql$ psql -U helloworld
    Welcome to psql 8.3.7, the PostgreSQL interactive terminal.
    
    Type:  \copyright for distribution terms
           \h for help with SQL commands
           \? for help with psql commands
           \g or terminate with semicolon to execute query
           \q to quit
    
    helloworld=> SELECT * FROM hello;
      salutation   | language 
    ---------------+----------
     hello         | English
     hola          | Spanish
     bonjour       | French
     merhaba selam | Turkish
     zdravstvuyte  | Russian
     buon giorno   | Italian
     sawadee ka    | Thai
    (7 rows)
    
    helloworld=> 
    

The chain of events is as follows. 
    
    
      1. We type the words into the form.
      2. We click submit.
      3. The words are placed into the http request:
    
      webob._parsed_post_vars: (MultiDict([('salutation', 'sawadee ka'),
      ('language', 'Thai')]), <FakeCGIBody at 
      0x354b5d0 viewing MultiDict([('ol...R')])>)
    
      4. We are routed to the add_salutation function in the hello 
         controller via routing.py
      5. The add_salutation function parses the salutation and language 
         out of the http request.
      6. It then hands it off to Simpycity, which translates it into:
    
      SELECT * FROM public.add_salutation(E'sawadee ka',E'Thai');
    
      7. Which then inserts it into the database, returning true.
      8. We come back to the add_salutation function, which checks the
         return, which is True.
      9. We are routed to the success page. Here, we can click to go back 
         to the /hello page.
    

We can now click to see our newly added salutation and language. (which may take a few tries, since it is randomly selected.) 
    
    
    sawadee ka
    
    That is hello in: Thai
    
    Add a salutation
    Remove a salutation
    Modify a salutation
    

We can modify a salutation as well. Click the modify salutation link, which will bring us to the modify salutation page. We will add capitalization to the Thai greeting that we just added. Type the following into the form pages: Old Salutation: sawadee ka New Salutation: Sawadee Ka And click submit. Again, you will be greeted by a page that looks like this. 
    
    
    SUCCESS: Modified:
    
    sawadee ka
    
    Sawadee Ka
    
    Return home
    

And if we check the database here as well... 
    
    
    lacey@blinky:~/project/helloworld/helloworld/model$ psql -U helloworld
    Welcome to psql 8.3.7, the PostgreSQL interactive terminal.
    
    Type:  \copyright for distribution terms
           \h for help with SQL commands
           \? for help with psql commands
           \g or terminate with semicolon to execute query
           \q to quit
    
    helloworld=> SELECT * FROM hello;
      salutation   | language 
    ---------------+----------
     hello         | English
     hola          | Spanish
     bonjour       | French
     merhaba selam | Turkish
     zdravstvuyte  | Russian
     buon giorno   | Italian
     Sawadee Ka    | Thai
    (7 rows)
    
    helloworld=> 
    

We note that the salutation is now capitalized. The lifecycle of this event is almost exactly the same as the one noted above, except in two places. The routing points at the modify_salutation function, and the upd_salutation function is translated into 
    
    
    SELECT * FROM public.update_salutation(E'sawadee ka',E'Sawadee Ka')
    

Finally, if we decide that we no longer want the salutation Sawadee Ka in the database, we can delete with a very similar lifecycle. Click on the Remove a Salutation Link. Salutation: Sawadee Ka (note that it has to be capitalized now) Language: Thai 
    
    
    SUCCESS: Removed:
    
    Sawadee Ka
    
    Thai
    

Checking the database, we note that it is indeed removed. 
    
    
    lacey@blinky:~/project/helloworld/helloworld/model$ psql -U helloworld
    Welcome to psql 8.3.7, the PostgreSQL interactive terminal.
    
    Type:  \copyright for distribution terms
           \h for help with SQL commands
           \? for help with psql commands
           \g or terminate with semicolon to execute query
           \q to quit
    
    helloworld=> SELECT * FROM hello;
      salutation   | language 
    ---------------+----------
     hello         | English
     hola          | Spanish
     bonjour       | French
     merhaba selam | Turkish
     zdravstvuyte  | Russian
     buon giorno   | Italian
    (6 rows)
    
    helloworld=> 
    

And as noted above, the lifecycle is the same. The routing points at the remove_salutation function, and the del_salutation function is translated into 
    
    
    SELECT * FROM public.remove_salutation(E'Sawadee Ka',E'Thai')
    

Thus, removing it from the database. This now completes our small web application. Combining Simpycity, Pylons and PostgreSQL, we have made an app that displays database content, and creates, updates, and deletes that content, which is the core functionality of any database driven web application.   
  
And this also concludes our PostgreSQL->Simpycity->Pylons tutorial.   
  
Thank you for following along. =)

---
[View this page online](https://www.commandprompt.com/blog/pylons_postgresql_and_simpycity_in_60_minutes_or_less/)

---

# The shortest path between two points

> Recently I was doing some benchmarking on one of our machines. The benchmarking wasn&#x27;t going so well due to bad batteries on the RAID controller. I had instruc…

Recently I was doing some benchmarking on one of our machines. The benchmarking wasn't going so well due to [bad batteries on the RAID controller](<http://www.commandprompt.com/blogs/joshua_drake/2009/05/hardware_problem_solved_when_you_really_need_some_cache/>). I had instructed one of our System Administrators to take care of the problem. Long story short, the Administrator went down a very long trail to an obvious solution. The trail was well mapped, thought out and precise. It however missed some important points. When I caught on to the long trail she was taking I asked, "What is the shortest path between two points?". She replied, "On a plane or sphere?". That is when I knew we were in trouble. Now most people would have just said, "Huh?". Luckily I have been blessed with at least a modicum of technical/mathematical knowledge and a general experience with Geeks for 18 years. Let's review. **The System Administrators trail was:**

  * Visit Colo to check cards physically after receiving BIOS message 
  * Record all information about cards including BIOS versions 
  * Research possible cause of batteries not charging, find that some versions of the BIOS can do that. Thus causing yet another trip to the colo for installation. 
  * Go back to colo to update BIOS revisions to see if that resolves the problem
    * If that doesn't solve the problem, research new batteries for order 

**My trail:**

  * System reports batteries are bad 
  * Known fact: Hardware was bought used 
  * Buy new batteries 
  * Upgrade BIOS during new battery installation 

What is the difference? I run into this a lot with technical people. They become hyper focused and they are not able to abstract their problem solving skills to include the entirety of the problem. Now you say, "What the problem is the batteries don't work, fix them." It isn't that simple. Using the System Administrators path, the solution to the problem cost at least 1500.00-2000.00. Using my path, the cost is 550.00. My path is a single trip to the collocation facility with cards drop shipped, an hour to replace and upgrade BIOS. Same resolution, ~ 37% of the cost. **But... But... what if that doesn't fix the problem?** Then you know you have bad cards and it will still cost less to replace them that to perform multiple trips to the colo. Again it isn't that the System Administrators path was incorrect. In fact I would bet a lot of businesses would think it was the absolutely correct direction to take. I would rather just write off the cards and replace them. We can make far more money from the System Administrator if they are not focusing on long and winding roads to the same destination that can be reached by not taking a left at the fork.

---
[View this page online](https://www.commandprompt.com/blog/the_shortest_path_between_two_points/)

---

# Hardware problem solved, when you really need some cache.

> As reported in my last blog, Stefan was having much greater success with his pgbench results than I. In reviewing why, we found a problem with the hardware. Wh…

As reported in my last blog, Stefan was having much greater success with his pgbench results than I. In reviewing why, we found a problem with the hardware. What I like about this problem is that the results in the [previous blog post](<http://www.commandprompt.com/blogs/joshua_drake/2009/05/837_tps_and_checkpoint_segments/>) become more interesting. As a reminder I was running 16 connections over 4 different users at 1M transactions. Below is the results from a single user from that batch: 
    
    
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 101.024360 (including connections establishing)
    tps = 101.024392 (excluding connections establishing)
    

Over 16 connections we were getting ~ 400 TPS. I verified that this was consistent by running a second test with a single user and 4 connections. The results: 
    
    
    pghost: localhost pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 404.021738 (including connections establishing)
    tps = 404.022316 (excluding connections establishing)
    

So, what is it that causes a machine with plenty of resources to perform in such a consistently slow manner?. You can only write data as fast and the spindles turn. That is why they invented cache. The results should look very similar to Stefan's once we replace the battery cache.

---
[View this page online](https://www.commandprompt.com/blog/hardware_problem_solved_when_you_really_need_some_cache/)

---

# Thanks Stefan

> So while doing the benchmarking of the various parameters, Stefan pointed out the my numbers were ridiculously low. I wasn&#x27;t really paying attention because I …

So while doing the benchmarking of the various parameters, Stefan pointed out the my numbers were ridiculously low. I wasn't really paying attention because I was looking at differences between parameters but then he posted me an example of a single thread pgbench using my same parameters. His machine is a dual core connected to 10 spindles on a NetAPP. In theory my machine should be faster. It is not. His configuration, like mine was all defaults. Stefan's numbers. 
    
    
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 1681.615766 (including connections establishing)
    tps = 1681.622950 (excluding connections establishing)
    

So now I am trying to figure out what is up with my hardware.

---
[View this page online](https://www.commandprompt.com/blog/thanks_stefan/)

---

# 8.3.7 TPS and checkpoint segments

> Continuing my postgresql.conf changes I ran a new test yesterday with checkpoint_segments set to 300. As a reminder the original results and specs of the machi…

Continuing my postgresql.conf changes I ran a new test yesterday with checkpoint_segments set to 300. As a reminder the original results and specs of the machine being used in the test are [here.](<http://www.commandprompt.com/blogs/joshua_drake/2009/05/default_tps_performance_of_837/>) The results of the new test below: 
    
    
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 101.024360 (including connections establishing)
    tps = 101.024392 (excluding connections establishing)
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 100.796885 (including connections establishing)
    tps = 100.796924 (excluding connections establishing)
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 100.801501 (including connections establishing)
    tps = 100.801534 (excluding connections establishing)
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 100.852900 (including connections establishing)
    tps = 100.852944 (excluding connections establishing)
    

O.k. so same test, same hardware, 10x more checkpoint_segments gives us ~8 percent improvement.

---
[View this page online](https://www.commandprompt.com/blog/837_tps_and_checkpoint_segments/)

---

# Default TPS performance of 8.3.7

> I recently purchased some used hardware for some performance testing of PostgreSQL. I didn&#x27;t want to interrupt the great work that Mark Wong was doing with the…

I recently purchased some used hardware for some performance testing of PostgreSQL. I didn't want to interrupt the great work that Mark Wong was doing with the PostgreSQL Performance Lab. The testing I am doing is a bit different than Mark's. Where Mark is testing various filesystem performance via PostgreSQL using DBT2 and FIO and wanted to go up a level. I am testing using the PostgreSQL tool pgbench which is available in contrib. I am also testing in a basically default environment as a way to see how changing different parameters of the postgresql.conf changes overall performance. **Hardware Configuration**

> Newisys Quad Opteron 846 32GB of memory (2) MSA 30s (RAID 10, 14 drives each) (2) HP 6402 Controllers (one for each MSA) 

**Operating System Configuration**

> Ubuntu Hardy LTS x86_64 /array1 , ext3, data=writeback elevator=deadline 

Outside of the minor operating system changes the system remained in default. The only postgresql.conf parameter I changed was to set checkpoint_segments to 30.   
**pgbench configuration** I used four pgbench instances within a single database with four schemas. Each schema was assigned to its own pgbench user 01-04. The pgbench command used was: 
    
    
    /array1/jd/pgsql/bin/pgbench -U bench01 -s10 -t1000000 -c4 -p 6000 -d bench \
    > bench01&
    /array1/jd/pgsql/bin/pgbench -U bench02 -s10 -t1000000 -c4 -p 6000 -d bench \
    > bench02& 
    /array1/jd/pgsql/bin/pgbench -U bench03 -s10 -t1000000 -c4 -p 6000 -d bench \
    > bench03&  
    /array1/jd/pgsql/bin/pgbench -U bench04 -s10 -t1000000 -c4 -p 6000 -d bench \
    > bench04&
    

**Results**
    
    
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 92.279931 (including connections establishing)
    tps = 92.279960 (excluding connections establishing)
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 91.674708 (including connections establishing)
    tps = 91.674739 (excluding connections establishing)
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 91.583754 (including connections establishing)
    tps = 91.583782 (excluding connections establishing)
    pghost:  pgport: 6000 nclients: 4 nxacts: 1000000 dbName: bench
    transaction type: TPC-B (sort of)
    scaling factor: 100
    number of clients: 4
    number of transactions per client: 1000000
    number of transactions actually processed: 4000000/4000000
    tps = 91.616330 (including connections establishing)
    tps = 91.616355 (excluding connections establishing)
    

Each pgbench process executed 4M transactions with an average of ~ 24TPS per client. That is pretty miserable. However remember this is defaults and the defaults will make you checkpoint quite a bit (every 20 seconds or so) with the above stress test. Stay tuned for results as we change specific parameters to see the effect each one has.

---
[View this page online](https://www.commandprompt.com/blog/default_tps_performance_of_837/)

---

# Surprising events from a top 20 list

> In a completely unscientific review of community popularity I was reviewing the active members of various channels on #freenode. For those that don&#x27;t know, Fre…

In a completely unscientific review of community popularity I was reviewing the active members of various channels on #freenode. For those that don't know, Freenode is the defacto destination for the Open Source community on IRC. This is where you will find official community support channels for such open source luminaries as #gentoo, #ubuntu, #mysql and of course #postgresql. **The List**

  1. Ubuntu 
  2. Gentoo 
  3. Linux 
  4. Debian 
  5. Python 
  6. ArchLinux 
  7. Django 
  8. Haskell 
  9. Perl 
  10. C 
  11. Git 
  12. RubyOnRails 
  13. C++ 
  14. PHP 
  15. Fedora 
  16. Jquery 
  17. Vim 
  18. KDE 
  19. PostgreSQL 
  20. Drupal 

I find a couple of data points that can be made from this list. Debian and its kissing cousin Ubuntu are clearly stomping everyone around them in the community driven Distro wars. There are surprising entries such as ArchLinux, Haskell and Vim. O.k. I am not surprised about Vim, if you are using it you clearly will need a lot of help. Even as a Python zealot I was surprised to see that it was above Perl in the listing. However to be fair I know that there is an irc.perl.org which has a large base. There is not an equivelant for Python so it is quite possible that if you take into account irc.perl.org, Perl would overtake Python. Of course all of this is dodging the real point. The real point is that the "World's most popular database" isn't even in the top 30. Now there will be many out there that say, "You can't judge the community by IRC alone." That is certainly true and I am not trying to spread doom and gloom about MySQL. The only reason I am pointing this out is that it was just an extremely short while ago that MySQL consistly had more users in channel than PostgreSQL. Power to the Elephant. Power to the People. Fight the Power.

---
[View this page online](https://www.commandprompt.com/blog/surprising_events_from_a_top_20_list/)

---

# Long Running Request Handlers and Python Garbage Collection

> While working on a Simpycity + Pylons environment the other day, I noticed that my app was leaking Postgres connection handles. This is not behaviour you ever …

While working on a [Simpycity](<https://public.commandprompt.com/projects/simpycity>) \+ [Pylons](<http://pylonshq.com>) environment the other day, I noticed that my app was leaking Postgres connection handles. This is not behaviour you ever want to see, especially in software as vital as Simpycity. Investigation and testing demonstrated pretty conclusively [here,](<https://projects.commandprompt.com/public/simpycity/pastebin?show=f5d51e358%0D>) and [here](<https://projects.commandprompt.com/public/simpycity/pastebin?show=f41b90427%0D>) that the Python garbage collector was **not** immediately cleaning up dead/unreferenced objects. Specifically, in the test case below,  
  

    
    
     def foo():
          r = Raw("SELECT count(*) as cnt, usename, current_query FROM 
     pg_catalog.pg_stat_activity GROUP BY usename,current_query ORDER BY cnt 
     DESC")
          return r()
    
     foo()
     

when executed in the Python interactive interpreter, a dangling (unassigned) ResultSet object in remained in memory. Even though no references to the object exist, and it should be cleaned up, it will **not** be cleaned up until another garbage collection event is triggered. Calling locals(), globals() or by forcibly executing the garbage collection via import gc; gc.collect() will clean up the stray ResultSet as expected. Model-based objects exhibit the same behaviour.   
  
As the Postgres handles are being created (by default) READ COMMITTED, they are left in the state " in transaction". This part can be handled via calling .commit() on all handles, but, still prone to the leaking/cleanup issue. At its core, the leaking issue stems from design choices behind Simpycity; specifically, abstracting away the connection management logic leaves us in the position where automatic management cannot depend purely on the Python garbage collector for handle cleanup. This lifecycle issue affects Simpycity under Pylons, as well.  
  
By relying on the Python garbage collection, a request's Postgres connections fall out of scope, but are not reaped until **later** , when the mod_wsgi subprocess accepts and handles a new request. Once we realized how this happens in the interactive interpreter, we saw that in an environment such as mod_wsgi or mod_python, with multiple active subprocesses, lurking/hanging sessions will inevitably occur.  
  
When Lacey and I studied [SQLAlchemy](<http://www.sqlalchemy.org/>), it appeared vulnerable to the same behaviour; Reading over their pooling logic, as well as examining a Pylons app configured to use SQLAlchemy in the Paster template showed they are **explicitly** cleaning up all DB connections after every Pylons request. This was implemented using a  
  

    
    
     try:
          ...
     finally:
          ...
     

block in the core Pylons controller, as well as the global initialization of a db connection during Pylons setup (see model/meta.py, model/__init__.py, lib/base.py in a default Pylons project setup as an example). As Pylons + SQLAlchemy is not our default environment, this was initially missed.  
  
Discussion with James Bennett (ubernostrum, irc.freenode.net) shows that the Django ORM has a similar issue. Django resolves this with an asynchronous message-passing system, which, at the end of a Request cycle, notifies the ORM backend that the opened connections should be terminated. Therefore: **Reliance on Python's garbage-collection cycle is fickle at best, especially in long-running, asynchronous processes such as Pylons.**  Based on the SQLAlchemy mechanisms within Pylons, specifically the end-of-request session cleanup, it seems reasonable to implement a session manager for Simpycity.  
  
This would exist to only to handle long-running scenarios where automatic garbage collection would not be able to consistently run. The connection manager would need to do little more than maintain a list of all active/open handles, and offer a .cleanup() call to free all handles at the end of the request. Coupled with the explicit try-finally cleanup pattern that SQLAlchemy uses within the Pylons WSGIController, a connection manager would succinctly solve the problem. **This would maintain correct transactional integrity, because implicit commits are never issued to the PostgreSQL backend. The leaking handle issues would vanish, because we know that the only handles used within Simpycity will be tracked within the connection management object, and correctly cleaned up after each request.**  
  
In short-run applications, this is largely a non-issue, as the exiting of the interpreter closes all extant handles automatically. As this is a subtle issue, we'll be providing an upstream patch for Pylons, to provide a Paster template specifically to set up a connection management environment for Simpycity. This will also be documented on the Simpycity [wiki](<https://public.commandprompt.com/projects/simpycity/wiki>), discussing how to set up a connection manager and use it for long-running programs.

---
[View this page online](https://www.commandprompt.com/blog/long_running_request_handlers_and_python_garbage_collection/)

---

# My turn on Oracle purchasing Sun.

> I feel like I am coming late to this topic. All the pundits have already had there say and the blogosphere has been rampant. I have been talking with a lot of …

I feel like I am coming late to this topic. All the pundits have already had there say and the **blogosphere** has been rampant. I have been talking with a lot of MySQL folks lately, encouraging them to at least test PostgreSQL as an alternative. MySQL folks are nervous. They don't like the _opportunity_ Oracle brings to the table. This morning I was asked quite bluntly, "From your perspective what is the future of MySQL?".  
  


It is an interesting question because in my perspective MySQL has always been a "just good enough" second class citizen in the database world. I don't run into a lot of MySQL migrations because the Command Prompt's customers are generally already PostgreSQL folks or asking us to implement something anew. Trying to be objective I think MySQL will live on in various incarnations but I do think its glory days are over. It will be a supported (for a short time) but second class citizen from Oracle. In the Sun purchase Oracle was primarily after two things with Sun, Solaris and Java.   
  
During Innotech yesterday I was [speaking on the open source panel](<http://vimeo.com/4307197>) and one of the participants stated that they were nervous about the fact that MySQL had been bought twice in the last two years. I did mention that I didn't think MySQL was going away and that Oracle is a smart company and there is a lot of mind share with MySQL. However, Oracle is not interested in the 1000.00/yr business. That is the majority of MySQL revenue. It was estimated that MySQL AB was only doing 50M a year when they were bought by Sun. 50M a year is petty cash for Oracle. I only see two outcomes (both with variations).   
  
Oracle will completely change the MySQL model to make it more profitable and thus alienate its majority user base (small websites) or maintain it long enough to allow MySQL to kill itself. MySQL is already killing itself through the various forks that have permeated in the last 9 months. I see a large possibility of mass migration from MySQL by non web applications. Yes there are a lot of them. Why? Because one way Oracle can make money from MySQL is to continue to charge for "linked" software against MySQL.   
  
If you are building a web app as long as your web language is open source, you are good with the GPL. If you are building a monolithic app in say C++ you have a serious problem because the nature of the GPL guarantees that your C++ app will have to be open source (assuming you are linking to MySQL libs versus something like ODBC). The majority (by far) of the world still isn't using Open Source. MySQL does have a strong following in the appliance world and if Oracle opts to start charging for MySQL closed applications the way they charge for Oracle the appliance world is going to run, not walk to other technologies.   
  
The obvious choice is PostgreSQL because of the BSD license and the maturity of the software. In conclusion I expect that MySQL in two years likely won't exist except on the most tertiary level. Most new projects will be developed in either PostgreSQL, Firebird or one of the forks (MariaDB, Drizzle).

---
[View this page online](https://www.commandprompt.com/blog/my_turn_on_oracle_purchasing_sun/)

---

# The great netbook giveaway

> At PostgreSQL Conference East, Platinum Sponsor EnterpriseDB raffled two Netbooks. This is the video of the raffle (only 5 minutes). Of particular interest is …

At PostgreSQL Conference East, Platinum Sponsor [EnterpriseDB](<http://www.enterprisedb.com/>) raffled two Netbooks. This is the video of the raffle (only 5 minutes). Of particular interest is a certain Major Contributors response.

---
[View this page online](https://www.commandprompt.com/blog/the_great_netbook_giveaway/)

---

# Escaping data madness

> We had an interesting issue crop up this past week. The question was, &quot;How do we properly escape the following string...?&quot;. The string was:
You can&#x27;t have it …

We had an interesting issue crop up this past week. The question was, "How do we properly escape the following string...?". The string was:
    
    
    You can't have it that way can you?
    

That seems like a pretty simple string right? On insert you would do one of the following:
    
    
       (E'You can\'t have it that way can you?');
       ($$You can't have it that way can you?$$);
       ('You can''t have it that way can you?');
    

You would think that would be the end of it. However, If you are using ODBC with a pass through query you will receive the error, "The # of binded parameters is < than the # of parameter markers." Yes, that's right. ODBC will parse the ? and interpret it as a parameter. This affects psqlodbc and ODBCng. Apparently it is actually not a bug [1]. I am not sure I agree with that, regardless of what Microsoft says. What is particularly interesting here is that it is specifically the ? that is the problem. Not the single quote. To work around this problem you can execute the query like this:
    
    
    INSERT INTO foo VALUES ($$You can't have it that way can you?$$);
    INSERT INTO foo VALUES ('You can''t have it that way can you?');
    

Of course neither of those are actually standard (the E'\'' is standard). 1\. [MSDN Data Platform developer center](<http://msdn.microsoft.com/en-us/library/ms713534\(VS.85\).aspx>)

---
[View this page online](https://www.commandprompt.com/blog/escaping_data_madness/)

---

# Registration closing for PostgreSQL Conference East

> As a reminder for all of those in our community that like to register at the last minuted (that means most of us), registration will be closing on Wednesday Ap…

As a reminder for all of those in our community that like to register at the last minuted (that means most of us), registration will be closing on Wednesday April first. On line registration is much easier than registering at the door so please bounce on over to [PostgreSQL.us/purchase](<http://www.postgresql.us/purchase>) and get your registration in.

---
[View this page online](https://www.commandprompt.com/blog/registration_closing_for_postgresql_conference_east/)

---

# PostgreSQL Training

> Command Prompt has offered training since we began as a one man shop back in 1997. It has always been, &quot;by request&quot;. Since that time a lot of things have chang…

Command Prompt has offered training since we began as a one man shop back in 1997. It has always been, "by request". Since that time a lot of things have changed and we are regularly receiving training requests from multiple companies. We have decided to finally bring our training into the light and make it a forefront of the services that CMD offers. Interestingly we are going to be providing a lot of ad-hoc, webcast style training (as well as traditional on site or classroom). The number one training we are asked for is something that is half day that covers a specific topic such as backup and restore or configuring Point in Time Recovery. These types of courses will be cost effective for even small establishments and will be held over the Internet. We will also be participating in the open curriculum community ensuring that most if not all of our curriculum is freely available for self starters. What other training provider is going to do that? Here is our current [list of pre-defined courses](</services/training>). We will be adding a dozen or so more in the next 90 days.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_training/)

---

# PostgreSQL Conference East: Final Schedule announced

> PostgreSQL Conference East is the Eastern segment of the United States PostgreSQL Conference series. The event is being held at Drexel University. It starts on…

PostgreSQL Conference East is the Eastern segment of the United States PostgreSQL Conference series. The event is being held at Drexel University. It starts on April 3rd and runs through April 5. We kick the conference off on April 3rd with three sessions. For DBAs we have Mastering PostgreSQL Administration a four hour training, presented by PostgreSQL Core Team member Bruce Momjian. For Developers we have a Database Normalization, a 4 hour workshop. Finally for those who are seeking information on the upcoming 8.4 release we have a 3 hour guide to PostgreSQL 8.4 presented by Major Contributor Robert Treat. April 4th and 5th are a plethora of mini-tutorials and sessions. The talks range from Pylons and Grails development with PostgreSQL to Understanding Column Level privileges, Windowing Functions, the Art of Indexes, four presentations on different Replication technologies and a Performance Round Table. In all we have 35 sessions. There is no question that there is something at this conference for every PostgreSQL user. We will close out the conference with a raffle of two Asus EEEPC 1000 preloaded with Ubuntu Intrepid and Postgres Plus from [Platinum Sponsor EnterpriseDB.](<http://www.enterprisedb.com/>) The proceeds of East are being donated directly to the United States PostgreSQL (PgUS) Association. You may [view the schedule.](<http://www.postgresqlconference.org/2009/east/>) [You may register here.](<https://www.postgresql.us/purchase>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_final_schedule_announced/)

---

# More PostgreSQL Conference goodness, West 08 Keynote

> This is the Keynote I gave at West 08 last October. Topics include updates on the various non-profits, reach out to tertiary communities, recognition of the im…

This is the Keynote I gave at West 08 last October. Topics include updates on the various non-profits, reach out to tertiary communities, recognition of the importance of non direct PostgreSQL participation as well as many others (such as 8.4 and replication). Those interested in participating in the [upcoming East should visit here and register.](<http://www.postgresql.us/purchase>)

**Can we do anything more in 6 months?**

**Slides**

**[PostgreSQL Conference: West 08](<https://www.slideshare.net/linuxpoet/postgresql-conference-west-08-presentation> "PostgreSQL Conference: West 08")**

---
[View this page online](https://www.commandprompt.com/blog/more_postgresql_conference_goodness_west_08_keynote/)

---

# Remembering excellence from past PostgreSQL Conferences

> Just about 5 months ago we held PostgreSQL Conference, West 2008 in Portland Oregon. It was a very successful conference with approximate 20% growth over the p…

Just about 5 months ago we held [PostgreSQL Conference, West 2008](<http://www.postgresqlconference.org/2008/west>) in Portland Oregon. It was a very successful conference with approximate 20% growth over the previous West in 2007. It was also a three day conference over the previous West event which was a single day conference. As we prep to hold [PostgreSQL Conference, East 2009](<http://www.postgresqlconference.org/2009/east/>) at Drexel University I wanted to look back at one of my favorite talks from West. Developing a PL for PostgreSQL is a hilarious but technically accurate presentation on creating procedural languages for PostgreSQL, the catch? The presentation uses LOLCode.

**Josh Tolley - Developing a PL for PostgreSQL**

**Slides**

**[Developing A Procedural Language For Postgre Sql](<https://www.slideshare.net/linuxpoet/developing-a-procedural-language-for-postgre-sql> "Developing A Procedural Language For Postgre Sql") **

---
[View this page online](https://www.commandprompt.com/blog/remembering_excellence_from_past_postgresql_conferences/)

---

# Pg Conference East 09, Registration open

> This year is shaping up to be an even larger even than last year with 3 days, four rooms, and multiple tracks. East runs from April 3rd to April 5th at Drexel …

This year is shaping up to be an even larger even than last year with 3 days, four rooms, and multiple tracks. East runs from April 3rd to April 5th at Drexel University. To register please point your [Open Source web browser to PgUS.](<https://www.postgresql.us/purchase>) Registration is free for Students and Professors and starts at as low as 40.00 for University staff. Once you have registered make sure to [visit and subscribe to the attendees list.](<http://lists.postgresqlconference.org/mailman/listinfo/attendees>) The attendees list is the way to find out about all the goings on of the conference. Here is a sampling of the content to be presented at this years East:  
**Web**

> An Introduction to the Pylons Web Application Framework  
>  Architecting Your PostgreSQL Application for the Cloud  
>  Grails In Practice  
>  Building A Collaborative Environment With PostgreSQL To Enhance  
>  The Learning Experience  
> 

**Replication/HA**

> PostgreSQL Backup/Recovery and Replication  
>  Replication using PostgreSQL Replicator  
>  Reconciling and comparing databases using schemas, DBI-Link and Slony  
>  Bucardo  
>  Introduction to Golconde  
>  Configuring a Warm Standby, the Easy Way  
> 

**Performance**

> Predicting Postgres Performance: Practical Queueing Theory for Postgres DBAs  
>  pgcrypto benchmarking  
>  The Art of Indexes  
>  Effects of Flash and SSDs on PostgreSQL  
>  Using and Abusing pgbench  
> 

**8.4**

> Column-Level Privileges, and other changes coming in 8.4  
>  Trees and More in PostgreSQL: Common Table Expressions  
>  Windowing Functions: Putting the TPS in TPS Reports  
>  No More Waiting, A guide to PostgreSQL 8.4  
> 

**Usage, Development Newbie and Administration**

> The power of psql  
>  Playing with Playr: The Postgres Application Testing Tool  
>  Postgresql and Java  
>  Converting your database and application from Sybase/MSSQL to PostgreSQL  
>  ERP built by Postgres: We don't need no stinkin toolkit!  
>  PostgreSQL and Temporal Data  
>  Database Development Policies  
>  Monitoring Postgres with check_postgres.pl  
>  More Than Storage: Intro to PL/pgSQL  
>  Socially Relevant Database Projects in the Undergraduate Classroom  
>

---
[View this page online](https://www.commandprompt.com/blog/pg_conference_east_09_registration_open/)

---

# Seven things

> Theo Schlossnagle recently wrote a blog post called seven things. The idea is, seven things that you &quot;might&quot; want to know about him. Along those lines he liste…

[Theo Schlossnagle](<http://lethargy.org/~jesus/>) recently wrote a blog post called [seven things.](<http://lethargy.org/~jesus/archives/140-Seven-things..html>) The idea is, seven things that you "might" want to know about him. Along those lines he listed me as someone he would like to know seven things about. It has taken me a while to get to the post because I have been busy with [various](<http://www.commandprompt.com/>) [things](<http://www.postgresqlconference.org/>). So here we go, seven things about me.

>   * I have crashed a car at 135MPH and walked away. 
>   * I did not finish High School. 
>   * I am a [master gardener.](<http://extension.oregonstate.edu/mg/>)
>   * I am an entrepreneur not a computer geek. 
>   * I think the Open Source community needs to learn when to be quiet. 
>   * I hate it when people think I should care about **x**. 
>   * I spent two recent years being someone, I am not. This problem has been resolved. 
> 


The second part of this blog is I am supposed to list seven people I would like to know seven things about. This has struck me as more difficult than I imagined. Most of the people I want to know about, don't blog and barely email. Many other people don't interest me. Here we go:

>   * [Michael Stonebraker](<http://www.csail.mit.edu/people/Michael_Stonebraker/reminder>), because PostgreSQL doesn't interest him. 
>   * [Magnus Hagander](<http://blog.hagander.net/>), because he is my counterpart in [Europe](<http://www.postgresql.eu>). 
>   * [Richard Stallman](<http://www.stallman.org/>), because I have never seen a bigger hippy that is still living. 
>   * [W. Somerset Maugham](<http://en.wikipedia.org/wiki/W._Somerset_Maugham>), because he is one of the best authors I have ever read (yes I know he is dead). 
>   * [Bruce Momjian](<http://www.momjian.us/>), because I realized he is a friend. 
>   * [Robert Treat](<http://www.xzilla.net/>), because I think he will struggle like I did to come up with this list. 
>   * [Tom Lane (TGL)](<http://en.wikipedia.org/wiki/Tom_Lane_\(Open_Source_Software_Developer\)>), because after all these years he will still graciously answer my email. 
>

---
[View this page online](https://www.commandprompt.com/blog/seven_things/)

---

# PostgreSQL Conference: Talk deadline approaching

> The deadline (Feb, 23rd) is fast approaching for PostgreSQL Conference East talk submissions. Get your talk in today! 

The deadline (Feb, 23rd) is fast approaching for PostgreSQL Conference East talk submissions. [Get your talk in today! ](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_talk_deadline_approaching/)

---

# PostgreSQL mininum requirements

> In this article we will be discussing the minimum requirements for production usage of PostgreSQL whether on-prem or in the cloud. We will not be discussing pr…

**Updated: 08/10/2022**

 **Joshua D. Drake**

In this article we will be discussing the **minimum** requirements for **production** usage of PostgreSQL whether on-prem or in the cloud. We will not be discussing proprietary forks such as Amazon RDS or other Open Source forks such as Yugabyte or Greenplum.

PostgreSQL is the Linux of databases. It provides the kernel and key features to the most critical database services available today. These include but are not limited to:

  * Greenplum
  * Yugabyte
  * Amazon RDS for PostgreSQL
  * Amazon Aurora for PostgreSQL
  * Azure Database for PostgreSQL
  * AlloyDB
  * Cloud SQL for PostgreSQL
  * NeonDB



It also provides key infrastructure to other databases such as Cockroach.

Supported Platforms

PostgreSQL is supported on a number of platforms including various cloud providers. The canonical source for the officially supported list of Postgresql.org platforms is the [supported platforms page](<https://www.postgresql.org/docs/current/supported-platforms.html>).

Cloud

The scope of this article will not allow us to discuss specific cloud instance options. Instead we are going to focus on general minimum requirements for running with the cloud. These options will be valid across all major platforms but will not include proprietary forks such as AlloyDB, Aurora, RDS or Hyperscale. That is not to say those platforms aren’t useful or good, just that they are not PostgreSQL.

An advantage to modern cloud platforms is that you can customize your instance to your needs. During your initial provision you may only need 2GB of memory and 2CPUs but suddenly your new product or service takes off… Instead of having to buy all new hardware and perform a migration you can upgrade your instance to a more powerful implementation and reboot. It becomes a very quick outage versus a long, drawn out, planned migration.

## The Basics

  * 1GHZ Dual Core processor
  * 2GB of memory
  * 2GB of disk space
  * RAID 1
  * Linux



### Processor & Memory

In a cloud environment, you usually choose an instance configuration instead of a specific processor speed. This allows you to modify some specific memory and processor requirements within a single bundle. It also allows you to select a type of instance that is specific to your workload, for example memory favored or CPU favored.

#### Google Cloud

When using Google cloud the minimum instance size for GCE (Google Compute Engine) would be the e2-small which provides 2 shared core CPUs and 2GB of memory. These are [shared-core instances](<https://cloud.google.com/compute/docs/general-purpose-machines#e2-shared-core>) and do provide specific limitations to be aware of, including a maximum disk space of 3TB per persistent disk. If you are looking for a similar configuration but with a non-shared core, we would recommend the e2-standard-2 which provides more reliable performance with 2vCPUs and 8GB of memory.

#### AWS

Using AWS for PostgreSQL can be a bit more challenging due to the AWS pricing model. If we adhere to the minimum requirements then the AWS EC2 instance m4.large might be what a good choice. It has 2vCPUs and 8GB of memory. However, it is an “EBS volume only” instance and it limits your EBS bandwidth to 450Mbps. Since it is limited to EBS volumes, it would not be difficult to reach that limitation depending on the configuration of your EBS volumes and the velocity of your database traffic.

### Disk Space

In the cloud this is not as straightforward. There is a production advantage to being able to dynamically add storage to an instance. It increases uptime and the resilience of your data. However, the cloud can make disk usage overly complicated. When using lower tier instances it is common to only allow the use of network based volumes. It is also common to restrict the performance of those volumes based not only on instance size but also size of disk.

#### AWS

When provisioning for AWS your minimum requirements are limited by the use of only EBS volumes and having limited EBS volume bandwidth. Using the aforementioned instance type of m4.large, we can provision the appropriate size of a minimum of 2GB of disk but we will have to provision 2 EBS volumes so we achieve the minimum requirement of RAID 1. You are then limited to 450Mbps in total for the two volumes. Put another way, due to the limitations of the instance, the provisioned database would be the equivalent of having an On-Prem server with (2) SAS drives in a RAID 1. One can find further information on [AWS instance options and limitations here.](<https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html>)

#### Google Cloud

Provisioning for Google Cloud can be simpler as they allow you to modify the size and type of your boot disk. Though this boot disk is not redundant and does not meet the requirements of RAID 1, it can meet your performance requirements. The minimum size is 10GB. GCE also provisions the speed of a disk by type and size of disk. You can find [more on this topic here.](<https://cloud.google.com/compute/docs/disks/performance>)

### RAID 1

The cloud provides a false sense of security when it comes to the resilience of your data. There is a plug and go mentality. Unfortunately, like any configuration there is a risk of failure. If you allow your data to reside on a single EBS (or local) volume. You are at similar risk as if you allow your data to reside on a single local disk using On-Prem. Yes, you can (and you should) have backups, snapshots, point in time recovery etc… However, nothing will beat the ability to lose a volume and continue operating while you provision a new volume and add it to an existing operating array without causing an outage.

### Linux

Equal to On-Prem, one should use Linux for PostgreSQL. This is not a slight against any other operating system (looking at you FreeBSD). PostgreSQL is tested most widely on Linux and the ecosystem is centered around Linux. Further PostgreSQL takes a specifically Linux/Unix view of its configuration and administration which makes it feel foreign to Windows users (though Microsoft has proven that PostgreSQL runs well on Windows). We further recommend that you stick with widely and externally supported Linux distributions such as Debian, RHEL, SLES and Ubuntu LTS. One should try to avoid vendor centric distributions such as Amazon Linux.

* * *

### On-Prem

Though a solid percentage of PostgreSQL users are migrating to the cloud, whether it be via instances such as EC2 or managed services such as RDS for PostgreSQL, they are still dwarfed in regards to the overall population of on-prem installations. If you have the staffing and expertise, on-prem can offer a lot of options that the cloud will not or cannot do in a cost effective manner. There is also an argument that by moving to the cloud you are increasing external risk.

## The basics:

  * 1GHZ Dual Core processor
  * 2GB of memory
  * 2GB of disk space
  * RAID 1
  * Linux



### Processor

PostgreSQL is process based and this means it can do literally only one thing per process, per core, at a time. The use of technology such as context-switching helps but the inherent physical limitation still exists. Though there are applications that will work fine in that scenario, your scalability goes up significantly in a multi-core scenario. Even if your application only uses a single processor, there are other processes running in the background of PostgreSQL (wal writer, bgwriter, stats collector, autovacuum, etc.) that you want to make sure you have resources for outside of the application itself. One should also avoid anything that isn’t 64bit.

### Memory

The 2GB of memory is a recommendation for memory you can allocate to PostgreSQL outside of the operating system. If you have a small data set, you are still going to want enough memory to cache the majority of your hot data (you can use pg_buffercache to determine your hot data). With 2GB of memory you could allocate 512MB of shared buffers for hot cache and leave 1.5GB for maintenance daemons, parallelism, and work_mem.

### Disk space

There are some articles that suggest that you can provision with 512MB of disk space. Unfortunately, those articles are not taking into account the default configuration of current PostgreSQL installations. Consider that max_wal_size defaults to 1GB, plus you have parallelism of capabilities that use work_mem (which can spill to disk), maintenance_work_mem (which can spill to disk), and you still need at least some space for your data and indexes.

### Raid 1

When speaking of disks for on-prem and in almost all circumstances for production, you need at least RAID 1. RAID 1 will not provide any write performance increase but depending on the driver/controller will provide read performance increases. Further, it provides redundancy just in case that backup is out of data, or you have specific uptime requirements that will prevent you from shutting the database down to restore a backup. Remember: though NVME Data Center drives are ridiculously fast (and reliable), if one fails – you can be in a world of hurt if you don’t have proper redundancy.

### Linux

While it is true that PostgreSQL runs on a vast array of operating systems, PostgreSQL is tested most widely on Linux based operating systems. This is not to take away from the other operating systems out there (@FreeBSD: looking at you!). The use of Linux is going to provide you with the widest capability of expertise and knowledge bases for properly running PostgreSQL. We would also recommend that the installation of Linux you use is an LTS release such as Ubuntu LTS, Redhat RHEL, SLES, etc.

While not a comprehensive manual in provisioning PostgreSQL, it is the hope that this article provides someone who wants to work with PostgreSQL a starting point that is performant, reliant and sheds some light on the difficulties in just “using PostgreSQL”. In future articles we will discuss other topics such as Replication, Snapshots, how to provision in a high performance manner and connection pooling.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_mininum_requirements/)

---

# What is that sound ... ... ... that is the sound of JD stomping.

> After years of listening to Dave Page, Magnus Hagander, Josh Berkus, David Fetter, Stefan Kaltenbrunner, Ads, Gabrielle, JPA and numerous other contributors th…

After years of listening to Dave Page, Magnus Hagander, Josh Berkus, David Fetter, Stefan Kaltenbrunner, Ads, Gabrielle, JPA and numerous other contributors that I should mention but won't. I have finally submitted to get a passport. Well at least the application is filed. So let's tell a story about acquiring a passport in the United States. Generally speaking it doesn't seem to bad. I needed my birth certificate and my drivers license. I had to fill out a longish form but they have it in PDF Form format so I got to do it on the computer and print it. Less pen and paper, good. They had to take a copy of my drivers license because they wanted to prove my signature was actually my signature (people who have seen my signature will understand). All of this was reasonable and I was quite pleased with how smoothly it went. Of course, we can't have all good news. So let's run down the bad. You need to know when your father was born. I don't know and I don't care. You need to know where your father was born. I don't know and I don't care. You also need to know the same for your mother, I do know but I still don't care. I was lucky, at least the state of birth for both of my parents was on my birth certificate. I had to guess the year my father was born. I had to give a reason why I am traveling out of the country and when. It is none of the United States Government's business when or why I plan to travel except that I am. They will know when I go through the airport and they stamp my passport. Otherwise, I claim right to privacy. I just put I was leaving in July. I can always hop a plane to Japan if I get bored. I am sure Tatsuo would love to have dinner. He is a great guy. Oh well I can live with this. It isn't like they are taking DNA... yet. The last straw was when it came to payment. I do not carry cash, ever. I do not carry checks, ever. It is 2009, not 1989. Let us please get a clue. Worse apparently the Department of State doesn't take cash, so even a trip to the ATM does me no good. So I can do a cashier's check or a money order. A money order? I didn't even know those were still used. I read about them once in history class. I take my cold, irritated, JD carcass down to Bank of America. Anyone who has done any real business with Bank of America knows that they are the Bank of Stupid. Command Prompt once had an account with them to supposedly help **facilitate** the paying of our Canadian employees. That was the biggest mistake we ever made. The act of **facilitating** in the Bank of America dictionary means, "the practice of being [constipated](<http://www.medterms.com/script/main/art.asp?articlekey=2829>)". I walked into Bank of America with cold, hard America cash to purchase a Cashiers Check. Bank of America will not give you a cashiers check (even if you have cash) if you are not an account holder. What? After a brief and obvious sign of astonishment the nice bank lady leaned over, whispered and said, "The post office has money orders, I would go there." Thank you nice bank lady. I walk to the Post Office. There was no line. No I am not kidding. I asked for a money order. They asked how much. I said 75.00. They said there will be a 1.65 (might have been 1.95) fee. I said o.k. They printed it, gave me my change and I walked out. Wait, what? That's right. The most efficient entity in this whole process was the Post Office. I started with being completely frustrated by the U.S. Government and in the end, was completely satisfied by the U.S. Government. Whatever. After a long walk up a hill, I re-entered the passport office. I handed them the money plus a 25.00 fee, in cash. Yes, that's right. I can pay one fee in cash but not another. I received my receipt and left, happy. So what does this all mean? It means that in theory, about six weeks from now I will be free to terrorize Europe. When is the next ITPUG meeting?

---
[View this page online](https://www.commandprompt.com/blog/what_is_that_sound____that_is_the_sound_of_jd_stomping/)

---

# Using Simpycity in Pylons

> Project Design

Simpycity&#x27;s core philosophy is that the DBA is going to perform the vast majority of the schema design without the aid of a conventional ORM.…

**Project Design** Simpycity's core philosophy is that the DBA is going to perform the vast majority of the schema design without the aid of a conventional ORM. This is a marked divergence from most other ORMs and database abstraction layers, and it has an impact on how your project should be designed. The best results with Simpycity will be seen with a strong up-front requirements analysis, thorough schema design, and a consistent, fixed database API. To use an example from one of our in-development applications, the majority of our business logic is is stored in stored procedures, with a small number of views. The tables and internal layout is hidden from the application code, with all access being performed through stored procedure interfaces such as: 
    
    
        CREATE OR REPLACE FUNCTION create_db_item (
            in_user_id
        ) RETURNS int
        AS $body$
            DECLARE
                v_user users;
                v_db_id;
            BEGIN
                SELECT * INTO v_user FROM users WHERE id = in_user_id;
                
                IF NOT FOUND THEN
                    RAISE EXCEPTION 'Could not find user.';
                END IF;
                
                v_db_id = nextval('db_item_seq');
                
                INSERT INTO db_item (id, owner) VALUES (v_db_id, v_user.id);
                
                RETURN v_db_id;
            END;
        $body$ language plpgsql;
    

**Configuration** Configuration of Simpycity for use with Pylons is fairly simple, due largely to Pylons' natural decoupling of components. To start, add a few keys to your .ini file. In the default case, this is $appdir/development.ini, in the [app:main] section: 
    
    
        
        [app:main]
        use = egg:helloworld
        full_stack = true
    
        cache_dir = %(here)s/data
        beaker.session.key = helloworld
        beaker.session.secret = somesecret
        beaker.session.type = memory
    
        # If you'd like to fine-tune the individual locations of the cache data dirs
        # for the Cache data, or the Session saves, un-comment the desired settings
        # here:
        #beaker.cache.data_dir = %(here)s/data/cache
        #beaker.session.data_dir = %(here)s/data/sessions
    
        # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
        # Debug mode will enable the interactive debugging tool, allowing ANYONE to
        # execute malicious code after an exception is raised.
        set debug = true
    
        db.database = helloworld
        db.user     = helloworld_user
        db.host     = localhost
        db.port     = 5432
        db.password = 12345
    

These are the basic keys for the DB backend, and should be changed according to your environment. Next, we'll need to configure Simpycity itself during the application startup. To do this, open $appdir/config/environment.py and add 
    
    
        from simpycity import config as db_config
    

to the top of the file. As Simpycity uses a global config module by default, this will give you allow setup before any Simpycity code gets executed. Next, still in environment.py, underneath of 
    
    
        # CONFIGURATION OPTIONS HERE (note: all config options will override
        # any Pylons config options)
    

add 
    
    
        app_conf = config['app_conf']
    
        db_config.port = app_conf['db.port']
        db_config.database= app_conf['db.database']
        db_config.host= app_conf['db.host']
        db_config.user = app_conf['db.user']
        db_config.password = app_conf['db.password']
        db_config.debug = False
    

Thus configuring Simpycity. Due to the nature of Simpycity, these configuration options will be accessible by any Simpycity object created by your application. The .ini keys should also match the name of variables that Simpycity uses, for the sake of clarity. **Models** As Pylons has no tight integration with any ORM, the model "system" is easy to use with Simpycity. For a smaller app, the best practise is to create our models in the model/__init__.py, such as 
    
    
        from simpycity.core import Function
        from simpycity.model import SimpleModel
    
        from Update import UpdateModel
    
        class Hello(SimpleModel):
    
            f = Function("hello")
            
        class Item(SimpleModel):
            create_item = Function("create_db_item",[''])
    

where "hello" is a PostgreSQL stored procedure of 
    
    
        
        CREATE OR REPLACE FUNCTION hello () RETURNS setof hello_test AS $body$
            SELECT * FROM hello_test;
        $body$ language SQL;
    

Allowing you to do, in your controller: 
    
    
        from helloworld.model import Hello
        ... # rest of controller imports
        
        class HelloController(BaseController):
    
            def index(self):
                # Return a rendered template
                #   return render('/template.mako')
                # or, Return a response
    
                h = Hello()
                result = h.f()
                
    

For a more complex app, and more complex models, it might make sense to split model definitions into separate files, as in 
    
    
        
        model/hello.py:
            from simpycity.core import Function, Raw
            from simpycity.model import Construct, SimpleModel
    
            class Hello(SimpleModel):
    
                f = Function("hello")
                
    
        model/create_item.py:
            from simpycity.core import Function, Raw
            from simpycity.model import Construct, SimpleModel
            
            class Item(SimpleModel):
                create_item = Function("create_db_item",['user_id'])
    

And then, in model/__init__.py, 
    
    
        from hello import Hello
        from create_item import Item
    

This will allow the same controller code to perform as expected. **Connection Isolation/Scope** By default, Simpycity queries all run in an implicit transaction with the normal isolation level as set by psycopg2. As a result, anything you do in the database won't show up to two different connections, and anything you do MUST be explicitly committed. While this behaviour can be overridden, the safest way to perform all DB operations is 
    
    
        
        from helloworld import Hello, Item
        ... # remainder of controller imports
        
        class HelloController(BaseController):
    
            def index(self):
                # Return a rendered template
                #   return render('/template.mako')
                # or, Return a response
    
                h = Hello()
                i = Item()
                try:
                    rs = i.create_item(request.session['user_id'])
    
                    for row in rs:
                        # ... Check DB response.
                        all_is_okay = True
                    if all_is_okay:
                        i.commit()
                        result = h.f()
                        return result.next()
                    else:
                        i.rollback()
                        return redirect_to("error_page")
                    
    
                except:
                    i.rollback()
                    response.status = '500 Internal Server Error'
                    return redirect_to("error_page")
                
    

This will provide you with a known-consistent database state, regardless of a problem with your input data. **Connection Pooling** By default, Simpycity does not offer any connection pooling system. If your application requires connection pooling, the excellent pgbouncer package will work as a drop-in connection pooler for Simpycity.

---
[View this page online](https://www.commandprompt.com/blog/using_simpycity_in_pylons/)

---

# Configuring Pylons on Ubuntu Hardy

> I recently configured a complete Pylons + PostgreSQL environment for a customer. The operating system was (of course) Ubuntu Hardy. The system included the use…

I recently configured a complete [Pylons](<http://www.pylonshq.com/>) \+ [PostgreSQL](<http://www.postgresql.org/>) environment for a customer. The operating system was (of course) [Ubuntu Hardy](<http://www.ubuntu.com/>). The system included the use of [Simpycity](<https://public.commandprompt.com/projects/simpycity>) and [WSGI](<http://www.wsgi.org/wsgi/>). Although I could never done it without the Pylons documentation, I found that it was unnecessary complicated for those who **just want to get it done**. These are the steps I took: 

**Install some dependencies:** The use of apt-get here is wonderful because I didn't even have apache2 installed yet.
    
    
    jd@hardy:~$ sudo apt-get install python-dev python-setuptools \
    python-psycopg2 libapache2-mod-wsgi
    jd@hardy:~$ sudo easy_install pylons 
    jd@hardy:~$ sudo easy_install genshi
    

**Set up a generic location for python egg cache:**
    
    
    jd@hardy:~$ sudo mkdir /home/pylons
    jd@hardy:~$ sudo chgrp www-data /home/pylons
    jd@hardy:~$ sudo chmod 770 /home/pylons
    

**Enable mod-wsgi**
    
    
    jd@hardy:~$ cd /etc/apache2/mods-enabled
    jd@hardy:/etc/apache2/mods-enabled$ sudo ln -sf ../mods-available/mod-wsgi.* .
    

**Initialize your HelloWorld app**
    
    
    jd@hardy:~$ mkdir www
    jd@hardy:~$ cd /var/www; ln -sf /home/jd/www jd
    jd@hardy:~$ cd jd
    jd@hardy:~$ paster create -t pylons helloworld
    Selected and implied templates:
      Pylons#pylons  Pylons application template
    
    Variables:
      egg:      helloworld
      package:  helloworld
      project:  helloworld
    Enter template_engine (mako/genshi/jinja/etc: Template language) ['mako']: genshi
    Enter sqlalchemy (True/False: Include SQLAlchemy 0.4 configuration) [False]: 
    Enter google_app_engine (True/False: Setup default appropriate for Google App Engine) [False]: 
    Creating template pylons
    Creating directory ./helloworld
      Recursing into +package+
    [...]
    

_Notice the choice of[genshi](<http://genshi.edgewall.com/>) as the template language._

**Configure your wsgi handler**
    
    
    jd@hardy:~$ mkdir ~/etc
    jd@hardy:~$ cd etc; joe helloworld.wsgi
    

**The helloworld.wsgi looks like this**
    
    
    import os, sys
    sys.path.append('/home/jd/www/helloworld')
    os.environ['PYTHON_EGG_CACHE'] = '/home/pylons'
    
    from paste.deploy import loadapp
    
    application = loadapp('config:/home/jd/www/helloworld/development.ini')
    

**Edit your 000-default file**
    
    
    jd@hardy:~$ sudo joe /etc/apache2/sites-enabled/000-default
    

**Add your WSGIScriptAlias**
    
    
    WSGIScriptAlias /jd/helloworld /home/jd/etc/helloworld.wsgi
    

**Restart Apache**
    
    
    jd@hardy:~$ sudo /etc/init.d/apache2 restart
    

You should be good to go!

---
[View this page online](https://www.commandprompt.com/blog/configuring_pylons_on_ubuntu_hardy/)

---

# 2nd call for papers: PostgreSQL Conference East!

> PostgreSQL Conference East is being held at historic Drexel University on April 3rd through 5th 2009 . This is the second call for papers. The call for papers …

PostgreSQL Conference East is being held at historic Drexel University on April 3rd through 5th 2009 . This is the second call for papers. The call for papers ends Feb 23rd and speakers will be notified on the 27th. You may [submit your talk here.](<http://www.postgresqlconference.org/>) We are looking for a wide range of topics. Can you speak on any of the below topics? What about a different topic? As long as it is centered around PostgreSQL we want to hear about it. **Hacker topics:**
    
    
     MVCC
     C Function development
     Writing Procedural Languages
     Creating types
     The planner
     Optimization tips
     Explaining the process model
    

**DBA topics:**
    
    
     Backing up PostgreSQL
     Understanding and Configuring Autovacuum
     Normalization
     Trigger Happy (how to use triggers)
     PITR -- happiness is a shipped transaction log
     User / Groups / Roles
     Security
    

**End User development:**
    
    
     Web Frameworks with PostgreSQL
       Pylons
       Grails
       Rails
       Cake
       Turbo Gears
       Django
    

**Solutions:**
    
    
      Do you have a successful case study to present? 
      How did you solve a problem with PostgreSQL?
      Do you have an Open Source product that runs on PostgreSQL?
    

As always we let the presenters drive the feel of the conference. If you have an itch, let's figure out how to scratch it (as long as it is with PostgreSQL). [Submit your paper today.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/2nd_call_for_papers_postgresql_conference_east/)

---

# PostgreSQL and Replicator at Northwest Python Day

> Last Saturday I gave a talk at the Northwest Python Day in Seattle. Unfortunately it was a short talk of only 30 minutes so I didn&#x27;t get to cover all the topic…

Last Saturday I gave a talk at the Northwest Python Day in Seattle. Unfortunately it was a short talk of only 30 minutes so I didn't get to cover all the topics I wanted but I was able to briefly share on PostgreSQL and on configuring PostgreSQL (Mammoth) Replicator. Just for grins I started the talk off with a question, "Please raise your hand if you are running Ubuntu." There were over 50 people in the room. Over half raised their hand. World domination is coming along nicely. I was asked two questions at the end of the talk. One was about how to have many masters replicate to a single slave. Similar to the salesman problem where they have a database of information that has to sync up to the main hub once a day or something like that. This particular application was doing security polling and the gentlemen wanted to have all the nodes report centrally. Replicator isn't really designed for that. I suggested looking at Slony which is a little more flexible with obscure configurations. The second question was about the mcp server and if the master/slaves would recover should the mcp be unavailable for a period of time. Yes, they will. The trip itself was pretty uneventful but it was nice to get out of town for a couple of days.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_and_replicator_at_northwest_python_day/)

---

# Reflecting on the great community discussion

> As I diligently prepare for PostgreSQL Conference East 09 by trying to ensure that we have enough talks (hint: talk submission closes Feb 27th). We have a sugg…

As I diligently prepare for [PostgreSQL Conference East 09](<http://www.postgresqlconference/>) by trying to ensure that we have enough talks **(hint: talk submission closes Feb 27th)**. We have a suggested hotel and that everyone knows it is going on (including the Groovy, Python, MySQL, PHP and Ruby communities), I take heart in knowing that our community [PostgreSQL](<http://www.postgresql.org/>) can have a well thought out, pointed and [productive discussion](<http://archives.postgresql.org/pgsql-hackers/2009-01/msg01799.php>) like no other. I was thinking what other great and historical discussions have we had? 

>   * Vi vs. Emacs? (answer: joe) 
>   * cvs vs. git vs. svn (answer: svn) 
>   * python versus perl (answer: Python) 
>   * C vs C++ (answer: C, but only because I have had patches accepted) 
>   * fbsd vs linux (answer: my nick is linupoet, you guess) 
>   * Red versus Blue (answer: They both suck) 
> 


Any that I missed?

---
[View this page online](https://www.commandprompt.com/blog/reflecting_on_the_great_community_discussion/)

---

# East 09: Call for papers!

> PostgreSQL Conference, U.S., East 09 will be held in Philadelphia at historic Drexel University from April 3rd through 5th. The call for papers is now out.
As…

PostgreSQL Conference, U.S., East 09 will be held in Philadelphia at historic Drexel University from April 3rd through 5th. The [call for papers is now out.](<http://www.postgresqlconference.org/2009/east/>)

As always we let our submissions define our actual tracks. If you have something you want to talk about it. Submit it. As long as it is about PostgreSQL (or doing something with PostgreSQL) we will consider it. 

We are seeking creative ideas about things we can do at the conference. At West we had a code sprint. The sprint was very successful as it was about all things postgresql and open source. It wasn't just hacking back end code but people worked on all kinds of things.. Is someone up for running a code sprint? 

There has also been specific interest in having us add (in addition to our advanced topics) a newbie track. Please do not be afraid to submit a talks on items such as:

>   * Backing up PostgreSQL 
>   * Understanding and Configuring Autovacuum 
>   * Normalization 
>   * Trigger Happy (how to use triggers ;) 
>   * PITR -- happiness is a shipped transaction log 
> 


Other topics we are interested in beyond the standard PostgreSQL architectural fanfare are:

>   * Groovy/Grails 
>   * Django 
>   * PHP 
>   * Pylons 
>   * SQL Alchemy 
> 


So don't delay, PostgreSQL Conference, U.S. is the premeire PostgreSQL conference series for the United States PostgreSQL community! [Submit your talk today.](<http://www.postgresqlconference.org/2009/east/>)

---
[View this page online](https://www.commandprompt.com/blog/east_09_call_for_papers/)

---

# Simpycity: A Quick Tutorial

> Using Simpycity is as easy as its name suggests - quick, easy. Simple. In keeping with that philosophy, Simpycity offers 3 constructs for database access: Func…

Using Simpycity is as easy as its name suggests - quick, easy. Simple. In keeping with that philosophy, Simpycity offers 3 constructs for database access: Function, Query, and Raw. At a glance, each name describes the type of access it offers: Function providing access through stored procedures, Query constructing a simple SQL query from your arguments, and Raw, which allows you to write your own SQL query directly. We will first describe the Function construct, which, if you recall from the [introductory article](<../../../../blog/simple_postgresql_database_mapping/>), 
    
    
    >>> f = Function("get_rows")
    

is the most basic construct that can be created with Simpycity. When this is converted to SQL, it becomes 
    
    
    SELECT * FROM get_rows();
    

Now, any time that f() is called now, Simpycity will connect to your database, execute the query and return the results to you. Simple. But a bit limited. To make this function more versatile, we can do the following: 
    
    
    >>> f = Function("get_row",['id'])
    

The second argument to Function tells Simpycity that our function requires an argument, which we've named 'id'. This argument name isn't required to match the PostgreSQL function definition, it's purely for Simpycity. Now, we can call the function using normal positional arguments: 
    
    
    >>> result = f(1)
    

Or, using keyword arguments: 
    
    
    >>> result = f(id=1)
    

Simple and easy, and totally consistent with every other Python function you've ever used. Additionally, Simpycity supports returning only a subset of columns from your query: 
    
    
    >>> results = f(id=1, options=dict(columns=["id"]))
    

Which Simpycity will turn into: 
    
    
    SELECT id FROM get_row(1);
    

This works in more advanced cases as well, such as: 
    
    
    >>> results = f(id=1, options=dict(columns=["id as identifier","col1"]))
    

Which Simpycity will interpret as: 
    
    
    SELECT id as identifier, col1 FROM get_row(1);
    

Easy to use, and easy to remember. Next time, we'll take a look at the Query and Raw constructs, as well as the basis for collective Simpycity constructs. As always, Simpycity is a Commandprompt Open Source project, licensed under the terms of the Lesser GPL and you can get it from [https://public.commandprompt.com/projects/simpycity/](<https://public.commandprompt.com/projects/simpycity>)

---
[View this page online](https://www.commandprompt.com/blog/simpycity_a_quick_tutorial/)

---

# Simple PostgreSQL Database Mapping

> With everyone and their mothers trying to build the next awesome website and next amazing web service, you&#x27;ll probably find that SQL databases are getting more…

With everyone and their mothers trying to build the next awesome website and next amazing web service, you'll probably find that SQL databases are getting more and more popular. As it turns out though, writing complex software on databases is harder than it looks.   
  
Hard enough that database abstractions are growing in popularity, pushing "database agnosticism" and turning the database into a dumb, interchangable data store. As a database developer, trying to write app code in this environment is really frustrating. I know how to design a DB schema. I know how to abstract that schema with views and stored procedures. When I try to use an ORM? All it does is get in my way, especially when you lose most of the ORM functionality by going to raw SQL. Writing SQL straight against the PostgreSQL DB API isn't much better - I end up writing the same boilerplate connection code, return handling and other management that comes with working with low-level interfaces. Honestly, this is more trouble than it's worth.   
  
Simpycity changes that. Model definition? Unnecessary. One line to declare a function signature. One line to declare a simple query. One line to declare raw SQL. Returned rows are nothing but standard Python dicts. Got a model definition? All three support wrapping returned rows in any arbitrary model definition. Need to change your data model? Update your app by doing nothing more than adhering to the same API you developed the first time. A minor change in the database is a minor change in Simpycity.   
  
Instead of designing your entire API in terms of Python, you seamlessly connect your well-structured database to the Pythonic representation of your choice, cleanly and easily maintaining separation of logic and duty. It's simplicity. Here's how it works:  
  

    
    
    >>> from simpycity.core import Function
    >>> function_def = Function("get_rows")
    >>> results = function_def()
    >>> function_def.query
    SELECT * FROM get_rows()
    
    >>> function_def = Function("get_row",['id'])
    >>> function_def.query
    SELECT * FROM get_row(%s)
    
    >>> results = function_def(1) 
    
    - or -
    
    >>> results = function_def(id=1)
    

  
That's it.   
  
That's Simpycity.   
  
Simple, easy, seamless mapping of PostgreSQL stored procedures to Python. Simpycity is a Commandprompt Open Source project, licensed under the terms of the Lesser GPL and you can get it from [https://public.commandprompt.com/projects/simpycity/](<https://public.commandprompt.com/projects/simpycity>)

---
[View this page online](https://www.commandprompt.com/blog/simple_postgresql_database_mapping/)

---

# FK, CHECK, ENUM or DOMAIN. That is the question.

> We have a customer that recently asked me to comment on which I would use for a particular problem. This is a simple validating lookup. For example, CHECK(VALU…

We have a customer that recently asked me to comment on which I would use for a particular problem. This is a simple validating lookup. For example, CHECK(VALUE IN ('foo','bar')). Should we use a CHECK constraint, FK, ENUM or DOMAIN? 

A CHECK constraint is easy to apply and has simple syntax. It is also extremely flexible in solving other types of validating problems. If your valid values change you must DROP CONSTRAINT and ADD CONSTRAINT. You can not add an element to the CHECK. 

A Foreign Key creates the requirement of a lookup table. It also offers the easiest management of valid values. You just INSERT, UPDATE or DELETE from the lookup table. If you are a smart monkey and using natural keys versus artificial ones, you can avoid the JOIN on SELECT as well. 

ENUM registers as a type in PostgreSQL. This means if you use an ENUM extensively you are basically locking yourself into the use of the type. In short if you need to modify an ENUM you drop the ENUM and recreate it. You can't drop an ENUM if a relation is using it. There are some interesting functions available with ENUM but I am having a hard time seeing a use case for the type as a whole. An ENUM type in theory lends itself specifically to this type of problem so I have included it. 

A DOMAIN for this problem suffers from the same problems as ENUM as it registers as a type. However a DOMAIN is more flexible as you can apply complex logic to the validation (just as you can with a CHECK). For example a DOMAIN could contain the regex to validate if a email address is correctly formed. I have used domains many times in the past to create complex validating types. They are useful. 

So what does all this boil down to? I have listed the pros and cons of managing each method above but what I haven't mentioned is performance. What is the particular performance bottleneck for each method? Read on, to find out for yourself. First I created a table for the CHECK constraint test: 
    
    
    CREATE TABLE check_test (
       foo text CHECK(foo IN ('text','html')), 
       bar int);
    

Then the tables for the FK test: 
    
    
    CREATE TABLE fk (foo text PRIMARY KEY);
    CREATE TABLE fk_test (
       foo text REFERENCES fk(foo),
       bar int);
    

I then created a series of 10000 queries. Each query executed 5000 times individually. 
    
    
    INSERT INTO check_test VALUES('text',5);
    INSERT INTO check_test VALUES('html',5);
    

**CHECK Test: 1**
    
    
    real	0m10.144s
    user	0m0.200s
    sys	0m0.292s
    

**CHECK Test: 2**
    
    
    real	0m11.667s
    user	0m0.356s
    sys	0m0.256s
    

O.k. so what about Foreign Keys? **FK Test 1:**
    
    
    real	0m11.106s
    user	0m0.356s
    sys	0m0.252s
    

**FK Test 2:**
    
    
    real	0m11.566s
    user	0m0.256s
    sys	0m0.272s
    

O.k. about the same. What about if all 10000 are in a single transaction? **CHECK Test: 3 single transaction**
    
    
    real	0m1.143s
    user	0m0.184s
    sys	0m0.180s
    

**FK Test: 3 single transaction**
    
    
    real	0m1.476s
    user	0m0.184s
    sys	0m0.228s
    

O.k. this is closer than I thought it would be. I expected an FK to be much slower and in my individual tests it actually is. Just out of curiousity, what about ENUM? 
    
    
    CREATE TYPE content_type AS ENUM('text','html');
    CREATE TABLE enum_test (foo content_type, bar int);
    

**ENUM Test: 1**
    
    
    real	0m9.124s
    user	0m0.288s
    sys	0m0.196s
    

**ENUM Test: 2 single transaction**
    
    
    real	0m1.025s
    user	0m0.152s
    sys	0m0.192s
    

O.k. one last test... what about a DOMAIN? 
    
    
    CREATE DOMAIN d_content_type AS text CHECK(VALUE IN ('text','html'));
    CREATE TABLE domain_test (foo d_content_type, bar int);
    

**DOMAIN Test: 1**
    
    
    real	0m10.860s
    user	0m0.340s
    sys	0m0.260s
    

**Domain Test: 2 single transaction**
    
    
    real	0m1.316s
    user	0m0.172s
    sys	0m0.188s

---
[View this page online](https://www.commandprompt.com/blog/fk_check_enum_or_domain_that_is_the_question/)

---

# Replicator meeting log for 01-08-09 is up

> The PostgreSQL + Replicator meeting logs for 01-08-09 are up. This was a long meeting held on #replicator using the Freenode IRC service. Topics covered were t…

The PostgreSQL + Replicator meeting logs for 01-08-09 are up. This was a long meeting held on #replicator using the Freenode IRC service. Topics covered were the removal of the Single Point of Failure of the MCP which is partially done. The new in the PostgreSQL backend forwarder works but now the question is how to safely handle failover. [Take a look, maybe you have an idea.](<https://public.commandprompt.com/projects/replicator/wiki/01_08_09>)

---
[View this page online](https://www.commandprompt.com/blog/replicator_meeting_log_for_01-08-09_is_up/)

---

# PostgreSQL Conference / PgCon.US update

> In an attempt to ensure the continued positive growth of the community, PostgreSQL Conference, U.S. is going to change its current policy toward the domain PgC…

In an attempt to ensure the continued positive growth of the community, PostgreSQL Conference, U.S. is going to change its current policy toward the domain PgCon.US. The current policy is that the domain would only be used in lieu of [http://www.postgresqlconference.org/](<http://www.postgresqlconference.org>) when space was significantly to display the long URL was significantly limited. The new policy will be that PgCon.US will not be used. I would encourage any and all other communities making use of the PgCon name to change their branding as well. In an effort to help any communities who have invested resources in using the PgCon name, PostgreSQL Conference will offer sub domain pointing (and hosting if required) to their conference sites. As an example, the Brazilian community is using the brand PgCon Brazil with the URL: [http://pgcon.postgresql.org.br](<http://pgcon.postgresql.org.br/>) . At the Brazilian's request PostgreSQL Conference would configure: **http://brazil.postgresqlconference.org/** If you are a community looking for such help, please don't hesitate to ask. It is my hope that this will put an end to the [PgCon](<http://www.pgcon.org/>) debate.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference__pgconus_update/)

---

# PITRTools: Multiple slave support

> I gave a lightning talk at Pg Conference: West 08 about a tool that I have developed call PITRTools. PITRTools is a python based log shipping utility. Essentia…

I gave a lightning talk at [Pg Conference: West 08](<http://www.postgresqlconference.org/>) about a tool that I have developed call PITRTools. PITRTools is a python based log shipping utility. Essentially it wraps itself around standard tools such as rsync, and pg_standby to provide a usable experience. Some of the features is provides are: 

>   * Auto initialization of environment 
>   * Simple base backups 
>   * Monitoring of Master 
>   * Arbitrary alerts 
>   * Failover 
>   * Failover actions 
>   * etc... 
> 


In all it is by far the simplest and most effective tool for PostgreSQL standby that I have used (of course I wrote it so...). One of the features recently added to PITRTools is multi-slave support. The way it works is like this: 
    
    
       Archiver checks for logs in local queue
          if found
             archiver attempts to sends (queued) logs to slave N
             if success
                archiver sends new archive to slave N
                if success
                   continue
                if fail
                   archive local
                   if success 
                      continue
                   if fail
                      bail out really loudly (FATAL)
                   exit 1
             if fail
                archive local
                if success 
                      continue
                   if fail
                      bail out really loudly (FATAL)
                   exit 1
          if not found
             Archiver sends log to Slave N
             if success
                continue
             if fail
                archive local (queue)
                if success
                   continue
                if fail
                   bail out really loudly (FATAL)
             continue
       if fail
          queue
          exit 1
       exit 0
    

One of the key requirements of PITRTools was no extra support. It requires no extra Python modules just Python >= 2.5 AND Python <= 2.6. No it is not 3.0 safe, but will be soon enough. Give it a whirl and let us know what you think, its BSD licensed. To get PITRTools you can check it out like so: 
    
    
    svn co https://projects.commandprompt.com/public/pitrtools/repo pitrtools
    

It's BSD licensed. Have at it.

---
[View this page online](https://www.commandprompt.com/blog/pitrtools_multiple_slave_support/)

---

# PostgreSQL Replicator Update 01.06.09

> I know it appears that it has been pretty quiet since we open sourced Replicator but that isn&#x27;t the case. We have been actively working on 1.9 and fixing 1.8 B…

I know it appears that it has been pretty quiet since we open sourced Replicator but that isn't the case. We have been actively working on 1.9 and fixing 1.8 Beta as bug reports have come in, including a bug to sequence replication. However, 1.9 is the true milestone release where we have finally moved away from the original architecture. For those that don't know, the original architecture looked like this: 
    
    
    master-->mcp
              |
              |
      -----------------
      |       |       |
      s0      s1      s2
    

The mcp would handle all communication and data transfer between the master and the slaves. The idea behind the architecture was to achieve maximum efficiency for the master, meaning that the number of the slaves never affected the performance of the master. However this architecture came with a cost. A single point of failure. If the mcp were to ever crash, replication would stop. When we started down the path of 1.9 it was made very clear to me by Alvaro and Alexey that this was not acceptable. In return I made it very clear that any architectural change we made must not suffer from the Slony problem (performance degradation based on number of subscribers). Together we were all very clear to each other and Alvaro came up with a new architecture. The new architecture calls for a "Forwarder" process and from a topological view doesn't look much different than the MCP. It does however offer us a great deal more flexibility and stability. Here is the new architecture: 
    
    
    master-->forwarder0
              |
              |
      -----------------
      |       |       |
      s0      s1      s2
    

How is this different? It is different in a couple of ways. First, the forwarder is now integrated into the PostgreSQL backend. This removes the mcp binary entirely. It also greatly decreases the redundancy of the code. Secondly if the primary forwarder goes down a slave can become the forwarder. This removes the single point of failure. You can read more information on the [forwarder here.](<https://lists.commandprompt.com/pipermail/replicator-general/2008-November/000024.html>) Other items up for idle thoughts on the possibilities of this new architecture is a single monitoring point. With versions of replicator <= 1.8, you can have a clear idea of which replication transactions have been received and transfered to each slave but you must access each slave individually to see what transaction has actually been restored. So what else is coming with Replicator 1.9? In continuing our cleanup of the architecture we are completely rewriting the ROLE and GRANT/REVOKE replication. This is actually the first step of the other half of the **Major Feature** of Replicator 1.9, DDL replication. We are currently investigating the opportunity to have certain DDL operations automatically replicate. The most obvious of these would be: 

>   * CREATE TABLE
>   * ALTER TABLE
>   * CREATE DOMAIN
>   * etc...
> 


We decided to pass on replicating CREATE FUNCTION due to complexity in dealing with externally linked libraries as well as various dependency problems. We may look at this again in the future. For more information on this feature please [visit the thread.](<https://lists.commandprompt.com/pipermail/replicator-general/2008-December/000135.html>) If you are interested in testing you can grab the 1.8 Beta or 1.9 from [SVN](<https://public.commandprompt.com/projects/replicator>). You can also get the 1.8 Beta from [The pgsqlrpms project.](<https://public.commandprompt.com/projects/pgcore>) The next developer meeting is on 01.08.09 at 11:00AM PST. We are holding in in the #replicator channel on Freenode. All are welcome.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_replicator_update_010609/)

---

# PostgreSQL Conference: West 2007, More video up

> I have gotten a couple more of the West 2007 Videos.
PostgreSQL Partitioning - Robert Treat 
Babel of PLs - David Fetter



I have gotten a couple more of the West 2007 Videos. 

>   * [PostgreSQL Partitioning](<http://www.postgresqlconference.org/2007/west/talks/#partitioning>) \- Robert Treat 
>   * [Babel of PLs](<http://www.postgresqlconference.org/2007/west/talks/#babel>) \- David Fetter
>

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_west_2007_more_video_up/)

---

# PgDay LFNW: Call for Papers! (04/25/09)

> PostgreSQL Conference, U.S. is having a PgDay at LinuxFest Northwest in Bellingham Washington on April 25th, 2009. The PgDay (and LinuxFest Northwest) is a fre…

[PostgreSQL Conference, U.S.](<http://www.postgresqlconference.org/>) is having a PgDay at [LinuxFest Northwest](<http://www.linuxfestnorthwest.org/>) in Bellingham Washington on April 25th, 2009. The PgDay (and LinuxFest Northwest) is a free event. We are holding the PgDAY on the first day of the event (a Saturday) parallel with LFNW. There was over 700 attendees to LFNW last year. LFNW is hoping for even more this year! In short, we are looking for some PostgreSQL talks (45 minutes each) to fill out the day. Please [click here to submit your talk.](<http://www.postgresqlconference.org/2009/pgday/lfnw/>)

---
[View this page online](https://www.commandprompt.com/blog/pgday_lfnw_call_for_papers_042509/)

---

# PostgreSQL Conference: West 07, two videos added

> As I was working on PostgreSQL Conference this weekend I happen to crawl under my desk to pick up a pin I dropped. As I was crawling back out I smacked my head…

As I was working on PostgreSQL Conference this weekend I happen to crawl under my desk to pick up a pin I dropped. As I was crawling back out I smacked my head on the top of the desk and in the process jostled an empty (black) computer case that was sitting there. I noticed something on top of the case so I took a long hard look and behold! It was the Western Digital USB drive the West 07 videos were on. Now most of you wouldn't think that was a big deal except that I completely forgot we did video for West 07 and two, I thought that hard drive was long lost to the computer parts gods. I plugged it in and viola! We have videos. Of course the first thing I did was rsync them all off so we have a backup. I then formatted it because it was using HFS and that is just unacceptable. Anyway, the first two videos I pulled from the vault were:

  * Stupid Solaris tricks : Josh Berkus
  * Ruby on Rails Essentials for PostgreSQL Enthusiasts | David Wheeler

They can both be found at [PostgreSQLConference.org](<http://www.postgresqlconference.org/2007/west/talks>).

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_west_07_two_videos_added/)

---

# PostgreSQL Conference: East 09, when to hold survey (closed)

> I have closed the survey, &quot;When to hold it&quot; and provided the results. Of particular interest to me was the majority wanted Late March/Early April but a signifi…

I have closed the survey, "When to hold it" and [provided the results.](<http://www.postgresqlconference.org/2009/east/>) Of particular interest to me was the majority wanted Late March/Early April but a significant amount were also interested in having the conference in Early June. I am also glad to see that people were not interested in conflicting with Ottawa as I hear it is a very good conference.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_09_when_to_hold_survey_closed/)

---

# PostgreSQL Conference: Perl5 is Alive

> Although I don&#x27;t follow the Perl world very much, my respected peer Matt S. Trout emailed me wondering when I would be able to get the Perl 5 is Alive! video u…

Although I don't follow the Perl world very much, my respected peer Matt S. Trout emailed me wondering when I would be able to get the [Perl 5 is Alive!](<http://www.postgresqlconference.org/2008/west/talks/#perl5_is_alive>) video up. Apparently there are some buffoons spreading FUD about the state of this very much alive, very much supported, very much developed, very much kicking language. So take a look at the link above and see for yourself. If you are a Perl fan you need not worry!

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_perl5_is_alive/)

---

# PostgreSQL Conference: East 2009, When should we hold it?

> I have been negotiating (with the help of Bruce and others) with various parties to determine where we are going to hold East 2009. One of the questions that k…

I have been negotiating (with the help of Bruce and others) with various parties to determine where we are going to hold East 2009. One of the questions that keeps popping up is, "When are we going to hold PostgreSQL Conference East: 2009". Since we now have this nifty new [Drupal](<http://www.drupal.org/>) (with PostgreSQL) driven web site, we should take advantage of the ease of use and ask for some feedback. If the community wouldn't mind weighing in that would be helpful. [Just visit the site and follow the links.](<http://www.postgresqlconference.org/2009/east/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_2009_when_should_we_hold_it/)

---

# Explain: Why do I have to recheck my condition?

> As with any PostgreSQL question, the first place you should look for answer is the PostgreSQL docs. I was recently reviewing the EXPLAIN docs as freshen up on …

As with any PostgreSQL question, the first place you should look for answer is the [PostgreSQL docs.](<http://www.postgresql.org/docs/>) I was recently reviewing the EXPLAIN docs as freshen up on some query tuning fu and I came across this little gem: 
    
    
    EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100;
    
                                      QUERY PLAN
    ------------------------------------------------------------------------------
     Bitmap Heap Scan on tenk1  (cost=2.37..232.35 rows=106 width=244)
       Recheck Cond: (unique1 < 100)
       ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..2.37 rows=106 width=0)
             Index Cond: (unique1 < 100)
    

What the above says (per the docs) is : 

> Here the planner has decided to use a two-step plan: the bottom plan node visits an index to find the locations of rows matching the index condition, and then the upper plan node actually fetches those rows from the table itself. Fetching the rows separately is much more expensive than sequentially reading them, but because not all the pages of the table have to be visited, this is still cheaper than a sequential scan. (The reason for using two levels of plan is that the upper plan node sorts the row locations identified by the index into physical order before reading them, so as to minimize the costs of the separate fetches. The "bitmap" mentioned in the node names is the mechanism that does the sorting.)

In short we go to the index and find out what tuples match the Index condition (unique1 < 100). What I didn't understand and what the docs didn't tell me was since the index already tells me which tuples meet the condition I had to recheck the condition in the upper node (Recheck Cond: (unique1 < 100). After a little investigation and help from [Neil Conway](<http://neilconway.org/>) I found the reason. A Bitmap scan is lossy and as the number of tuples returned from the scan increases PostgreSQL will switch from a "Match all tuples" to "Match all pages" mode. Since a page can contain multiple tuples, we have to recheck the condition in the upper node (Bitmap Heap scan).

---
[View this page online](https://www.commandprompt.com/blog/explain_why_do_i_have_to_recheck_my_condition/)

---

# Pg Conference: Videos up! (well some of them anyway)

> Last March at PostgreSQL Conference: East we video taped almost all the talks. It has taken some time to get them up and we are still encoding (and learning th…

Last March at PostgreSQL Conference: East we video taped almost all the talks. It has taken some time to get them up and we are still encoding (and learning the tricks of the trade) but we do have a few up now that people may enjoy. 

  * Deploying PostgreSQL on Windows
  * The magic of MVCC
  * PostgreSQL Interprocess Coordination and Communication
  * PostgreSQL Logic and Databases

You can find them at the newly designed [PostgreSQL Conference](<http://www.postgresqlconference.org/>) website. Just click on the East 2008 link under previous events. You will have to scroll down (or just ctrl-f Video) because I haven't had time to figure out how to handle collapsible DIV with drupal yet. In all, with the new web site I think that life is going to become much easier in managing the conference series. These videos will also help continue one of the mission points of the conference, **Education**.

---
[View this page online](https://www.commandprompt.com/blog/pg_conference_videos_up_well_some_of_them_anyway/)

---

# PostgreSQL Conference: A new platform

> In my on going efforts to secure a location for the upcoming East (MIT, Penn State, Drexel and even the Marriot are on the list), I am bound and determined to …

In my on going efforts to secure a location for the upcoming East (MIT, Penn State, Drexel and even the Marriot are on the list), I am bound and determined to revamp the entire [Pgcon.US website](<http://www.pgcon.us/>). I have several problems/goals I wish to solve. 

  1. A more community orientated site. Currently the site is 100% manage by me. Although it does use PHP it is essentially flat files. 
  2. A social site. I want people to use the site. We have a lot of excellent educational content and I want to make sure and utilize that. 
  3. Promotion. I want to promote our speakers. Most use their own money to help our community. They should be acknowledged. First step, blog aggregation. No I don't want to compete with [Planet](<http://planet.postgresql.org/>) or [Planet](<http://www.planetpostgresql.org/>) but the more linked a blog is the better. 
  4. A better sponsors interface. I want sponsors to feel as if they are partners. Possibly even allowing them to create custom content. 
  5. A push to <http://www.pgcon.us/> . My thought is that <http://www.postgresqlconference.org/> will become a portal for all postgresql conference about to happen. For example the [Canadian International conference.](<http://www.pgcon.org/>)

So [take a look](<http://drupal.postgresqlconference.org/>) let me know what you think. Don't complain about a lack of an email. If you can't find my email, you probably shouldn't be emailing me.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_a_new_platform/)

---

# PostgreSQL Certification: JTA results released

> The PostgreSQL Certification project has released the results of the Job Task Analysis. Thanks to everyone who participated in this important step toward deliv…

The PostgreSQL Certification project has released the results of the Job Task Analysis. Thanks to everyone who participated in this important step toward delivering a quality certification. 223 members took the time and effort to fill out the survey. A couple of interesting results. There were 213 members felt we needed a certification. That is a sharp contrast to exposed opinions of some in the community. Of all the results Linux topped the requested operating systems (no surprise) but Windows was number two (I was surprised). Other operating systems that made a decent showing were the various BSDs. If you haven't done so yet I invite you to [join the community.](<http://lists.postgresqlcertification.org/mailman/listinfo/cert>) The results [can be found here.](<http://www.postgresqlcertification.org/jta/2008/results>).

---
[View this page online](https://www.commandprompt.com/blog/postgresql_certification_jta_results_released/)

---

# PostgreSQL Certification: JTA now closed

> Thanks to everyone that took the time to participate in the PostgreSQL Certification JTA. We received over 223 respondents which is great. We will be posting t…

Thanks to everyone that took the time to participate in the PostgreSQL Certification JTA. We received over 223 respondents which is great. We will be posting the results of the JTA shortly and if you would like to participate in the resulting project discussion [please join us.](<http://lists.postgresqlcertification.org/mailman/listinfo/cert>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_certification_jta_now_closed/)

---

# PostgreSQL Certification (JTA closes November 14th)

> The PostgreSQL certification project is in the closing days of the JTA (Job Task Analysis). In short, what should the PostgreSQL certification project, certify…

The PostgreSQL certification project is in the closing days of the JTA (Job Task Analysis). In short, what should the PostgreSQL certification project, certify? In hacker terms, "What is the problem we are trying to solve?". It is relatively long but the information is of extreme value to ensure that the project develops a relevant certification to the professional PostgreSQL community. If you haven't done so already [please create an account](<http://www.postgresqlcertification.org/user/register>) and the [proceed to the JTA.](<http://www.postgresqlcertification.org/jta/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_certification_jta_closes_november_14th/)

---

# You are not good enough (for Open Source)

> A segment of the talk I gave at NAU on why you should contribute to Open Source and why you think you can&#x27;t. Original idea credited to Matt S. Trout.
  Update…

A segment of the talk I gave at NAU on why you should contribute to Open Source and why you think you can't. Original idea credited to Matt S. Trout.

  
Updated 11/05/08 from Matt Trout: [ the version he gave at YAPC-EU 2008](<http://www.shadowcat.co.uk/archive/conference-video/yapc-eu-2008/you-arent-good-enough/>)

---
[View this page online](https://www.commandprompt.com/blog/you_are_not_good_enough_for_open_source/)

---

# The Open Source job market

> The following is a segment of the talk I gave at Northern Arizona State University about the Open Source job market.


The following is a segment of the talk I gave at Northern Arizona State University about the Open Source job market.

---
[View this page online](https://www.commandprompt.com/blog/the_open_source_job_market/)

---

# PostgreSQL Replicator developer meeting 10/28

> With the recent open sourcing of Replicator, the team has been trying to come up with ways to ensure an open development process. In that light we have decided…

With the recent open sourcing of Replicator, the team has been trying to come up with ways to ensure an open development process. In that light we have decided to have our first release 1.9 meeting on Freenode. All people interested in participating in a discussion about the upcoming Replicator 1.9 are welcome to attend. The current topics are: 

  * New MCP architecture 
  * DDL Replication 
  * Release timeline 
  * Questions 

Replicator is set to be a short cycle release, hopefully landing before PostgreSQL 8.4. It will support PostgreSQL 8.3 and PostgreSQL 8.4 (when 8.4 is available). We will be meeting in the #replicator channel at 10:00 AM PDT..

---
[View this page online](https://www.commandprompt.com/blog/postgresql_replicator_developer_meeting_1028/)

---

# Replicator 1.8 Beta released as BSD 

> It took longer than we expected, but Replicator 1.8 for 8.1 and 8.3 of PostgreSQL has been released. It is 100% Open Source and of course, BSD. Replicator all …

It took longer than we expected, but Replicator 1.8 for 8.1 and 8.3 of PostgreSQL has been released. It is 100% Open Source and of course, BSD. [Replicator all your baby elephants here.](<https://public.commandprompt.com/projects/replicator>)

---
[View this page online](https://www.commandprompt.com/blog/replicator_18_beta_released_as_bsd_/)

---

# Thanks to all that helped with PostgreSQL Conference West

> PostgreSQL Conference West was a big hit this weekend. It exceeded expectations of attendance as well as content. I would like to take a moment to thank the pe…

PostgreSQL Conference West was a big hit this weekend. It exceeded expectations of attendance as well as content. I would like to take a moment to thank the people that took time out of their personal lives to help make this conference a success! 

  * Daniel Browning 
  * Selena Decklemann 
  * Lisa Drake 
  * Josh Berkus 
  * Richard Broersma Jr. 
  * Tim Bruce 
  * Rafael de Jess Fernndez Moctezuma 
  * Lacey Powers 
  * Gabrielle Roth 
  * David Wheeler 
  * Mark Wong 

Thank you all for the time you spent to help make this conference a success! Without you there is no way we could have pulled it off.

---
[View this page online](https://www.commandprompt.com/blog/thanks_to_all_that_helped_with_postgresql_conference_west/)

---

# On the morning of West, East 08 appears!

> In preparing for West I decided we weren&#x27;t going to go through the hassle we went through at East with recording. We ran out of tapes, had to borrow all the ca…

In preparing for West I decided we weren't going to go through the hassle we went through at East with recording. We ran out of tapes, had to borrow all the cameras, even used some digital cameras video mode. That combined with a lack of hardware to pull the video off of tapes caused content from East08 to be significantly delayed on getting to the web.

We purchased three cameras to handle all recording for West08. In the process I made sure that the cameras were compatible with Linux and [Kino](<http://www.kinodv.org/>) (So I can continue my unreasonable stance against MacOSX) and that it could process the tapes from East. So without further ado the [Keynote from East08.](<https://youtu.be/MKKNZV5ew_4>)

---
[View this page online](https://www.commandprompt.com/blog/on_the_morning_of_west_east_08_appears/)

---

# Pg Conference West: Last call for Lightning talks and tentative schedule released!

> Lightning talks are an exciting way to get involved in the conference with very little commitment on the speakers end. Assuming you can stand in front of an au…

Lightning talks are an exciting way to get involved in the conference with very little commitment on the speakers end. Assuming you can stand in front of an audience for 5 minutes; you can speak about anything PostgreSQL or Open Source related. 

  * [Submit your lightning talk.](<http://www.pgcon.us/west08/talk_submission/>)
  * [Register for the event.](<http://www.postgresqlconference.org/west08/register>)
  * [Tentative talk schedule.](<http://www.pgcon.us/west08/schedule>)

---
[View this page online](https://www.commandprompt.com/blog/pg_conference_west_last_call_for_lightning_talks_and_tentative_schedule_released/)

---

# Pg Conference West: Lightning talks!

> While recently seeking feedback on the conference schedule from Josh Berkus and David Fetter I was asked, &quot;Are there going to be lightning talks?&quot;. To which I …

While recently seeking feedback on the conference schedule from Josh Berkus and David Fetter I was asked, "Are there going to be lightning talks?". To which I replied, "What?". I know of lightning talks; in a similar manner of how I know of the existence of competitors to PostgreSQL. They are there in the background fog of consciousness while posing no perceivable threat but still trying to maintain their significance. The threat here of course is that West won't have lightning talks. So let's solve that threat now! [Enter the call for lightning talks.](<http://www.pgcon.us/west08/talk_submission/>) Lightning talks are 5 minute, micro talks on any topic of any regard as long as it is somehow related to PostgreSQL (Pythoners I am calling to you). If you have something you are willing to stand in front of people for no more than 5 minutes (or you will be gonged) and [talk about this is your chance.](<http://www.pgcon.us/west08/talk_submission/>)

---
[View this page online](https://www.commandprompt.com/blog/pg_conference_west_lightning_talks/)

---

# WEST Conference shaping up nicely

> Once again West this year is running on a truncated calendar. Registration is now open!. We had originally planned on announcing and organizing from June till …

Once again West this year is running on a truncated calendar. [Registration is now open!](<http://www.postgresqlconference.org/west08/register>). We had originally planned on announcing and organizing from June till end of conference. Unfortunately that didn't work out as planned and we are back on the 6-8 week time line. Nothing like Just in Time delivery! Not to worry though. West is shaping up nicely. We already have 20 talks and tutorials waiting to teach you everything from the wonders of Python + PostgreSQL + [SQLAlchemy](<http://www.sqlalchemy.org/>) to the finer points of [Catalyst](<http://www.catalystframework.org/>), DBIx::Class and PostgreSQL. These talks are being provided by core members of the respective projects! We also have talks on upcoming PostgreSQL 8.4 features as well as forums on PgUS and how PgUS and PgEU can work together! [See the full list (and growing) of talks and tutorials.](<http://www.pgcon.us/west08/talks/>) So don't hesitate, [register today!](<http://www.postgresqlconference.org/west08/register>)

---
[View this page online](https://www.commandprompt.com/blog/west_conference_shaping_up_nicely/)

---

# PostgreSQL Conference: West. October 10th-12th Call for papers

> The second annual PostgreSQL Conference: West is being held on October 10th through October 12th 2008 in the The Native American Student &amp; Community Center at …

The second annual PostgreSQL Conference: West is being held on October 10th through October 12th 2008 in the The Native American Student & Community Center at Portland State University. Command Prompt is sponsoring the 2nd annual West Coast PostgreSQL Conference. The conference is being held at Portland State University in Oregon. We look forward to seeing all the new and old PostgreSQL users alike. The conference is currently accepting papers and you can [submit your talks.](<http://www.postgresqlconference.org/west08/talk_submission/>) We have already seen submissions on Tsearch2 as well as pgTap. Do you have something you would like to share about PostgreSQL? Now is the time! This year West will be providing its proceeds to the [Postgresql.us](<http://www.postgresql.us/>).

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_west_october_10th-12th_call_for_papers/)

---

# PostgreSQL leads OSCON again

> For the what seems like yet another year (can&#x27;t we slow these guys down?), OSCON has proven to be the PostgreSQL stomping ground. Per our usual supply of great…

For the what seems like yet another year (can't we slow these guys down?), OSCON has proven to be the PostgreSQL stomping ground. Per our usual supply of great community members including, Selena, Gabrielle, Michael, Greg, Robert and the other Robert we had what seemed liked an endless supply of quality support and community reaction to all comers. This was also the first year in several that I haven't ran the OSCON PostgreSQL Booth. I must say that I am quite happy to let that responsibility go and found it wonderful to have passed the , "Booth Master" baton to Gabrielle! This year we had quite a few people discussing the MySQL and Sun merger. You can't really call it an acquisition when MySQL gets equal billing with the parent within the same booth. I find it interesting that this is still a hot topic, it seems the only thing that Sun has managed to do is drive more people to PostgreSQL. Thanks Sun! Quite a bit of interest was also generated around [PgUS](<http://www.postgresql.us/>) as well as several people who asked about [PostgreSQL Certification](<http://www.postgresqlcertification.org/>). Especially after a certain [companies announcement.](<http://people.planetpostgresql.org/xzilla/index.php?/archives/354-Certified-Schizophrenic.html>) Lastly I would like to note the leadership role the PostgreSQL Community decided to show by not distributing CDs full of software this year. Instead we chose to bite the bullet and purchase PostgreSQL branded USB thumb drives. These are high quality units at 1GB that fit very well within the PostgreSQL brand. Now instead of spreading more plastic coffee coasters around, we are providing a re-usable and generally useful tool. Just like our favorite software itself.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_leads_oscon_again/)

---

# PostgreSQL 04/24/08 thru 05/01/08

> As I digg and slashdot my way through the weary set of tubes that connects us all, I have stumbled across a number of interesting (good and bad) posts in the l…

As I digg and slashdot my way through the weary set of tubes that connects us all, I have stumbled across a number of interesting (good and bad) posts in the last week. The first of which comes from our friends doing [Ruby on Rails development](<http://railsforum.com/viewtopic.php?pid=61157#61157>). As a PostgreSQL user, the very first thing that should jump out at you is that the error the individual "just installed" version 7.4... A note to the general public, 7.4 is dying. Not as in BSD is dying but as in, expect no support for 7.4 from the community within 12 months. Please use something at least reasonably recent, such as [8.2.7](<http://www.postgresql.org/ftp/binary/v8.2.7>) or [8.3.1](<http://www.postgresql.org/ftp/binary/v8.3.1>). The next item of note in the post is that he has a [Eeepc](<http://usa.asus.com/products.aspx?l1=24>), which is very cool. Over at [UbuntuGeek](<http://www.ubuntugeek.com/howto-setup-database-server-with-postgresql-and-pgadmin3.html>) there is a great article on setting up PostgreSQL with Ubuntu. It addresses one of the most common asked questions for newbies. Which is, "Why can't I login to PostgreSQL?". Kudos to the author, it is nice to see a reasonably written articles that will help introduce PostgreSQL even further to Ubuntu folks. An interesting blog over at [Milking the Gnu](<http://blog.milkingthegnu.org/2008/04/mysql-the-perve.html>) about how MySQL/Sun is neglecting their community. The title is just classic. This post plays well into [my talk at MySQLCon](<http://www.commandprompt.com/blogs/joshua_drake/2008/04/what_mysql_and_really_sun_can_learn_from_postgresql/>). The best line of this blog is the title, "MySQL so busy becoming PostgreSQL it forgets its community". A quick post at [Fuzzy Tolerance](<http://maps.co.mecklenburg.nc.us/ft/?p=230>) on issues they had with upgrading to PostgreSQL 8.3 and specific reasons why they chose to upgrade.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_042408_thru_050108/)

---

# Is that performance I smell? Ext2 vs Ext3 on 50 spindles, testing for PostgreSQL

> There are few things I like better than when a customer says to the team, &quot;I want the best machine I can buy for XXX dollars&quot;. It inspires a certain sense of j…

There are few things I like better than when a customer says to the team, "I want the best machine I can buy for XXX dollars". It inspires a certain sense of joy not unlike the feeling an average Slashdot reader gets when they walk into the local gadget store. It is particularly special because you know as much as you **could** make use of such a machine, you **know** you would never justify the expense.  
In this case, the customer was willing to spend a modest but not excessive amount of money. I applaud this decision because I run into far to many people that feel that the only way to get real performance is to buy some ridiculous SAN at 10 times the cost to performance ratio.

 **Machine Specs:**

> HP DL585.  
> 4 Dual core 8222 processors  
> 64GB of ram. **Storage:  
> ** (2) MSA70 direct attached storage arrays.  
> 25 spindles in each array.  
> Single HP P800 controller.

 **Filesystem layout**

> /dev/cciss/c1d1p1 1693108576 201228 1606902380 1% /data2  
> /dev/cciss/c1d0p1 1693104732 201292 1606898664 1% /data1  
> /dev/cciss/c0d1p1 282181440 195616 267651768 1% /xlogs

 _Where /data[n] is an MSA70 and /xlogs is a RAID 10 on the embedded controller._  


 **Filesystem options**

> /dev/cciss/c1d0p1 /data1 ext3 data=writeback 1 2  
> /dev/cciss/c1d1p1 /data2 ext3 data=writeback 1 2  
> /dev/cciss/c0d1p1 /xlogs ext2 defaults 1 2

 **Xlog performance**

The PostgreSQL WAL is written in a sequential fashion negating the need for a large number of spindles to get reasonable performance. It is random writes that kills performance. Further, when the WAL is used for recovery purposes, it will recover up to the last known good transaction and throw all transactions after away. This ensures a consistent database regardless of crash. It also partly why we are able to forgo a journaling filesystem for the xlog files. Just for kicks, I ran tests for xlog on both ext3 and ext2. The benchmarking software being used is [IOzone](<http://www.iozone.org/>).

 **The command used was:**

> /opt/iozone/bin/iozone -e -i0 -i1 -i2 -i8 -t1 -s 1000m -r 8k -+u
    
    
    Here are the results: xlogs ext3 with defaults (ordered mode for journaling)
    Children see throughput for 1 rewriters = 87418.44 KB/sec
    Parent sees throughput for 1 rewriters = 87395.65 KB/sec
    Min throughput per process = 87418.44 KB/sec
    Max throughput per process = 87418.44 KB/sec
    Avg throughput per process = 87418.44 KB/sec

 **xlogs ext3 with data=writeback**
    
    
    Children see throughput for 1 rewriters = 84712.55 KB/sec
    Parent sees throughput for 1 rewriters = 83513.39 KB/sec
    Min throughput per process = 84712.55 KB/sec
    Max throughput per process = 84712.55 KB/sec
    Avg throughput per process = 84712.55 KB/sec

 **xlogs ext2 with defaults**
    
    
    Children see throughput for 1 rewriters = 115378.34 KB/sec
    Parent sees throughput for 1 rewriters = 115345.26 KB/sec
    Min throughput per process = 115378.34 KB/sec
    Max throughput per process = 115378.34 KB/sec
    Avg throughput per process = 115378.34 KB/sec

A pretty clear indicator that one should always consider /xlogs on a separate channel. The next series of tests I ran were with ext3 and the /data[n] partitions. Remember each of the partitions are on their own Direct Attached Storage. **/data1 with data=journal**
    
    
    Children see throughput for 1 random writers = 49444.73 KB/sec
    Parent sees throughput for 1 random writers = 48709.89 KB/sec
    Min throughput per process = 49444.73 KB/sec
    Max throughput per process = 49444.73 KB/sec
    Avg throughput per process = 49444.73 KB/sec

 **/data1 with data defaults (ordered mode)**
    
    
    Children see throughput for 1 random writers = 142926.14 KB/sec
    Parent sees throughput for 1 random writers = 142872.21 KB/sec
    Min throughput per process = 142926.14 KB/sec
    Max throughput per process = 142926.14 KB/sec
    Avg throughput per process = 142926.14 KB/sec

 **/data1 with data=writeback**
    
    
    Children see throughput for 1 random writers = 168948.55 KB/sec
    Parent sees throughput for 1 random writers = 168867.03 KB/sec
    Min throughput per process = 168948.55 KB/sec
    Max throughput per process = 168948.55 KB/sec
    Avg throughput per process = 168948.55 KB/sec

The ext3 journal mode of writeback is the obvious winner here. A note of caution however, it is likely not safe to use writeback unless you have a battery backed RAID controller. The overall bandwidth is respectable at ~ 170MB/s. How much of that is journaling? /data1 with ext2
    
    
    Children see throughput for 1 random writers = 178404.45 KB/sec
    Parent sees throughput for 1 random writers = 178320.32 KB/sec
    Min throughput per process = 178404.45 KB/sec
    Max throughput per process = 178404.45 KB/sec
    Avg throughput per process = 178404.45 KB/sec

Although ext2 is faster, I don't think it is fast enough to satisfy the downside of running a non journaled filesystem (long fsck times). What happens when we access both /data1 and /data2 at the same time. **/data1 and /data2 using separate processes**
    
    
     Children see throughput for 1 random writers = 93932.16 KB/sec
     Parent sees throughput for 1 random writers = 93909.48 KB/sec
     Min throughput per process = 93932.16 KB/sec
     Max throughput per process = 93932.16 KB/sec
     Avg throughput per process = 93932.16 KB/sec
    
     Children see throughput for 1 random writers = 105375.49 KB/sec
     Parent sees throughput for 1 random writers = 105292.74 KB/sec
     Min throughput per process = 105375.49 KB/sec
     Max throughput per process = 105375.49 KB/sec
     Avg throughput per process = 105375.49 KB/sec

I am not actually buying these numbers. The reason is as I monitored multiple thread results and how they interacted with each processor, whether I was running two processes separately or a single process over multiple threads, processor utilization was never correctly aggregated. I think this a failure of the benchmark software. In theory I should see almost identical results for a single arrray as the dual arrays. In an effort to get more accurate results across not only the arrays but the availability of processors I wrote a quick script. The script fires the benchmark software as four independent processes each with a single writer. I then executed that script on /data1 and /data2 simultaneously. This allowed us to have much better utilization of all processors and also gave us a more accurate representation of the peformance as a whole. **ext3 data=writeback, /data1 and /data2, four threads each**
    
    
        Children see throughput for 1 random writers = 50916.17 KB/sec
        Parent sees throughput for 1 random writers = 50909.04 KB/sec
        Min throughput per process = 50916.17 KB/sec
        Max throughput per process = 50916.17 KB/sec
        Avg throughput per process = 50916.17 KB/sec
        Children see throughput for 1 random writers = 51021.88 KB/sec
        Parent sees throughput for 1 random writers = 51013.58 KB/sec
        Min throughput per process = 51021.88 KB/sec
        Max throughput per process = 51021.88 KB/sec
        Avg throughput per process = 51021.88 KB/sec
        Children see throughput for 1 random writers = 51048.78 KB/sec
        Parent sees throughput for 1 random writers = 51040.33 KB/sec
        Min throughput per process = 51048.78 KB/sec
        Max throughput per process = 51048.78 KB/sec
        Avg throughput per process = 51048.78 KB/sec
        Children see throughput for 1 random writers = 50755.62 KB/sec
        Parent sees throughput for 1 random writers = 50746.71 KB/sec
        Min throughput per process = 50755.62 KB/sec
        Max throughput per process = 50755.62 KB/sec
        Avg throughput per process = 50755.62 KB/sec
    
    
     **/data2:**    Children see throughput for 1 random writers  =   49711.77 KB/sec
        Parent sees throughput for 1 random writers  =   49704.75 KB/sec
        Min throughput per process    =   49711.77 KB/sec
        Max throughput per process    =   49711.77 KB/sec
        Avg throughput per process    =   49711.77 KB/sec
        Children see throughput for 1 random writers  =   49708.98 KB/sec
        Parent sees throughput for 1 random writers  =   49695.55 KB/sec
        Min throughput per process    =   49708.98 KB/sec
        Max throughput per process    =   49708.98 KB/sec
        Avg throughput per process    =   49708.98 KB/sec
        Children see throughput for 1 random writers  =   49713.46 KB/sec
        Parent sees throughput for 1 random writers  =   49691.86 KB/sec
        Min throughput per process    =   49713.46 KB/sec
        Max throughput per process    =   49713.46 KB/sec
        Avg throughput per process    =   49713.46 KB/sec
        Children see throughput for 1 random writers  =   49707.78 KB/sec
        Parent sees throughput for 1 random writers  =   49699.04 KB/sec
        Min throughput per process    =   49707.78 KB/sec
        Max throughput per process    =   49707.78 KB/sec
        Avg throughput per process    =   49707.78 KB/sec

That is more like it... ~200MB/s. In seeing this improvement, I decided to run 8 threads per partition. I am only going to post one output but all of the threads had similar performance. The per thread performance went down but the aggregate performance for each partition was higher at ~ 280MB/s. Between the two arrays that is ~ 560MB/s.
    
    
    Children see throughput for 1 random writers  =   35403.08 KB/sec
    Parent sees throughput for 1 random writers  =   35398.90 KB/sec
    Min throughput per process    =   35403.08 KB/sec
    Max throughput per process    =   35403.08 KB/sec
    Avg throughput per process    =   35403.08 KB/sec

---
[View this page online](https://www.commandprompt.com/blog/is_that_performance_i_smell_ext2_vs_ext3_on_50_spindles_testing_for_postgresql/)

---

# In the news again today :)... but for something technical

> Command Prompt made news today at the grace of our very good partners in the PostgreSQL Community, Truviso. We are working with Truviso to implement some very …

Command Prompt made news today at the grace of our very good partners in the PostgreSQL Community, [Truviso](<http://www.truviso.com/>). We are working with Truviso to implement some very cool vacuum features that will help with long running transactions. Here are some links from the outside world: 

  * [Business Wire](<http://www.businesswire.com/portal/site/google/?ndmViewId=news_view&newsId=20080418005165&newsLang=en>)  

  * [Morning Star](<http://news.morningstar.com/newsnet/ViewNews.aspx?article=/BW/20080418005165_univ.xml>)  
  
http://news.morningstar.com/newsnet/ViewNews.aspx?article=/BW/20080418005165_univ.xml  
  
  

  * [Forbes](<http://www.forbes.com/businesswire/feeds/businesswire/2008/04/18/businesswire20080418005165r1.html>)  

  * [Yahoo Business](<http://biz.yahoo.com/bw/080418/20080418005165.html?.v=1>)  

  * [Sys-Con Media](<http://www.sys-con.com/read/546723.htm>)

---
[View this page online](https://www.commandprompt.com/blog/in_the_news_again_today__but_for_something_technical/)

---

# Additional comments about my talk at MySQLCon

> Colin Charles blogged about my talk at MySQLCon. I wanted to clear a few things up that he mentioned.

I noted in my talk:

EnterpriseDB is the opposite, t…

Colin Charles blogged about [my talk at MySQLCon](<http://www.bytebot.net/blog/archives/2008/04/17/what-mysql-can-learn-from-postgresql>). I wanted to clear a few things up that he mentioned. I noted in my talk: EnterpriseDB is the opposite, theyre closing up more and more. I spoke with Bob Zurek who is the CTO of EnterpriseDB. I was not correct in my EnterpriseDB comment. My reference came [from this page](<http://www.enterprisedb.com/products/postgres_plus_as.do>) which is very difficult to tell which is Open Source and which is not. I still think they would benefit more if they would be to just open everything. My impression (after the conversation) is that EDB is actually opening more and more product, such as [GridSQL](<http://www.enterprisedb.com/community/projects/gridsql.do>). Although they are keeping some crown jewels closed source (Oracle Compatibility). So kudos to Bob for having a great feedback session. Also in my talk I wrangled a little bit with a gentlemen from Fox Interactive Media (whose name I left out in my previous post, but Colin Charles mentioned him specifically). Colin felt I attacked the guy (not physically of course). All I can say is, "bummer". I didnt think I attacked the guy. I was just being honest. The gentlemen would not have brought up the problem (especially with Sun in the room) if Sun was correctly addressing his needs. If Fox Interactive Media wants a solution to that 5TB problem, interacting with the community is the way to get that problem resolved. Sun would hopefully be part of the solution. Sun recently did submit a [WIP patch on the very topic](<http://archives.postgresql.org/pgsql-hackers/2008-04/msg00990.php>). The response has been tepid because of what I believe is bad communication from Sun. I did say, regardless of the factors involved, the solution is still the same, you have to go through the community. (paraphrased). That point was made at benefit of Sun. Sun can solve the problem on their own, but if they dont work with the community to do so, they end up with a Fork and now they maintain three databases (JavaDB, MySQL, PostgreSQL).

---
[View this page online](https://www.commandprompt.com/blog/additional_comments_about_my_talk_at_mysqlcon/)

---

# What MySQL (and really, Sun) can learn from PostgreSQL

> I spent April 17th, 2008 flying to San Jose, Ca only to arrive 30 minutes before my talk, &quot;What MySQL can learn from PostgreSQL&quot;, jump in a cab and literally w…

I spent April 17th, 2008 flying to San Jose, Ca only to arrive 30 minutes before my talk, "[What MySQL can learn from PostgreSQL](<https://web.archive.org/web/20101208191555/http://commandprompt.com/files/mysql_learn.pdf>)", jump in a cab and literally walk into the door of the room I was assigned, "right on time". I think the talk went over fairly well. I opened with the statement, "This is not about MySQL AB, this is about MySQL and the community." I think it help set the tone for the presentation. I didn't want people to feel like I was attacking a profit model or a company. Some items that came up that are not in the talk: * In place upgrades This is a long standing and embarrassing wart for PostgreSQL. No, Slony is not a solution. An individual in the talk asked about in place upgrades for PostgreSQL. They have a database that is 5TB in size. **Let's think about that for a second... a database that is 5TB in size.** There is currently zero viable solution for upgrading a PostgreSQL database 20% of that size, let alone the full 5TB (if you are a 24x7 shop). Our largest competitors have in place upgrade (MSSQL, MySQL, Oracle). Why is it we don't again? A gentlemen from Sun is currently [working on the problem](<http://archives.postgresql.org/pgsql-hackers/2008-04/msg00990.php>), hopefully he is able to make some progress for 8.4. Another tidbit that I found out while having an excellent conversation on community development with [Marten Mickos](<http://en.wikipedia.org/wiki/M%C3%A5rten_Mickos>) is that he is currently [Josh Berkus's](<https://web.archive.org/web/20090403023602/http://it.toolbox.com/people/josh_berkus/>) boss. Which means the former boss of MySQL is now the current boss of a PostgreSQL Core member (although up the chain a bit). Lastly, one thing I noticed about MySQLCon is that the conference was focused on specific solutions. The last couple of PostgreSQL events I have attended have been focused on PostgreSQL the server (with a couple of exceptions like ptop). I think its time we reach out to folks like Catalyst, Drupal and Groovy. We need to get people talking about solutions on PostgreSQL, not just PostgreSQL itself. Thanks to HarrisonF and the MySQL folks that wore PostgreSQL shirts so I wasn't alone in the room!

---
[View this page online](https://www.commandprompt.com/blog/what_mysql_and_really_sun_can_learn_from_postgresql/)

---

# At East... keynote went well

> I delivered the Keynote for East this morning. It seemed to go very well, with a full discussion on expanding the community. I spoke on using mentoring contact…

I delivered the Keynote for [East](<http://www.postgresqlconference.org/>) this morning. It seemed to go very well, with a full discussion on expanding the community. I spoke on using mentoring contacts as well as organizing the community for free work shops. There is a surprising and well received number of new community members here.

---
[View this page online](https://www.commandprompt.com/blog/at_east_keynote_went_well/)

---

# Only 3 days left for PostgreSQL Conference: East

> Online registration ends for PostgreSQL Conference East on March 26th
at 5:00pm PST. PostgreSQL Conference: East is being held at the
Univerisity of Maryland…

Online registration ends for PostgreSQL Conference East on March 26th at 5:00pm PST. PostgreSQL Conference: East is being held at the Univerisity of Maryland, College Park in the CSIC building. The conference series is designed to be a geographically strategic series of conferences that allow contributors, current users and future users/developers to learn and network. Each conference is held in an Academic facility, students and educators are free. Our goal is to establish a series of forums for local developers, administrators and users to mingle with leading PostgreSQL contributors. Initially these forums and conferences will be held in the U.S. but we are also working with our European counterparts. For more information on the conference or to register visit: <http://www.postgresqlconference.org/> All registrations and sponsorships are donations to PostgreSQL via Software in the Public Interest, Inc., a 501(c)3 non-profit corporation.

---
[View this page online](https://www.commandprompt.com/blog/only_3_days_left_for_postgresql_conference_east/)

---

# Read only templates, PDXPUG March 20th, 2008

> I was at PDXPUG last night. While everyone was introducing themselves, they also mentioned one of their least favorite items about PostgreSQL. It was interesti…

I was at [PDXPUG](<http://pugs.postgresql.org/pdxpug>) last night. While everyone was introducing themselves, they also mentioned one of their least favorite items about PostgreSQL. It was interesting to hear everyone's experiences. Selena was frustated because: 
    
    
    \e foo(text);
    

Won't open the foo(text) function declaration in her editor. Jeff Davis was frustrated because there is no way to get [rules](<http://www.postgresql.org/docs/8.3/interactive/rules-update.html>) to return an accurate number of tuples that are modified when the rule executes. Another individual (I don't recall the name, sorry) was frustrated with the database template1. For those that don't know, template1 is the default template database. Any database you create in PostgreSQL by default will use the template1 database as a template. This means that if you create 40 tables in template1 and then create database foo, those 40 tables will also exist in template1. I believe it was David Wheeler that brought up it would be cool if you could set a template database read only or "static". The idea being that you configure your template and run a command like: 
    
    
    ALTER DATABASE FOO SET STATIC;
    

Which would prevent any further modifications to that database until you unset the static keyword. This would be particularly useful in preventing accidental creations. Lastly, my main complain is the postgresql.conf. I still feel it is completely silly that all but a handful of the parameters are even in the file. They should be configured from the database.

---
[View this page online](https://www.commandprompt.com/blog/read_only_templates_pdxpug_march_20th_2008/)

---

# Less than two weeks to go until East!

> Calling all Elephant herders! On March 29th and 30th 2008, The PostgreSQL Community Conference: East is set to unleash the preeminent source of community inter…

Calling all Elephant herders! On March 29th and 30th 2008, The PostgreSQL Community Conference: East is set to unleash the preeminent source of community interaction, knowledge exchange and learning to ever land on the East Coast! Not since the Founding Fathers sat huddled around candles extolling the virtues of declaring Independence from our taxation without representation overlords has a single more important event be presented to the general populous. We have presentations from some of the most well known names in the PostgreSQL community including, Andrew Dunstan (Dunslane Consulting), Magnus Hagander (Win32 port guru), Bruce Momjian (PostgreSQL Lead Integrator), Joshua Drake (me), Andrew Sullivan (level headed community guy and IETFer), Chris Browne (Slony committer), Robert Treat (Major Contributor), Greg Sabino Mullane (DBD::Pg maintainer) and many, many more. Click here for a [complete list of talks.](<http://www.postgresqlconference.org/talks>) As always all registrations and sponsorships are donations to PostgreSQL via Software in the Public Interest, Inc., a 501(c)3 non-profit corporation. You can [register here.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/less_than_two_weeks_to_go_until_east/)

---

# Postgresqldocs.org and 3 weeks left until PostgreSQL Conference: East!

> Its been a busy community season for me over here. A couple weeks back Greg Smith started down the path of getting a documentation wiki up for PostgreSQL. CMD …

Its been a busy community season for me over here. A couple weeks back Greg Smith started down the path of getting a documentation wiki up for PostgreSQL. CMD offered to host and the rest is as they say, history. [Postgresqldocs.org](<http://www.postgresqldocs.org/>) is meant to be a best of mailing list and web style site where people can go to find practical examples to in production problems for PostgreSQL. I invite you to go take a look and submit an article or snippet if you have something useful. In other news, [The PostgreSQL Community Conference series](<http://www.postgresqlconference.org/>) looks like it is going to raise more money in 2008 for PostgreSQL than any other event in community history. It is a great time for PostgreSQL when the community can actively fill two community conferences a year (not to mention several miniconfs or pgdays throughout the world). Go PostgreSQL. As a reminder, there are only [3 weeks left for registration](<http://www.postgresqlconference.org/>).

---
[View this page online](https://www.commandprompt.com/blog/postgresqldocsorg_and_3_weeks_left_until_postgresql_conference_east/)

---

# No, I am not a dirty hippy. In other words, on licensing.

> I find for many things the BSD License, leaves a bad taste in my mouth. Not all things of course but some. To me it allows theft of work product. I know this i…

I find for many things the BSD License, leaves a bad taste in my mouth. Not all things of course but some. To me it allows theft of work product. I know this is not the legal interpretation, it is a philosophical one and CMD is just as guilty of this theft as others in the PostgreSQL community including EDB and GreenPlum. The theory behind the BSD license is a good one. The great people contribute because it is the right thing to do. The good people contribute because they are compelled by the greater force of the community. The bad people? Well they steal it and call it their own. The best scenario is that a contributor is compelled to contribute per the value of the content. That content could be code ([PostgreSQL](<http://www.postgresql.org/>)). Reality dictates that there is a general level of community coercion that takes place and that the great people are few, the good people are some and the bad people are many. The LGPL seems to present the most reasonable flexibility of Freedom (which BSD provides) and community contribution (which the GPL forces). It is reasonable that as an author of software I can close that software. It is reasonable that a user may chose not to use that software because I chose to close it. It is not reasonable to force someone to open their software. It is absolutely not reasonable to close source modifications made to software that you don't own without giving back to the community (or author). The LGPL provides us with the protection to enforce that code stability. Should I chose to author and compile a piece of code on Linux, I can close source it because glibc is LGPL. However if I modify glibc itself, I have to give the change back. To me is that is a definition of fair. Lastly, no I don't think PostgreSQL should change their license (I don't think they could anyway). The BSD has worked well for PostgreSQL. I didn't say BSD was bad in all cases.

---
[View this page online](https://www.commandprompt.com/blog/no_i_am_not_a_dirty_hippy_in_other_words_on_licensing/)

---

# PostgreSQL at SCALE day 2

> It&#x27;s the second day of the Southern California Linux Expo (well third, but second for PostgreSQL) and things are looking good so far. When walking the floor ye…

It's the second day of the Southern California Linux Expo (well third, but second for PostgreSQL) and things are looking good so far. When walking the floor yesterday I was greeted by the pleasant surprise a customer,([Randr](<http://www.randrinc.com>)) has a booth at the show. I am glad to see that their Open Source business (based on PostgreSQL of course) is doing so well. Selena made a great [PostgreSQL Conference](<http://www.postgresqlconference.org/>) flyer yesterday. I am not sure why we didn't think about that before. Great work Selena it looks excellent (we printed it in color of course). I also spent a lot of time speaking with Dru of BSD Certification fame as well as a gentlemen from LPI. They are very interested in the [PostgreSQL Certification](<http://www.postgresqlcertification.org/>) efforts that we have launched. Dru has offered to help in any way that she can which I am greatly appreciative of. We are going to need a lot of community support to make sure the project gets off the ground in a successful way. One of the items that I have taken note of at the show is the community. SCALE has a different style of community user. We have met a lot of people who are using PostgreSQL or want to use PostgreSQL but they are not DBAs or developers. They are usually system administrators or of a integrator ilk. It has been great reaching out to an even more diverse level of community. Foresight Linux has a booth. Foresight is one of the projects that I had been talking to about becoming and affiliated project for [SPI](<http://www.spi-inc.org/>). Unfortunately for SPI they have decided to go with the Software Conservancy. I am glad to see that they finally decided on a non profit to help them. Foresight Linux is an up and coming distribution of Linux that has a strong (if small) and vibrant community. Good luck guys!

---
[View this page online](https://www.commandprompt.com/blog/postgresql_at_scale_day_2/)

---

# PostgreSQL at Southern California Linux Expo

> I am currently staffing the PostgreSQL booth at the Southern California Linux Expo. Initially the show was a little slow but I as kindly reminded as I reminisc…

I am currently staffing the PostgreSQL booth at the [Southern California Linux Expo](<http://www.socallinuxexpo.org/>). Initially the show was a little slow but I as kindly reminded as I reminisced about the high traffic days of OSCON that the Keynote for the show actually takes place mid morning. Once the key note ended traffic increased and with traffic increases comes new and old community members. Interestingly enough we have had many people ask us if we are now "Sun". Apparently the names MySQL and PostgreSQL are close enough to cause the confusion. Go figure. For the record (in case someone needs to be reminded), PostgreSQL can not be bought and we are stronger for it. We can not be killed by budget cuts, you can't hand our CEO walking papers and we are not subject to share holders that just want to see the share price go up at all costs. PostgreSQL is the strongest, mature and extensible Open Source database in existence. If you are looking for a database that you can rely on for years and years to come, take a look at the [community website.](<http://www.postgresql.org/>) You will see that even though PostgreSQL is **just a community** we have supported releases going back 5 years or more. Other topics we have been asked about are Windowing queries (come on guys, it is time to get this done), and oddly enough Merge. We might even see some contributed code in the form of a [Pgfoundry project](<http://www.pgfoundry.org/>) for Merge. Oh and here is the [interview](<http://www.socallinuxexpo.org/blog/2008/02/07/interview-with-postgresql-developers/>) that Josh Berkus and I did.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_at_southern_california_linux_expo/)

---

# Thoughts on the PostgreSQL EU non profit.

> I was talking with a peer about the particular PGEU problem that I am currently arguing on the following thread. I wanted to see if I could explain my position…

I was talking with a peer about the particular PGEU problem that I am currently arguing on the [following thread.](<http://archives.postgresql.org/pgsql-eu-general/2008-01/msg00128.php>) I wanted to see if I could explain my position outside of the thread to allow the thread to stay productive.

I am aware that there are variable levels of cultural idioms in all countries. Americans have theirs, Canadians, Germans... all of them. Whenever I make a comment about the succinct nature of PeterE's responses, the response I get back is, "He's German". It's not derogatory, it's a statement of a particular cultural perspective.

I on the other hand am trying to look past cultural divides. This isn't about Europe or America or Japan. This is about PostgreSQL. I don't care if you are a Platypus from Australia, if you know and love PostgreSQL I want you involved.

To take it back to a practical example. I posted the following email about [PostgreSQL Conference East a while back.](<http://archives.postgresql.org/pgsql-eu-general/2007-11/msg00051.php>)

One of the responses I got back was, "Why do Europeans care about a United States conference?" My response to that was and still is:

 **" It is not an United States conference. It is a PostgreSQL conference being held in United States".**

Because we are all members of PostgreSQL you should care.

I specifically ignore (much to others dismay) cultural, racial and sex boundaries because I believe those boundaries are the implicit basis for most problems created within the world as a whole. When I apply the philosophy of no boundaries to PostgreSQL we have (initially) three distinct micro communities:

  * EU
  * JPUG
  * NA (north america)  
(note there are others that are forming like Pg.BR)



I believe it makes absolute sense to have legal organizations in place that represent the community. They should however be representing the PostgreSQL community as a whole, while being strategically located within their particular geographic region.

The problem arises when you limit who can be active within a particular organization. When an organization generates artificial limitations based on cultural divides you are not representing PostgreSQL as a whole. You are representing a subset of PostgreSQL which will in the long run creates rifts and weaken the global fabric of the macro community.

I see this to some degree within the JPUG community already. They barely participate in the larger community. (There are some even larger cultural and language concerns that assist in the divide but those concerns don't exist for the EU community).

The macro community of PostgreSQL is based on the idea of meritocracy. The tallest order being an invitation to -core. Through the hard, diligent, responsible and respectable work of the contributors you garner different levels influence, respect and responsibility.

The current path of the EU micro community is that the meritocracy is limited. Someone from Chile could in fact become one of the most beneficial members to the the EU community and yet never be in a position to authoritatively influence the direction of the micro community itself. That removes a lot of the attraction to crossing regional divides and creating bonds between the micro community and the macro community.

If we continue down this path we are going to end up with a bunch of micro communities that have zero distinct tie to the larger macro community of [PostgreSQL.org.](<http://www.postgresql.org/>) We as a community will be worse for it.

---
[View this page online](https://www.commandprompt.com/blog/thoughts_on_the_postgresql_eu_non_profit/)

---

# Call for Papers: PostgreSQL Conference East

> The call for papers went out tonight for PostgreSQL Conference East which is being held in College Park Maryland on March 29th and 30th. At West, we only had o…

The call for papers went out tonight for PostgreSQL Conference East which is being held in College Park Maryland on March 29th and 30th. At West, we only had one day and a series of 9 talks. This time around, we have two days and three rooms... During EAST we plan on having a series of talks, tutorials and a new format (for us at least) mini-tutorials. The idea behind mini-tutorials is 90 minute HOWTO style talks. In my mind topics that fall under this would be items such as, "Knowing when bgwriter isn't working, and how to fix it" or "How does one use the the TOC option of the custom format for pg_dump." These are not longer tutorials because they don't have to be. They are practical concepts that aren't really discussed well in the documentation and in general people don't talk about them on the lists. What is even more interesting about the three rooms and two days is the wide array of content we are going to be able to provide to our attendees. We can host a total of 10 three hour tutorials, plus 9 talks or we can host about 20 mini-tutorials plus 9 talks or any combination in between. My hope is that we find a creative mix to allow not only a strong technical contribution to the community but also some inter-social time to allow users to mingle with contributors. If you would like to [submit a talk here is where you need to be!](<http://www.postgresqlconference.org/talk_submission/>)

---
[View this page online](https://www.commandprompt.com/blog/call_for_papers_postgresql_conference_east/)

---

# Phew... Handling PostgreSQL Conference East 08

> When Selena and I started with the Fall Conference last October we had no idea what a success it was going to be. O.k., Selena swears she knew but I was surpri…

When Selena and I started with the Fall Conference last October we had no idea what a success it was going to be. O.k., Selena swears she knew but I was surprised. After Fall there was zero question that we were going to do an East. The community demand was just too high and we have a volume of not only contributors but also general community on the East coast. Since the announcement of East I have had a lot of people contacting me directly. Many of these people I had never even heard of, all of them were telling me they plan on attended and they wanted to know how they could help. I was surprised at the number of lurkers we have on the lists. In fact, we have had so much direct contact about the conference that the Organizing team has increased the number of rooms we will have at the conference. This is in turn is going to increase the amount of content that we can provide to our attendees. Now that our facilities and dates are firm, we can start on the real work, which is insuring that our attendees receive best of breed tutorials, talks and (possibly) mini-tutorials. As you are thinking about how you are going to recover from Spring Break (do we still recover from Spring Break?), consider coming to Maryland on March 29th and 30th. Check this link for more information on [The Community PostgreSQL conference.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/phew_handling_postgresql_conference_east_08/)

---

# PostgreSQL Conference East 08 (updated)

> It&#x27;s that time, after a wildly successful conference last October in Portland, Oregon we are now beginning to ramp up for the East Coast 08 conference! The cur…

It's that time, after a wildly successful conference last October in Portland, Oregon we are now beginning to ramp up for the East Coast 08 conference! The current plan is to host a two day conference of Tutorials (new) and Talks on March 28th and 29th. The currently designated location for the conference is the Univserity of Maryland. This will be confirmed within two weeks. For now, we are making a call out to the community, it was the hands of the community that made the October conference great. It will be the hands of the community that makes the March conference great! We have already had a couple of offers for help which we are grateful for but we want to make sure that we open this up for anyone who may want to help organize the conference. Of specific interest are community members that are geographically close to the Maryland area. We will need boots on the ground to help us follow up with others (such as student unions etc..) to make sure we kick this conference off without a hitch. As a reminder all proceeds from the Conference series go directly to Software in the Public Interest, a 501(c)3 non-profit, and will be used for PostgreSQL development, support and advocacy. So if you are on the east coast and can help with organizing this conference please let me know at jd go-no-spam@ commandprompt.com . [updated] The [conference website is located here.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_east_08_updated/)

---

# PostgreSQL logging, time for a change

> I have often thought that PostgreSQL logging although very flexible is also unwieldy.  PostgreSQL has so many logging options, it is difficult if not impossibl…

I have often thought that PostgreSQL logging although very flexible is also unwieldy. PostgreSQL has so many logging options, it is difficult if not impossible to find the "right" logging setting without a lot of trial and error. Let's just break it down. Below is all of the logging options available to DBAs when 8.3 hits store shelves. 
    
    
    #log_destination = 'stderr'		
    # This is used when logging to stderr:
    #logging_collector = off		
    

Why do we have both of the above? Let's just have: 
    
    
    log_collector

Which would be either, stderr, syslog, cvslog, eventlog, or file. 
    
    
    # These are only used if logging_collector is on:
    #log_directory = 'pg_log'		
    #log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' 		
    #log_truncate_on_rotation = off			
    #log_rotation_age = 1d					
    #log_rotation_size = 10MB		
    

This is a tough one because we need to be able to rotate logs and things like logrotate can loose information when rotating. However, logrotate can also execute arbitrary commands so perhaps logrotate can be instructed to execute a psql query that will cause logging to pause during rotation? Once rotation is complete logrotate can execute another query to tell postgresql to start logging again. For those who are not running a logrotate capable machine, use eventlog or syslog and the problem goes away entirely. 
    
    
    # These are relevant when logging to syslog:
    #syslog_facility = 'LOCAL0'
    #syslog_ident = 'postgres'
    

No problem here. 
    
    
    #client_min_messages = notice
    

O.k. why do I care what my client sets its min_messages to. I am the server. If you want to be able to make it configurable, fine. Use ALTER USER, but leave it out of my conf. It is just noise. 
    
    
    #log_min_messages = notice		
    #log_error_verbosity = default
    #log_min_error_statement = error
    

O.k. I really only need one of these. The log_min_messages should just take: 
    
    
     #   debug5
     #   debug4
     #   debug3
     #   debug2
     #   debug1
     #   info
     #   notice
     #   warning
     #   error
     #   log
     #   fatal
     #   panic
    

The verbosity should be inclusive as should the logging of the statement causing the offending warning, error, debug2 etc... 
    
    
    #log_min_duration_statement = -1
    

You can take log_min_duration_statement from my cold dead fingers. 
    
    
    #silent_mode = off		
    

The silent_mode is useless noise in this context. 
    
    
    #debug_print_parse = off
    #debug_print_rewritten = off
    #debug_print_plan = off
    #debug_pretty_print = off
    

I don't actually have a problem with the above, but it seems they should be pushed out of the general logging section. 
    
    
    #log_checkpoints = off
    #log_connections = off
    #log_disconnections = off
    #log_duration = off
    

Yeah all of these should be pushed into some level within log_min_messages. Checkpoints are obviously something to be logged and likely at the NOTICE or INFO level. As far as log_connection/disconnections... if you want that as an option, fine but we only need one option... log_connection. The disconnection should be inclusive. Then we come to log_duration which is obviously useful and I am not sure exactly where to push it in log_min_messages. Maybe something like DEBUG and higher automatically provide duration and offer STATEMENT and STATEMENT_DURATION? 
    
    
    #log_hostname = off
    

O.k. log_hostname is something people probably ask for. I personally always leave it off due to performance problems. It almost seems like one of those options that is there for the sake of having it, not because anyone in their right mind would use it. 
    
    
    #log_line_prefix = ''		
    

Ahhh log_line_prefix, I like this one. Don't touch it. 
    
    
    #log_lock_waits = off		
    

What? Why in the world did we do this? Push it into DEBUG and above and call it good. 
    
    
    #log_statement = 'none'		
    

Another option that really belongs in log_min_messages. Add STATEMENT_DML, STATEMENT_MOD, where STATEMENT (see previous mention) is a implicit ALL. 
    
    
    #log_temp_files = -1		
    

Yeah... DEBUG or above. 
    
    
    #log_timezone = unknown		
    

Uhm... log_line_prefix anyone? Or perhaps part of log_connections? 

Well that's it for at least the next hour.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_logging_time_for_a_change/)

---

# PostgreSQL Conference Fall 2007: My wrap up

> We had a great time at the conference and subsequent party. If you are
ever in PDX and want some great food and interesting accommodations I
strongly suggest…

We had a great time at the conference and subsequent party. If you are ever in PDX and want some great food and interesting accommodations I strongly suggest the Paramount Hotel and Dragon Fish cafe. They treated all of us very well and had great food! The conference did well above expectations, signing on 10 sponsors, some at the last minute (LinuxFund). Our original goal was only 4. And as has been mentioned in other places already, we had well over the 35 attendees we expected, topping out at 60+. That is a great day for our community! Further because of our sponsors and our attendees, we were in a single day able to raise over 5000.00 dollars for the community. Not bad considering we only had 8 weeks to prepare and it is the first conference that the team had done together. The money of course all went to SPI our affiliated 501c3. The money raised will be used to continue our community growth including sponsoring speakers for other shows, purchasing new shirts and the upcoming live CD for 8.3. Of course the team isn't sleeping until next year, we are already busy on our other upcoming conferences. We are having a PostgreSQL Web Technologies mini-conf in February 08. This will be attached to SCALE and will be similar in format to our PGDay last July. We are also having a PostgreSQL Conference East 08! This show is being held in late Winter, early Spring. We are very excited about this conference as we have a swell of community members in the area. It is going to be held in the D.C./Maryland area, likely be 1.5 days and we are hoping for over 100 community members to attend. Make sure you watch for the call for speakers for both of these upcoming shows. Lastly the conference website: [www.postgresqlconference.org](<http://www.postgresqlconference.org>) has all the audio from the talks up. We also have "some" of the slides (more forthcoming) and the video will be up in a couple of weeks! Thanks to everyone again for their support of this conference series. It is great to see the community growing and supporting each other.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_fall_2007_my_wrap_up/)

---

# PostgreSQL Conference: Good Lord... twice as many as we expected

> When Selena Deckelmann and I decided to start a PostgreSQL Conference series, we believed that a small, regional, technically specific conference was appropria…

When Selena Deckelmann and I decided to start a PostgreSQL Conference series, we believed that a small, regional, technically specific conference was appropriate. We considered that at most, we would get around 35 people and it would essentially be a large user group meeting that had a series of talks and was good for the community. That was the end of July. It is now the night before the conference, October 19th. The original sponsorship goal was 4. We have 10. The original attendee goal was 35. We have at least 60 not including speakers. We expected mostly locals from the Pacific Northwest. At least half are not from the Pacific Northwest. I must say I am quite taken aback at the performance of this conference and it has hardened my resolve to have an even bigger conference on the east coast in 6 months (watch for that). Thank you all who are taking time from your lives to support our community, including sponsors, attendees and speakers.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_good_lord_twice_as_many_as_we_expected/)

---

# plphp 1.3.5 Beta 1 Released

> Not much to say here but plphp 1.3.5 Beta1 supports named parameters and PostgreSQL 8.3 Beta1.

Enjoy :) PL/php website

Not much to say here but plphp 1.3.5 Beta1 supports named parameters and PostgreSQL 8.3 Beta1. Enjoy :) [PL/php website](<http://projects.commandprompt.com/public/plphp>)

---
[View this page online](https://www.commandprompt.com/blog/plphp_135_beta_1_released/)

---

# PostgreSQL Gotcha: Default timestamps are not exact!

> If you are compiling PostgreSQL from source you have a configure option called:

--enable-integer-datetimes

Now Debian/Ubuntu wisely turn this option on b…

If you are compiling PostgreSQL from source you have a configure option called: 
    
    
    --enable-integer-datetimes
    

Now Debian/Ubuntu wisely turn this option on by default, unfortunately the RPM provided by PostgreSQL.Org and the RPM provided by RedHat/Fedora do not. Why is this a problem? I think we can all agree that given that a particular value is within a column that value should be able to be retrieved from that column. Consider the following: 
    
    
    SELECT created FROM foo WHERE id = 2630863;
             created        
    -------------------------------
     2007-08-29 12:35:27.897597-04
    

O.k. simple enough. Now consider this: 
    
    
    SELECT created FROM foo WHERE created = '2007-08-29 12:35:27.897597-04';
    
     created
    --------------
    (0 rows)
    

What? That doesn't seem to make sense does it? If we continue our testing: 
    
    
    SELECT created FROM foo WHERE created = '2007-08-29 12:35:27.897597-04'  
       AND id = 2630863;
    
     created
    --------------
    (0 rows)
    

And: 
    
    
    SELECT created FROM foo WHERE created ilike '2007-08-29 12:35:27.897597-04' 
       AND id = 2630863;
             created
    -------------------------------
     2007-08-29 12:35:27.897597-04
    

Say what? Heh... In short... if you can, always use --integer-datetimes. So why is this a really big deal? It is a really big deal because you must initdb to fix the problem. That means a dump and reload. That means a significant outage.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_gotcha_default_timestamps_are_not_exact/)

---

# Recursive PLPGSQL, Lookup Table and Ltree

> There are many reasons and needs to implement a tree structure inside of an SQL database. In our particular example today, we&#x27;re using a basic knowledge base t…

There are many reasons and needs to implement a tree structure inside of an SQL database. In our particular example today, we're using a basic knowledge base tree as an example of a small- to large-scale tree inside of an SQL database. Additionally, any sort of directory/file system layout would be a good match for these concepts. I am going to discuss three basic concepts on dealing with small, medium, and large tree structures  
  
The first, and most applicable to small trees, is a recursive lookup query. In essence, at any given branch of the tree, this function will walk back up the tree and generate a delimited path representing the depth of the given node in the tree. For small trees, this function does work very well, and the dynamic reaction to updates is unparalleled - as every execution of the function examines the tree in full, updates, including branch alterations, are handled very quickly. A delete function, however, is required to remove entire subsets of trees, or to affix them to the parent branch.   
  
Downsides to this approach are the very flexibility it affords, as every single node of a branch is traversed for every object in that tree. One hundred items in a direct linear tree will have significantly more than 100 iterations to walk the entire length. The first branch would walk up two(self, root), the second would walk up three (self, parent, root), and so on, with the final node in the series walking back up the entire length of the tree, 101 iterations of the function. As you can imagine, a fully recursive lookup in this method is highly inefficient for large trees, or for a large connection load. For example, with a basic tree of 10 top-level nodes, each with 10 levels of depth, we have an approximate runtime of 40ms on our development server.  
  
However, if we take this tree to 100 top-level nodes of 10 depth, the runtime increases to 358ms, roughly. So far, it's scaling close to linearly with the size of the database. At 50 top-level nodes, each of 20 depth, the full runtime comes in at 600ms, even though the number of actual rows is the same as before. Doubling the row count to 100 top-level nodes of 20 depth each brings the runtime up to an approximate 1200ms, and this is only with 2000 rows in our database.   
  
As you can see, as the size of the tree increases, so to will the runtime, approximately linearly with the size of the tree. The queries used here were simply to extract the path as "Foo, Bar, Baz" from the tree. The next logical step is a path lookup table. This requires no external modules, merely a trigger and a new SELECT function to operate. It works on the basic principle of, you know where an object in the tree is at insertion time, so why not write it down for later?   
  
The basic layout of the insertion trigger is:   
  
\- Does the new row have a parent ID?   
\- If yes, query the lookup table for the parent ID   
\- If there's a parent ID in the lookup table, append our path to that path, add a new row   
\- else, enter the recursive function and compute the parents' path and our own path, and add both to the lookup table   
\- If no, use our own name as the path and insert ourself into the lookup table.   
  
At this point, our queries can be significantly faster than a full recursive query - the recursion and tree organization is already done, via the lookup table. Querying any level in the tree gives us all the nodes all the way back up, via a regex and a second select statement. For instance, in a "." delimited path, we can extract any member of the tree "Foo.Bar.Baz.Foobar.Foobaz" via  
  

    
    
    SELECT id FROM lookup_table 
       WHERE path ~ "^Foo.Bar.Baz$";
    

  
for any . level of the tree.   
  
This can also be used to manage large-scale deletes and updates of the table. Downsides to this approach are that your triggers must fire properly, both for inserts and deletes from the database. A second trigger or function would be required to manage deletes on branches in the tree. Further downsides include poor performance on the regex queries, though this could be partially alleviated with appropriate indexes being added to the lookup table. Further issues arise from moving branches around inside the tree, requiring more processor time to analyze all the paths in the lookup table and rearrange them correctly to reflect the new tree layout. For instance, if one moves a node from Foo.Bar.Baz to a direct child of Foo.Bar, then one would have to have a subsequent call of  
  

    
    
    UPDATE lookup_table SET path = "foo.bar." || 
       old path where path = "foo.bar.baz.old_path";
    

  
or something in that general idea. Furthermore, additional time must be spent to write a series of regex functions to analyze locations in the tree, and to do interleaving in the event you may want, for instance, "Foo.Bar.*.Baz". This can prove to be a complex and time-consuming proposition. Delete, however, is much faster than the previous concept, where entire swaths of the tree can be removed by  
  

    
    
    DELETE from tree_table 
    WHERE id IN (
       SELECT id FROM lookup_table where path  = "$Foo.Bar.*"
    ); 
    

  
roughly. The initial lookup table is built using the recursive path query lookup. The pathnames are created as "parent.child.second_child", etc. Path is stored as TEXT field. Since queries to generate only the full path listing would be pointless at this stage, due to their pre-existence, we will focus on extracting only specific branches of the tree from here on in. The first query,  
  

    
    
    SELECT path FROM tree 
       JOIN lookup_table ON tree.id = lookup_table.tree_id;
    

  
has an approximate runtime of 11ms. So, let's find all the nodes that have "baz" in them, which carries a runtime of 13ms, using the query  
  

    
    
    SELECT * FROM tree 
    JOIN lookup_table ON tree.id = lookup_table.tree_id 
    WHERE path ~ 'baz';
    

  
Basic query, very fast. A similar query using the recursive function runs in 1232ms, no drop from simply selecting all of the rows. However, what if we wanted only the rows from the table where 'baz' was the top-level?  
  

    
    
    SELECT * FROM tree 
    JOIN lookup_table ON tree.id = lookup_table.tree_id 
    WHERE path ~ '^baz'; 
    

  
is one simple way, and runs in approximately 3ms. or where baz is anywhere in the tree, but NOT the root?  
  

    
    
    SELECT * FROM tree 
    JOIN lookup_table ON tree.id = lookup_table.tree_id 
    WHERE path ~ '\w{0,}\.baz\\.\w{0,}';
    

  
which runs in 20ms, and only returns nodes which have .baz. However, there's no easy way to tell if 'bar' is a child node of 'foo', for instance. A regex similar to '*.foo\\\\.\w*\\.bar'.  
  
However, having to write out these complex regexes takes significant development time and resources and testing. Ltree builds further on top of the lookup table functionality, moving certain complexities into pre-written C functions and binding comparison tools as infix operators, significantly simplifying the queries required. As the majority of the module is written in C, it is most suitable for very large trees, or systems with a large number of concurrent users. All the regexes provided by the standalone lookup table are still applicable in the ltree mode, and some new syntax is provided specifically to work with tree structures.   
  
Converting from the initial lookup tree path to the ltree path format is taken care of by a very convenient function - text2ltree(TEXT). Rebuilding the index can be done in a quick, simple and easy query, remarkably close to the query that originally built the lookup table. However, ltree still has the same basic disadvantages a the lookup table, as the same trigger must be used to create the lookup table, as well as requiring the same delete and insert code. However, such code CAN be significantly simplified by using the infix operators that are provided by the ltree module. For instance, one can acquire all items in a tree using a simple and understandable query such as  
  

    
    
    SELECT path FROM lookup_table 
    WHERE path <@ 'Foo.Bar'; 
    

  
returning all nodes under the Bar branch in the Foo tree. This is similar, but significantly more flexible than the regex function discussed in the Lookup Table section, as you are not required to give the entire path to the right side of the query, in this case. Such a query would resemble  
  

    
    
    SELECT path FROM lookup_table 
    WHERE path ~ '*{1,}.bar.*{0,}';
    

  
thus giving anything under any of the .bar branches, no matter what their location in the tree. So bar.bar would match, as would foo.bar.baz, or foo.foobage.bar.baz.foobar. This query has a runtime of 2.2ms, in total. However, this doesn't really show the full potential of ltree - yes, it's fast and the syntax allows for very sophisticated manipulation of the tree.   
  
But how fast is it when the tree is excessively large? The ltree documentation uses a fragment of the DMOZ (dmoz.org) index to show off the versatility of its tree manipulation speeds. Our demonstration tree has been increased to a size of 10,000 top-level nodes with a varying depth of 25-75. This gives us, at minimum, 250,000 nodes. The above query, doing a basic path query, took 600ms, using the ltree module, over a set of approximately 280,000 records. The same query, modified slightly to use ltree-to-text for standard regex mapping, took approximately 974ms. The query  
  

    
    
    SELECT count(*) FROM lookup_table 
    WHERE path <@ 'foo';
    

  
also took an approximate 220ms to completely, returning 37k rows. The similar query,  
  

    
    
    SELECT count(*) FROM non_ltree_lookup 
    WHERE path ~ '^foo\\.\w{0,}';
    

  
using a plain regex took approximately 500ms. All queries are shown without indexes on the lookup tables.

---
[View this page online](https://www.commandprompt.com/blog/recursive_plpgsql_lookup_table_and_ltree/)

---

# The easy but harder than I thought road to PostgreSQL Conference Fall 2007

> The PostgreSQL Conference Fall 2007 has given me a knew appreciation for the little things. If it wasn&#x27;t for PDXPUG leader Selena Deckelmann the conference wou…

The PostgreSQL Conference Fall 2007 has given me a knew appreciation for the little things. If it wasn't for [PDXPUG](<http://pugs.postgresql.org/pdx>) leader Selena Deckelmann the conference would not have the complimentary breakfast/social nor would it have the synopsis of the talks on the [conference website.](<http://www.postgresqlconference.org/>) The hard work of Selena, myself and the speakers appears to be paying off. We have a strong list of sponsors as well as a very strong list of speakers. See for yourself: 

# Speakers and Topics

  * 8:00 - 8:45 - Coffee / Breakfast / Social / Wake up / Go back to hotel for socks (provided by conference) 
  * 8:45 - 9:00 - Joshua Drake - A word from our sponsors 
  * 9:00 - 9:25 - JoshB - Welcome to 8.3 
  * 9:25 - 10:20 - David Wheeler - Web 2.0 (Rails) applications with PostgreSQL 
  * \-- 10 minute break -- 
  * 10:30 - 11:20 - Robert Hodges - Scaling PostgreSQL Performance with uni/cluster 
  * 11:20 - 12:10 - Neil Conway - Understanding Query Execution in PostgreSQL 
  * 12:10 - 13:15 - Lunch 
  * 13:15 - 13:45 - Mark Wong - PostgreSQL Performance 
  * 13:45 - 14:15 - Joshua Drake - PL/Proxy and Horizontal Scaling 
  * 14:15 - 15:05 - Web Sprague - PostGIS (geographic database) 
  * \-- 10 minute break -- 
  * 15:15 - 16:05 - David Fetter - Babel of procedural languages 
  * 16:05 - 17:00 - Robert Treat - PostgreSQL Partitioning, semantics, pitfalls and implementation 
  * 17:00 - 17:25 - Josh Berkus - Stupid Solaris tricks 
  * 17:25 - 17:30 - Closing Remarks, Thanks, Where's the party? 
  * 17:30 - 18:00 - Get to party/dinner (provided by conference) 
  * 18:00 -- Dinner/Party till they kick us out 

If you haven't registered for [PostgreSQL Conference Fall 2007, you can do so with this link.](<http://www.postgresqlconference.org/>)

---
[View this page online](https://www.commandprompt.com/blog/the_easy_but_harder_than_i_thought_road_to_postgresql_conference_fall_2007/)

---

# Log level correlations

> There was a post recently on using Syslog with PostgreSQL on pgsql-general. As you can see, Tom Lane kindly replied in the thread.

I decided that it might b…

There was a [post recently on using Syslog with PostgreSQL on pgsql-general.](<http://archives.postgresql.org/pgsql-general/2007-09/msg00972.php>) As you can see, Tom Lane kindly replied in the thread. I decided that it might be a good idea to submit a [DOC patch.](<http://archives.postgresql.org/pgsql-patches/2007-09/msg00305.php>) I only received on comment on the patch, so I don't know if it will be applied or not. The comment, caused me to consider creating a table for the docs that correlated the different log levels between PostgreSQL, Syslog and Eventlog. The HTML version of that table is below: Log level correlation  
---  
PostgreSQL| Syslog| Eventlog  
DEBUG1-DEBUG5| LOG_DEBUG| EVENTLOG_INFORMATION_TYPE  
LOG| LOG_INFO| EVENTLOG_INFORMATION_TYPE  
INFO| LOG_INFO| EVENTLOG_INFORMATION_TYPE  
NOTICE| LOG_NOTICE| EVENTLOG_INFORMATION_TYPE  
WARNING| LOG_NOTICE| EVENTLOG_WARNING_TYPE  
ERROR| LOG_WARNING| EVENTLOG_ERROR_TYPE  
FATAL| LOG_ERR| EVENTLOG_ERROR_TYPE  
PANIC| LOG_CRIT| EVENTLOG_ERROR_TYPE  
I have decided not to submit a patch to -docs for this. I do not have the inclination to use DocBook SGML (XML sure and yes it is quite a bit different) and since we are past year 2001, the tools out there I could find support only DocBook XML.

---
[View this page online](https://www.commandprompt.com/blog/log_level_correlations/)

---

# PostgreSQL Conference Fall 07

> When sitting in the booth with the Army of Smurfs (tm) at OSCON 2007, I was struck by the idea that having PostgreSQL Conference(s) (yes plural) could be a gre…

When sitting in the booth with the Army of Smurfs (tm) at OSCON 2007, I was struck by the idea that having PostgreSQL Conference(s) (yes plural) could be a great way to insure the growth of our community. Check -- duh! You would think that this is obvious. In fact I would think this is obvious. This is why the community had the Anniversary two years ago and Dan Langille was successful with his PgCon last May. However, I foresaw what I concluded was a fatal flaw in the traditional trade show, in that... only those in the know, actually attend and only those who can expense it, will normally travel for them. In the past this problem could be solved with a user group, but user groups are typically one evening, once a month and only a couple of hours long. A lot of the time, they are just social gatherings which of course is good but is not a way for someone new, learning, or just plain curious about our technology is going to get a solid presentation of what our technology is all about. Thus buds my idea about PostgreSQL Conference Fall 07 (and in fact many more to come). [PostgreSQL Conference Fall 07](<http://www.postgresqlconference.org/>) is a community conference. It is a highly technical conference. It is a geographically strategic conference. It is a conference for and about our community and the incredible software that community produces. It is one day, of technical presentations, specifically on features that everyone wants to know about and only a few actually do. Our topics are ranging from horizontal partitioning, to performance to Geographic information systems using PostGIS. O.k. so what, why is this so cool? I will quote Josh Berkus, "It seems to be the way that PostgreSQL events are growing organically. We seem to be a very decentralized project. Partly it's also timing; in the world of tech conferences, the current trend is for smaller, thriftier, regional conferences (e.g. the growth of "LinuxFest [location]" and the collapse of LinuxWorld)." I would agree 100% with this statement and add to it. Having smaller conferences, and many of them that are settled strategically within a geographic area that incorporates PostgreSQL contributors, allows those who are not contributors who would come to a conference like this, to mingle with contributors, learn from them and thus become contributors themselves. That simple equation equates to: **contributor * (5 + new users) = larger community with more contributors** So how is one conference going to increase our community. It isn't, but a dozen will. In short (for such as long blog post), we are going to be planning, or help plan and organizing at least a dozen conferences over the next year. In the United States alone we already have the following conferences planned: 

  * Fall 07 
  * Winter 08 -- Part of SCALE 
  * Spring 08 -- East Coast 
  * Summer 08 -- OSCON 
  * Summer 08 -- LWE 
  * Fall 08 

Winter 08 and the two summer 08 conferences will be larger as they are attaching to the larger conferences of SCALE, OSCON and LWE. Spring 08 is essentially the east coast version of Fall 07 but focusing on the east coast crowd who doesn't want to fly 6 hours to the west coast for a one day conference (regardless of the great party they are going to miss). Further, there are European conferences happening that PostgreSQLConference.org would like to be a part of, including the upcoming PgDay.It in 08 and EuroPGcon. That is part one. Part two is that the every single conference that PostgreSQLConference.org is organizing is 100% community. All monies from sponsorships, registrations, swag sales etc... go directly back to the community. If in the U.S., it will go directly through the PostgreSQL.org SPI account which is a 501c3 non-profit. Should PostgreSQLConference.Org organize a European conference, then the same will apply with whatever local non-profit exists, for example ffis e.V.. The end result of course, is not only a stronger community but a wider community that allows all users of PostgreSQL to be successful with their deployments.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_conference_fall_07/)

---

# PostgreSQL 8.3, it's faster, really it is!

> I downloaded the latest check out of PostgreSQL 8.3 (not even beta yet) just to see how things are progressing. Of particular interest to me was a recent conve…

I downloaded the latest check out of PostgreSQL 8.3 (not even beta yet) just to see how things are progressing. Of particular interest to me was a recent conversation about sequential scans I had with Jeff Davis. In short, in 8.3 sequential scans should be faster. I decided to test the theory. Using the exact same machine, and an optimized 8.1.8 installation, I compared 8.1.8 versus a out of the box unconfigured (except for the tcpip port change) 8.3. First step, create table and populate on both 8.1.8 and 8.3dev. 
    
    
    CREATE TABLE seqtest (test integer);
    INSERT INTO seqtest (test) VALUES (generate_series(1,1000000));
    

Next step execute a guaranteed sequential scan query on 8.3dev. 
    
    
    EXPLAIN ANALYZE SELECT COUNT(*) FROM seqtest;
    
    
    
     QUERY PLAN                                                        
    -------------------------------------------------------------------------------------------------------------------------
     Aggregate  (cost=16905.05..16905.06 rows=1 width=0) (actual time=4633.981..4633.984 rows=1 loops=1)
       ->  Seq Scan on seqtest  (cost=0.00..14405.24 rows=999924 width=0) (actual time=0.363..2317.909 rows=1000000 loops=1)
     Total runtime: 4634.037 ms
    

I ran the above EXPLAIN ANALYZE on 8.3dev five times, all with extremely similar results. In fact the variance was only about 70 milliseconds one way or the other. Then I performed the exact same query on 8.1.9, five times. 
    
    
       QUERY PLAN                                                        
    -------------------------------------------------------------------------------------------------------------------------
     Aggregate  (cost=17904.90..17904.91 rows=1 width=0) (actual time=4905.377..4905.379 rows=1 loops=1)
       ->  Seq Scan on seqtest  (cost=0.00..15405.12 rows=999912 width=0) (actual time=0.025..2536.639 rows=1000000 loops=1)
     Total runtime: 4905.515 ms
    

Again the numbers were consistent across five runs. This is great news. O.k. 300 milliseconds isn't alot... Actually yes it is, that is almost a third of full second, now think about it over 10 million rows. I also ran the same test against SELECT sum() and got similar results. 8.3 does indeed appear to be faster than 8.1 for seq scans. Updated: 08/24/07 I now have what I suspect is the reason for the speed up: 
    
    
    seqtest=#  select version(),pg_relation_size('seqtest');
    -[ RECORD 1 ]----+------------------------------------------------------------------------------------------------
    version          | PostgreSQL 8.1.8 on x86_64-pc-linux-gnu, compiled by GCC cc (GCC) 4.1.2 (Ubuntu 4.1.2-0ubuntu3)
    pg_relation_size | 44285952
    
    
    
    seqtest=#  select version(),pg_relation_size('seqtest');
    -[ RECORD 1 ]----+---------------------------------------------------------------------------------------------------------
    version          | PostgreSQL 8.3devel on x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 (Ubuntu 4.1.2-0ubuntu4)
    pg_relation_size | 36093952
    

You will note that 8.3 is approximately 19% smaller for the same data set. In 8.3 the hackers were able to reduce the size of the row header. Amazing what the little things can do.

---
[View this page online](https://www.commandprompt.com/blog/postgresql_83_its_faster_really_it_is/)

---

# How many rows do I have anyway?

> Have you ever wondered how many tuples you have in a relation? Normally to find out how many tuples you have you would do something like:
SELECT count(1) FROM…

Have you ever wondered how many tuples you have in a relation? Normally to find out how many tuples you have you would do something like: 
    
    
    SELECT count(1) FROM rows;
     count 
    -------
     10002

This will return the exact number, per your snapshot of committed tuples within a relation. It is also a guaranteed _sequence scan_ on the relation and a performance nightmare on large tables. So how do you get around it? Well it depends, if you **need** the exact amount of tuples within the relation, you don't. However if you only need an approximate number you can do this: 
    
    
    SELECT reltuples FROM pg_class 
       JOIN pg_namespace ON (pg_class.relnamespace = pg_namespace.oid) 
    WHERE nspname = '$namespace' 
    AND relname = '$tablename';
     reltuples 
    -----------
         10002

The above will result in the exact number of tuples that PostgreSQL knows to be in the relation. **Q.** How does PostgreSQL know how many tuples are in a relation? **A.** Why ANALYZE of course. When you ANALYZE the pg_class relation is updated with vital and directly pertinent information about your relations. Yet another reason to beat people over the head with the, **WHAT EVERY POSTGRESQL USER NEEDS TO KNOW.**

---
[View this page online](https://www.commandprompt.com/blog/how_many_rows_do_i_have_anyway/)

---

# Surrogate versus Natural Primary Keys

> This is a constant source of argument, flame and general discomfort with any database design. On the PostgreSQL lists it comes up occasionally and it is always…

This is a constant source of argument, flame and general discomfort with any database design. On the PostgreSQL lists it comes up occasionally and it is always a long drawn out thread with people arguing on each side about which one is correct. Before I go on about the good and bad of both, let me define a couple of things. 1\. Surrogate keys (also known as artificial keys) are **not** correct in a correctly normalized design. That doesn't mean they are not useful but if you want a "correctly" designed database, you will not have surrogate keys. 2\. Natural keys are **always** better at representing your data. That doesn't mean they are "easier". Let's assume a very simple structure: 
    
    
      Table "public.one_nf"
       Column   | Type | Modifiers 
    ------------+------+-----------
     first_name | text | 
     last_name  | text | 
    
    
    
    normal_forms=# SELECT * FROM one_nf ;
     first_name | last_name 
    ------------+-----------
     Joshua     | Drake
     John       | Worsley
     Joshua     | Drake
    (3 rows)
    

Here we have already violated 1NF by having duplicate values (yes I am fully aware that there are other components to take into account. This is just the simplest example). We have no Primary Key and we have duplicates. Now, let's add the "standard" component amongst all web frameworks to "fix" this problem. 
    
    
    normal_forms=# ALTER TABLE one_nf ADD COLUMN id serial;
    NOTICE:  ALTER TABLE will create implicit sequence "one_nf_id_seq" for serial column "one_nf.id"
    ALTER TABLE
    normal_forms=# \d one_nf
                               Table "public.one_nf"
       Column   |  Type   |                      Modifiers                      
    ------------+---------+-----------------------------------------------------
     first_name | text    | 
     last_name  | text    | 
     id         | integer | not null default nextval('one_nf_id_seq'::regclass)
    
    normal_forms=# UPDATE one_nf set id = nextval('one_nf_id_seq');
    UPDATE 3
                                               ^
    normal_forms=# ALTER TABLE one_nf ADD PRIMARY KEY (id);
    NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "one_nf_pkey" for table "one_nf"
    ALTER TABLE
    normal_forms=# \d one_nf
                               Table "public.one_nf"
       Column   |  Type   |                      Modifiers                      
    ------------+---------+-----------------------------------------------------
     first_name | text    | 
     last_name  | text    | 
     id         | integer | not null default nextval('one_nf_id_seq'::regclass)
    Indexes:
        "one_nf_pkey" PRIMARY KEY, btree (id)
    

Great now we have a Primary Key, albeit a Surrogate Key. 
    
    
    normal_forms=# SELECT * FROM one_nf;
     first_name | last_name | id 
    ------------+-----------+----
     Joshua     | Drake     |  4
     John       | Worsley   |  5
     Joshua     | Drake     |  6
    (3 rows)
    

Now your table is able to work with any number of ORMs. Which of course makes web development a lot easier but, which Joshua Drake is the correct Joshua Drake? Exactly. You don't know and your data representation is broken. O.k. no sweat, we will just add a UNIQUE constraint. 
    
    
    normal_forms=# DELETE FROM one_nf WHERE id = 6;
    DELETE 1
    normal_forms=# ALTER TABLE one_nf ADD UNIQUE (first_name,last_name);
    NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "one_nf_first_name_key" for table "one_nf"
    ALTER TABLE
    normal_forms=# \d one_nf
                               Table "public.one_nf"
       Column   |  Type   |                      Modifiers                      
    ------------+---------+-----------------------------------------------------
     first_name | text    | 
     last_name  | text    | 
     id         | integer | not null default nextval('one_nf_id_seq'::regclass)
    Indexes:
        "one_nf_pkey" PRIMARY KEY, btree (id)
        "one_nf_first_name_key" UNIQUE, btree (first_name, last_name)
    
    normal_forms=# 
    

Of course I had to delete Joshua Drake, and I am not sure if the Joshua Drake I deleted is the correct one, but that isn't really the point is it? You would think that this enough right? O.k. fair enough, the Surrogate Key allows for very easy queries: 
    
    
    UPDATE one_nf SET first_name = 'Bruce' WHERE id = 1;
    

Versus: 
    
    
    UPDATE one_nf SET first_name = 'Bruce' WHERE last_name = 'Momjian' AND first_name = 'Burce';
    

Is the laziness of a few extra characters worth the performance penalty of the extra INDEX maintenance? Random ramblings I guess. [A great page on 1NF](<http://en.wikipedia.org/wiki/First_normal_form#_note-Elmasri>)

---
[View this page online](https://www.commandprompt.com/blog/surrogate_versus_natural_primary_keys/)

---

# OSCON 2007, PostgreSQL army of smurfs!

> OSCON 2007 was a huge success for the PostgreSQL community. Of course, OSCON is usually a good conference for PostgreSQL but this year was different. So what w…

OSCON 2007 was a huge success for the PostgreSQL community. Of course, OSCON is usually a good conference for PostgreSQL but this year was different. So what was different about this year than other years? How did we stand out from other community booths? What about MySQL? [Professional presence.](<http://archives.postgresql.org/pgsql-advocacy/2007-06/msg00007.php>) The community moved to a professional presence of advocating only PostgreSQL at the community booths. Flexing our community muscle to provide a unified display to all attendees paid off and we received many comments to the pleasant surprise the presentation provided. [An army of technical guys!](<http://www.mysqlperformanceblog.com/2007/07/26/mysql-on-oscon/>) Even MySQL folks noted our presence at OSCON both while during the conference, on blogs at even at the bar after. The fact is, the other Open Source databases (and closed source forks) don't get it. Conferences are about people. They are not about your marketing material. PostgreSQL had a number of very well known contributors present at our booth at any given time including, Josh Berkus, myself, Robert Treat, David Fetter and Alvaro Herrera. We also had local users from PDXPUG such as Selena Deckelmann and Gabrielle. At one point we had a gentlemen come up and thank us for a great product but complain that he was a newbie and hadn't figured out how to get PostgreSQL running on Ubuntu (he had been trying to compile from source). So we walked him through getting the software up on his laptop with Synaptic. He then graciously thanked us and was honestly surprised at how helpful we were. I noted that he was also at our BOF a day later. We have a new community member! How does all of this compare to MySQL? MySQL I am sorry to say was pathetic. They had benchmarks from 2001 one the wall, a small sign begging that they were hiring, and a very pleasant (honestly) marketing gal at the booth. What they didn't have, was booth attendees from the conference. I would note that we also received very few of my favorite question, "How is MySQL different than PostgreSQL?". Those of you who have performed booth duty with me know that I have a threshold for that question, and at about 26... I started imploding. I don't think we even reached 12 this time. Instead we were consistently asked about, "How can I move from Oracle?" or "I need to migrate from MSSQL". This is great as it shows that the public is starting to recognize where our true place lies in the market. What about other community booths? Well one of our (PostgreSQL.Org) SPI fellows, Debian was there but unfortunately it was less than lackluster. This one actually surprised me because OSCON would be a show where Debian could shine. Instead there were two guys on bean bags under a dark tent, and zero material on what Debian is, why you would use it, or even some live CDs. FreeBSD had a solid presence with a nice display (32 inch I believe) to display their wares. I even had the opportunity to talk with someone who was directly involved with the upcoming FreeBSD 7. It looks like FreeBSD 7 will finally catch up or even beat Linux in the scaling and SMP arena. I was taken aback as I regularly do not suggest FreeBSD for PostgreSQL because after 4 CPUs it just isn't worth the effort. Watch version 7, it looks hot. (I would note that when I said to the their booth, "It is about darn time", they smiled and said, "Yes") I would like to put a special shout out to Sun. They appear to actually be thinking about their direction now and not only thinking but actually moving forward. I know.... "Woah Joshua, what are you saying?". I am saying that Sun, not only had a constant presence in the PostgreSQL booth (with Perna not Josh Berkus) but they also accepted our booth rules, willingly. E.g, They wore the PostgreSQL shirt, not a Sun one. They willingly put their marketing material in the folder in its proper place (the last page because it is alphabetical). Their whole attitude was so completely different from just 12 months ago, that I actually bothered to take a Open Solaris development kit to check it out. I wouldn't even have bothered to cover my mouth when I sneezed at it 12 months ago. In all, OSCON 2007 was a huge success and I expect LinuxWorld 2007 to be even better. PostgreSQL.Org, not Command Prompt, not EnterpriseDB, not Greenplum, and not Sun is where it is at and the Open Source community and consumer are starting to recognize this. This is a call out to all commercial supporters of PostgreSQL, you better recognize or you are going to be left in the dust by the people that understand this. Pictures are coming, really!

---
[View this page online](https://www.commandprompt.com/blog/oscon_2007_postgresql_army_of_smurfs/)

---

# PgDay Portland, A huge success!

> On July 22nd, PostgreSQL.Org held a single day conference in Portland Oregon preceding OSCON 2007. This conference, although short notice was a huge success. W…

On July 22nd, PostgreSQL.Org held a single day conference in Portland Oregon preceding OSCON 2007. This conference, although short notice was a huge success. We had solid attendance from new and old community members. Notable talks for me was Theo Schlossnagle's talk on Solaris and PostgreSQL. It was enlightening to see where PostgreSQL is lacking, (places I didn't realize) and how Theo has worked around the problems to provide a quite decent set of tools for Solaris and PostgreSQL. Following PgDay we had the PostgreSQL Party at the Marriot, home of the 5.00 free beer!. The party had excellent turnout (larger than PGDay itself) and lasted longer than I stayed (and I was the host). In all, I look forward to having a even bigger PGDay in Portland next year!

---
[View this page online](https://www.commandprompt.com/blog/pgday_portland_a_huge_success/)

---

# For the record, EnterpriseDB and Command Prompt, Inc.

> I recently made a post on the pgsql-advocacy list about a press release that EnterpriseDB put out that was less than flattering about PostgreSQL [1]. This thre…

I recently made a post on the pgsql-advocacy list about a press release that EnterpriseDB put out that was less than flattering about PostgreSQL [1]. This thread was long and a little tiring. To make matters worse an Oracle blogger [2] picked up the thread and blogged an incorrect assessment of what happen.   
  
I would like to take a moment and set the record straight. First there were some in the community that felt that it was CMD that was attacking EDB (EnterpriseDB). To be blunt, this is horse manure. I as a community member was pointing out a reference in a press release that was in my opinion written badly.   
  
I wanted to address that press release and did so on pgsql-advocacy as I felt it was the most appropriate channel. CMD and EDB are both community members and the press released involved PostgreSQL directly. Secondly, EDB and CMD work together for the community.   
  
We are **not** competitors when the community is at stake. We are partners. Yes we do compete in the marketplace, and I am sure there are many in the old school closed source world that don't quite understand how this could possibly work but it does.   
  
A case in point is that EDB sponsored some of the work on [ODBCng](<https://public.commandprompt.com/projects/odbcng/>) a commercially supported ODBC driver that is Open Source. EDB and CMD are also working together to bring a new and updated [PgFoundry](<http://www.pgfoundry.org/>) machine and environment into production.   
  
The end result is that EDB did the right thing, which I knew they would. EDB has promised to correct some of their marketing efforts to insure that full honesty is presented when referencing PostgreSQL. Everyone knows that marketing is a tricky game. Just remember, "Volvo, they are boxy, but they are good!".   
  
---  
  
[1] [Original post by Joshua D. Drake  
](<http://archives.postgresql.org/pgsql-advocacy/2007-07/msg00023.php>)[2] [LewisC EnterpriseDB vs. PostgreSQL](<http://blogs.ittoolbox.com/oracle/guide/archives/postgresql-vs-enterprisedb-hypocritical-crap-17648>) blog entry.

---
[View this page online](https://www.commandprompt.com/blog/for_the_record_enterprisedb_and_command_prompt_inc/)

---

# From the field: On Josh's Rules (of Database Contracting)

> Josh Berkus wrote an excellent bullet point list of things to do and not do when doing Database Contracting. I would like to expand on that list and add some c…

Josh Berkus wrote an excellent bullet point list of things to do and not do when doing [Database Contracting.](<http://networking.ittoolbox.com/r/rss.asp?url=http://blogs.ittoolbox.com/database/soup/archives/joshs-rules-of-database-contracting-17253>) I would like to expand on that list and add some comments to a couple of his points: 

  1. Data Reflects the Business: show me a client with a chronic database problem, and I'll show you a client with a chronic management problem. _Generally I would agree with this statement but remember, that is why they called you. A lot of times it isn 't a chronic management problem, but a chronic ignorance problem which I would classify as different. _
  2. Bad Clients Will Destroy Your Business: half of your success will be built on the ability of recognizing bad clients and avoiding them or terminating their contracts before they suck away all of your time and resources. Always be able to walk away. _Hands down a winner on this one. Remember that the relationship is this: Vendor <->Client It is not: Vendor->Client Keep expectations clear. _

**The following are my additions:**

  * Get a retainer. _If your client isn 't willing to pay a little upfront then walk away. There are exceptions of course, specifically Government entities and or large corporations. If you run into that, then make sure you get a purchase order._
  * Charge interest. _Require due on receipt invoices, Net-10 for qualified (customers you do business with a lot), anything and I mean anything over Net-30 is charged interest. You are not a bank. Don 't let customers treat you like one. _
  * Eliminate paper. _Don 't send out paper invoices. It takes too much time (not to mention paper, envelopes and stamps) and time is money. Use PDF to email or fax. _
  * Explore payment options. _Get a merchant account and accept e-checks. It is generally cheaper to take the 2.25% hit on a Visa charge than to wait for payment (see retainer above). If you do E-checks do *not* allow your merchant to take a percentage. There are plenty of services that charge a flat fee from .30 to .75 cents. The more convenient you make paying you, the faster you will be paid._
  * **Kill your cell phone.** _I can hear the wails of discontent on this one but I am serious. Clients do not need your cell phone number. Not even if they pay you twice what you normally get per hour. Get an answering service and the answering service gets your cell phone._
  * At 5:01pm, your rates go time and a half. _O.k., this one is variable based on your lifestyle but remember that your time is your time. If they are going to call you at 10:00pm, they should pay for the fact that they are calling you outside of normal hours._

---
[View this page online](https://www.commandprompt.com/blog/from_the_field_on_joshs_rules_of_database_contracting/)

---

# Training, hot seat style

> We have been stewing here at CMD for some time over training. Command Prompt actually does quite a bit of PostgreSQL Training. In the 12 months preceding April…

We have been stewing here at CMD for some time over training. Command Prompt actually does quite a bit of PostgreSQL Training. In the 12 months preceding April of 2007 we had taught a dozen classes on PostgreSQL. These classes have always been directed at on-site training, meaning that someone from CMD would travel to the customer site to train their employees. We did this for two reasons. One, because CMD is a widely dispersed corporation without any central location. Two, because we felt that our other training partners (namely [OTG](<http://www.otg-nc.com/>) and [Big Nerd Ranch](<http://www.bignerdranch.com>)) were better suited to classroom style training. We still believe that and thus Command Prompt, will not be offering any classroom style training in the foreseeable future. However, after speaking with many clients there appears to be a distinct lack of specific topic training. Most of our clients don't want a 4 day class on Introduction to PostgreSQL, or PostgreSQL Administration (although we teach both). Most of our clients want short, specific classes on items such as managing a backup infrastructure, understanding PostgreSQL I/O, and Tuning Autovacuum. All of which, we will be teaching this year. So what makes these classes different? The classes are short. No more than 8 hours, broken up over two days. The classes are taught virtually, using industry standard remote desktop and teleconference technologies. The classes are going to be relatively inexpensive with an 8 hour course costing higher than 100.00 but less than 500.00 (no, we haven't come up with our actual pricing strategy yet). Lastly, the name! All marketers beware, Hot Seat Training now belongs to Command Prompt, Inc. ;)

---
[View this page online](https://www.commandprompt.com/blog/training_hot_seat_style/)

---

# PostgreSQL Party July 22nd

> Command Prompt is working with the PostgreSQL community to have a PostgreSQL party on July 22nd. For those not calendar aware, that is the Sunday before OSCON …

Command Prompt is working with the PostgreSQL community to have a PostgreSQL party on July 22nd. For those not calendar aware, that is the Sunday before OSCON starts in Portland. For more information please visit [www.postgresqlparty.org](<http://www.postgresqlparty.org>).

---
[View this page online](https://www.commandprompt.com/blog/postgresql_party_july_22nd/)

---

# Education

---

# PostgreSQL - How to List All Available Tables?

> Learn how to use psql to list tables in PostgreSQL This definitive guide covers the psql \dt command, psql \d command and variations for specific schemas. List tables using postgresql information_schema, and practical examples for beginners and power users alike.

Listing tables in PostgreSQL is essential for organizing, managing, and utilizing the table’s data. For this purpose, Postgres provides different built-in commands and queries. For instance, you can gain instant access to a comprehensive list of all the tables with the “ **\dt** ” command, “ **information_schema** ”, “ **pg_tables** ”, etc. Using these commands and queries, you can get the list of tables from a specific database or list of all available tables in Postgres.

This blog will demonstrate how to get the list of all available tables in Postgres using practical examples.

 **How to List All Available Tables/Relations in Postgres?**

Let’s learn how to list all the available tables in Postgres using the following methods:

  * Method 1: Using “\dt” Command
  * Method 2: Using “\d” Command
  * Method 3: Using information_schema
  * Method 4: Using “pg_tables”



 **Method 1: Using “\dt” Command**

To list tables from all schemas, use the “\dt” command as follows:
    
    
    \dt *.*;

This command retrieves all the tables(including system and user-defined tables) from all the schemas. To get the list of tables from a specific schema, use the “\dt” command as follows:
    
    
    \dt public.*;

This time the “\dt” command will retrieve the tables from the public schema only:

Similarly, to list all the available tables of a specific Postgres database, you can use the command “\dt”. But for this purpose, firstly, you need to establish a connection with that particular database.

For instance, to list the available tables of the “example” database, firstly, we will connect to the example database using the following “\c” command:
    
    
    \c example;

Now execute the following “\dt” command to list down all the available tables of the example database:
    
    
    \dt;

The “ **\dt** ” command retrieves the list of all the tables/relations available in the selected database, i.e., “ **example** ”.

 **Method 2: Using “\d” Command**

The “\d” command can also be used to list all the available relations of a specific database. However, it will retrieve not only the tables but also the views, indexes, sequences, etc.
    
    
    \d;

The output shows that the “\d” command retrieves the list of available tables, views, sequences, etc. Using the “\d” command, you can describe all the tables available within a specific schema, as shown in the following snippet:
    
    
    \d public.*;

The output demonstrates that the “\d” command describes all the tables of the “public” schema.

 **Method 3: Using information_schema**

In Postgres, the “information_schema” can be used to list all the available tables:
    
    
    SELECT table_name
    FROM information_schema.tables;

The output shows that the information_schema retrieves all available tables. To get all the tables of some specific schema, you need to specify the name of that particular schema:
    
    
    SELECT table_name
    FROM information_schema.tables
    WHERE table_schema = 'public';

This time the “ **information_schema** ” retrieves all the tables of the public schema.

 **Method 4: Using “pg_tables”**

An alternate way of listing all tables is by querying the system catalog table called pg_tables. For this purpose, the below-provided query will be used in Postgres:
    
    
    SELECT tablename, tableowner
    FROM pg_tables 
    WHERE schemaname = 'public';

The above query retrieves all the tables of the “ **public** ” schema. Users can replace the “public” schema with the desired one to get the list of tables from that particular schema.

You can also use the “ **pg_catalog.pg_tables** ” to get the list of all the available tables from a specific database:
    
    
    SELECT tablename, tableowner
    FROM pg_catalog.pg_tables 
    WHERE schemaname != 'pg_catalog' AND 
    schemaname != 'information_schema';

Here, the WHERE clause is used to filter the user-defined tables only. If we omit the WHERE clause, then the “pg_catalog.pg_tables” will retrieve all tables, including system tables and user-defined tables:

This is how you can get the list of all the tables from a specific database.

 **Conclusion**

PostgreSQL provides different built-in commands and queries to get the list of all the tables, such as the “ **\dt** ” command, “ **pg_tables** ”, “ **information_schema** ”, etc. These commands and queries allow us to get the list of tables from a specific database, schema, or a list of all available tables in Postgres. Using examples, this blog presents a detailed overview of how to list tables in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-how-to-list-all-available-tables/)

---

# PostgreSQL BETWEEN operator, usage and examples

> Master the SQL BETWEEN operator with step‑by‑step examples. Learn its syntax, usage in Postgres queries, and how to combine it with NOT keyboard for advanced range filtering.

In PostgreSQL, the **BETWEEN** operator is used to find a match against a range of values in SELECT, UPDATE, INSERT or DELETE queries. The **BETWEEN** operator is used with the conjunction of the WHERE clause, and it returns true if the targeted match found successfully.

This write-up will show you how to use the **BETWEEN** operator in Postgres with the help of suitable examples. So, let’s start!

 **How to Use BETWEEN Operator in PostgreSQL?**

The basic syntax of the Postgres BETWEEN operator will go like this:
    
    
    expression BETWEEN val_1 AND val_2;

Let’s illustrate the above-given syntax step-by-step:

● The expression represents a column/value to be searched in the given range.

● The val_1 and val_2 represent a range in which the targeted value will be searched.

The BETWEEN operator will return true only if the targeted value/expression lies in the given range.

Let’s head into the practical implementation of the Postgres BETWEEN operator:

 **Example 1: A Basic Example of BETWEEN Operator**

We have already created a “bike_details” table. Let’s run the SELECT query to enlist all the details of the bike_details table:
    
    
    SELECT * from bike_details;

There are ten records in the bike_details table.

Let’s use the BETWEEN operator to fetch only those bikes whose price is between 100,000 and 130,000:
    
    
    SELECT * FROM bike_details
    WHERE bike_price BETWEEN 100000 AND 130000
    ORDER BY bike_id ASC;

The output shows that there are six bikes whose price is between 100000 and 130000.

 **Example 2: A Basic Example of NOT BETWEEN Operator**

The NOT BETWEEN operator in Postgres provides the contrary results as compared to the BETWEEN operator. The NOT BETWEEN operator will return all those records that did not lie in the given range.

Let’s modify example 1 a little bit and utilize the NOT BETWEEN operator instead of BETWEEN operator:
    
    
    SELECT * FROM bike_details
    WHERE bike_price NOT BETWEEN 100000 AND 130000
    ORDER BY bike_id ASC;

The NOT BETWEEN operator returned all those records that are either less than 100,00 or greater than 130,000.

 **Example 3: How to Use BETWEEN Operator With Date**

We have updated the bike_details table. We have inserted a new column named bike_launch_date. Let’s execute the SELECT query to see the updated table records:
    
    
    SELECT * FROM bike_details;

 **Note:** Always specify the date in ISO 8601 format (Year-month-day), i.e., “YYYY-MM-DD”.

Suppose we have to fetch those bikes that launched between the “2017-01-08” and “2021-01-01” then we will execute the following query:
    
    
    SELECT * FROM bike_details
    WHERE bike_launch_date BETWEEN '2017-01-08' AND '2021-01-01'
    ORDER BY bike_id ASC;

The output verifies that the BETWEEN operator fetched only those bikes whose launched date is between ‘2017-01-08’ and ‘2021-01-01’.

 **Conclusion**

The **BETWEEN** operator in PostgreSQL is used to find a match against a range of values in SELECT, UPDATE, INSERT or DELETE queries. The **BETWEEN** operator is used in conjunction with the WHERE clause, and it returns true if the desired match is found. This write-up explained several use cases of the BETWEEN operator with the help of suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-between-operator-in-postgresql/)

---

# How to Use ORDER BY Clause in PostgreSQL

> Learn to sort query results with PostgreSQL’s ORDER BY clause. This guide covers basic ASC/DESC sorting, multi‑column ordering and practical examples for SELECT statements.

In PostgreSQL, the SELECT statement returns a result-set in an unspecified order. To get the sorted rows of a result-set, PostgreSQL offers an **ORDER BY** clause. The table rows can be sorted ascendingly or descendingly with the help of the ORDER BY clause. The ASC or DESC keyword is used in the ORDER BY clause to sort the table rows in a particular order.

Let’s learn the working of the **ORDER BY** clause with examples.

 **How to Use ORDER BY Clause in PostgreSQL?**

The ORDER BY clause can sort a single or a list of columns using the comma-separated syntax:
    
    
    SELECT col_1, col_2, col_3, ..., col_N
    FROM tab_name
    ORDER BY col_1, col_2, col_3,  .. col_N [ASC | DESC];

Let’s consider the below-listed points to get a basic understanding of the ORDER BY clause:

● The SELECT statement will return a result set in an unspecified order.

● tab_name is a table whose result set will be sorted in ascending/descending order.

● The **ORDER BY** clause takes an individual column or list of columns and sorts them ascendingly or descendingly.

● A column or list of columns will be sorted according to the parameter specified in the ORDER BY clause i.e. ASC or DESC. HERE ASC represents ascending order, and DESC represents descending order.

ASC is a default option in the ORDER BY clause, so omitting it will sort the selected result set in ascending order.

 **Practical Implementation of ORDER BY Clause in Postgres**

The purpose of this section is to teach you how to sort table rows in ascending/descending order based on an individual column or several columns. A table named "bike_details" has already been created, whose details are as follows:
    
    
    SELECT * FROM bike_details;

 **Example # 1: How to Sort a Table in Ascending Order Based on a Single Column?**

Suppose we have to sort the bike_details table in ascending order based on the bike_model column. To do so, run the below-given query:
    
    
    SELECT * FROM bike_details
    ORDER BY bike_model ASC;

The above snippet proves that the ORDER BY clause sorted the result set in ascending order based on the bike_model.

 **Example # 2: How to Sort a Table in Descending Order?**

Let’s run the following query to sort the bike_details table in descending order based on the bike_id column:
    
    
    SELECT * FROM bike_details
    ORDER BY bike_id DESC;

The above snippet shows that the ORDER BY clause successfully sorted the result set in descending order with respect to the bike_id column.

 **Example # 3: How to Use ORDER BY Clause to Sort a Table by Multiple Columns in PostgreSQL?**

Let’s run the following query to sort the bike_model column in descending order and the bike_color column in ascending order:
    
    
    SELECT bike_model, bike_color
    FROM bike_details
    ORDER BY bike_model ASC, bike_color DESC;

● In this example, we utilized the **ORDER BY** clause to sort the bike_model in ascending order and bike_color in the descending order.

● So, the **ORDER BY** clause firstly sorted the rows in ascending order according to the bike_model, and afterward, it sorted the rows in descending order according to the bike_color column.

● As shown in the output, bikes with the same bike_model are sorted according to the bike_color column, i.e., in descending order.

That was all the basic information regarding the Postgres **ORDER BY** clause.

 **Conclusion**

To get the sorted rows of a result-set, PostgreSQL offers an **ORDER BY** clause. The **ORDER BY** clause in Postgres enables us to sort the table rows in ascending/descending order. To sort the result-set in a specific order, specify the ORDER BY clause and column name followed by the DESC or ASC keywords. This write-up considered several use cases of the **ORDER BY** clause and explained them with the help of suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-order-by-clause-in-postgresql/)

---

# How to Create, Update and Drop Tables in a PostgreSQL Docker Container

> To create, update and drop tables in PostgreSQL container, build and run PostgreSQL container and connect with Database Server. Then, perform these operations.

**A PostgreSQL Docker container** is a setup of the PostgreSQL database that is running within a Docker container. In PostgreSQL, a **table** is a collection of data organized or structured into rows and columns. Each row and column in a table represent a record and an attribute respectively.

Users can easily create tables, update their records, and even delete/drop tables from the PostgreSQL Docker container.

## Quick Outline

This article will demonstrate:

  *  **Prerequisite Steps for Creating, Updating, and Deleting a Table in PostgreSQL Container**
  *  **How to Create a Table in PostgreSQL Container**
  *  **How to Update Table in PostgreSQL Container**
  *  **How to Delete Table in PostgreSQL Container**



##  **Prerequisite Steps for Creating, Updating, and Deleting Table in PostgreSQL Container**

First, build and execute the PostgreSQL container via the following “ **docker run** ” command:
    
    
    docker run --name postgresCont -e POSTGRES_PASSWORD=pass123 -p 5432:5432 -d postgres

Subsequently, the “ **postgresCont** ” PostgreSQL container will be created and started:

Then, type out the below-listed command with the container name to open the shell within it:
    
    
    docker exec -it postgresCont bash

From the screenshot, it can be observed that the shell has been opened and we can run/execute SQL commands in it:

After that, establish a connection with the Postgres Database Server with the help of the below-listed command:
    
    
    psql -h localhost -U postgres

According to the below image, SQL Shell has opened where we can utilize/run PSQL commands and SQL queries:

Now, use the “ **CREATE DATABASE** ” command with the desired database name to create it. For example, we created the following database:
    
    
    CREATE DATABASE tsl_employee;

As you can see, the database has been efficiently created:

Now, connect to the recently created database using the “ **\c** ” command:
    
    
    \c tsl_employee;

It can be seen that the connection has been established:

Let’s move ahead and see how to create, update, and delete tables in the PostgreSQL Docker container.

##  **How to Create a Table in a PostgreSQL Container**

To make/create a new table in the particular database, use the “ **CREATE TABLE <table-name>(col1 <datatype>, col2 <datatype>, col3 <datatype>,....., colN <datatype>);**” command. For instance, we have made a table named “ **tech_authors** ” with some columns:
    
    
    CREATE TABLE tech_authors(
    ID INT PRIMARY KEY NOT NULL,
    NAME TEXT NOT NULL, 
    TYPETEXT NOT NULL, 
    CATEGORY TEXT NOT NULL, 
    ARTICLES INT NOT NULL);

Then, utilize the “ **INSERT INTO <table-name> VALUES (val1, val2, val3, ...);**” command for putting new values into the recently created table. Here, we have put the below-provided values:
    
    
    INSERT INTO tech_authors VALUES 
    (1, 'Laiba', 'Senior', 'Docker', 50);

Now, list table data using the below-stated command:
    
    
    SELECT * FROM tech_authors;

This command has displayed all the records of the specified table:

Moreover, if users want to view particular columns of the table, use the “ **SELECT <col_1>, <col_2>, … <col_N> FROM <table_name>**;” and specify the columns names and table name.

For instance, we want to only display the “ **ID** ”, “ **NAME** ” and “ **TYPE** ” columns from the selected table:
    
    
    SELECT ID, NAME, TYPE 
    FROM tech_authors;

The above command has retrieved the desired data from the selected columns:

##  **How to Update Table in PostgreSQL Container**

First, display the table data and select the particular record that you want to change or update:
    
    
    SELECT * FROM tech_authors;

The below output has displayed the table data. Here, we want to change the category of the user whose ID is “ **1** ”:

Let's execute the “ **UPDATE <table-name> SET <column1> = <value1>, <column2> = <value2>, … WHERE condition;**” command and specify the column name, value, and conditions. For instance, we have specified the following values and conditions:
    
    
    UPDATE tech_authors 
    SET CATEGORY= 'Linux' 
    WHERE ID=1;

Next, ensure that the column’s value has been updated using the provided command:
    
    
    SELECT * FROM tech_authors;

In the below screenshot, the highlighted part shows that the table’s value has been updated successfully:

##  **How to Delete Table From PostgreSQL Container**

In PostgreSQL, users can delete a specific record from the table, delete all records from the table, or delete the entire table. Let's see each scenario one by one:

 **Delete Specific Record from Table**

First, display the table data and choose a specific record that needs to be deleted:
    
    
    SELECT * FROM tech_authors;

Here, we want to delete the record of an entity whose ID is “ **5** ”:

Now, execute the following command and specify the ID of the entity whose record you want to delete:
    
    
    DELETE FROM tech_authors WHERE id=5;

Then, verify whether the specific record has been deleted or not by displaying the table data:
    
    
    SELECT * FROM tech_authors;

The below output indicates that the record of the specified entity has been deleted:

 **Delete All Records of Table**

Type out the “ **DELETE FROM <table_name>**” command to delete all records of the table:
    
    
    DELETE FROM   tech_authors;

For the verification, view the table data:
    
    
    SELECT * FROM tech_authors;

In the below output, no record can be seen in the table which indicates that all records of the table have been deleted successfully:

 **Delete Entire Table**

To delete an entire table, choose the desired table that you want to delete:
    
    
    \dt

For instance, we want to delete the “ **tech_authors** ” table:

Then, execute the “ **DROP TABLE <table_name>**” command to delete the table entirely:
    
    
    DROP TABLE   tech_authors;

Finally, ensure that the table has been deleted by displaying all tables:
    
    
    \dt

According to the below output, the specified table has been deleted from the database:

That was all about creating, updating, and deleting tables in the PostgreSQL Docker container.

##  **Conclusion**

A PostgreSQL Docker container enables users to run the PostgreSQL database within a particular container. For this purpose, they need to create and start a PostgreSQL container and set up a connection with the Database Server.

After establishing a connection, they can connect to the particular database and create tables, update their records, and delete tables from it. This article has efficiently demonstrated the method to create, update, and delete tables in the PostgreSQL docker container.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-update-and-drop-tables-in-a-postgresql-docker-container/)

---

# What’s the Difference Between HAVING Clause and WHERE Clause in PostgreSQL?

> In PostgreSQL, the WHERE clause filters the data of each row and then groups the data while the HAVING clause filters the grouped data.

The "WHERE" and "HAVING" clauses in PostgreSQL let us filter the table’s data. Both these clauses retrieve only those rows that satisfy the specified condition. However, both these clauses are distinct and are used for different purposes. The primary difference is that the "WHERE" clause filters the data of each row and then groups the data while the "HAVING" clause filters the grouped data.

This write-up will illustrate the difference between the "WHERE" and "HAVING" clauses along with syntax and suitable examples.

##  **PostgreSQL WHERE CLause**

A "WHERE" clause filters a result set before grouping the data. This means the "WHERE" clause first filters the data based on the specified condition and then groups the filtered data.

The following syntax is used to execute the "WHERE" clause in PostgreSQL:
    
    
    SELECT column_list
    FROM table_name
    WHERE filter_condition
    GROUP BY column_name;

 **Sample Table:**

Let’s see how the "WHERE" clause works in PostgreSQL using the following example:
    
    
    SELECT car_model, SUM (car_price)
     FROM cars_info
     WHERE car_price >= 1500000
     GROUP BY car_model;

In this example,

\- We use the "SELECT" query to fetch the "car_model" and sum of "car_price" from the "cars_info" table.

\- Next, we use the "WHERE" clause to filter the table’s data based on the car's price (i.e., car_price >= 150000).

After this, we employ the "GROUP BY" clause to group the table’s records based on the car model.

From the output, it is clear that the "WHERE" clause gets executed first and the table’s data is filtered accordingly. After this, the "GROUP BY" clause executes and groups the data according to the car model.

##  **PostgreSQL HAVING CLause**

PostgreSQL offers a "HAVING" clause that lets us filter a result set based on the specified condition. It filters the table’s data as a group. This clause was introduced in SQL because the "WHERE" clause can’t be used with the aggregate functions.

To use the "HAVING" clause in PostgreSQL, follow the below-mentioned syntax:
    
    
    SELECT column_list, aggregate_function
     FROM tab_name
     GROUP BY column_name
    HAVING filter_condition;

Let’s see how the "HAVING" clause works in PostgreSQL using the following example:
    
    
    SELECT car_model, SUM (car_price)
     FROM cars_info
     GROUP BY car_model
     HAVING SUM(car_price) >= 1500000;

In this code,

\- After fetching the car’s model and the sum of the car’s price we grouped the table’s data according to the car’s model.

\- In the next line, we use the "HAVING" clause with the SUM function to filter the table’s data based on the condition “sum of car_price must be greater than or equal to 1500000”.

From the output, you can observe that the "GROUP BY" clause executes first and it groups the table’s data according to the car’s model. After this, the data is filtered according to the grouped data, instead of each row.

##  **PostgreSQL HAVING Vs WHERE Clause - What’s the Difference?**

Here are some notable differences between the PostgreSQL "HAVING" and "WHERE" clauses:

  * The "WHERE" clause/keyword filters each table row before grouping while the "HAVING" clause filters the grouped data.
  * PostgreSQL runs "WHERE" before "GROUP BY" while "HAVING" is executed after the "GROUP BY".
  * In PostgreSQL, aggregate methods are not permitted in the "WHERE" clause.
  * The "HAVING" clause is most commonly used to filter groups based on aggregate functions, but it can also be used without aggregate functions.
  * If the "HAVING" clause is used without an aggregate function, it works similarly to the "WHERE" clause in filtering data.



##  **Conclusion**

In PostgreSQL, the "WHERE" and "HAVING" clauses are used to filter the result set of the "SELECT" query. However, the "WHERE" clause can’t be used with the aggregate functions while the "HAVING" clause can be used with any aggregate function.

Moreover, the "HAVING" clause filters the grouped data while the "WHERE" clause filters every single row before grouping the data. This post used suitable examples to discuss how the "HAVING" clause differs from "WHERE".

---
[View this page online](https://www.commandprompt.com/education/difference-between-having-where-clause-postgresql/)

---

# PostgreSQL Cheat Sheet - Basic Commands

> This blog presented a cheat sheet that assists us in working with the Postgres databases, schemas, tables, and users/roles, efficiently.

PostgreSQL is an advanced, open-source, highly stable relational database that extends the standard SQL language. It offers a variety of features, such as user-defined types, Point-in-time recovery, table inheritance, and many more. Due to its extensive features, PostgreSQL has become most developers' first choice.

PostgreSQL offers various commands/statements to work with databases, schemas, tables, roles, etc. This blog post will cover the basics of PostgreSQL concerning the below-listed concepts:

  * PostgreSQL Databases - Cheat Sheet
  * PostgreSQL Schemas - Cheat Sheet
  * PostgreSQL Table - Cheat Sheet
  * PostgreSQL Views - Cheat Sheet
  * PostgreSQL Users - Cheat Sheet
  * PostgreSQL Indexes - Cheat Sheet



So, let’s start with the database operations!

##  **PostgreSQL Databases - Cheat Sheet**

A database in Postgres is the topmost hierarchical level for managing database objects, like tables, views, indexes, etc. We can perform various operations on a database, such as create, alter, drop, etc. For this purpose, different commands are used.

 **Create Database**

To [create](<https://www.commandprompt.com/education/how-to-create-a-database-in-postgresql/>) a new database in Postgres, use the **CREATE DATABASE** command followed by the database name to be created:
    
    
    CREATE DATABASE db_name;

 **Access/Connect Database**

To connect to a databases, execute the “ **\c** ” command(from psql) followed by the database name:
    
    
    \c db_name;

 **Drop Database**

To drop a database, use the **DROP DATABASE** command, as follows:
    
    
    DROP DATABASE db_name;

 **Alter Database**

To alter a database, use the **ALTER DATABASE** command. Using this command, you can change the database owner, rename the database, change database attributes, etc.

 **Change Database Owner**

To change the database owner, users need to execute the **ALTER DATABASE** command as follows:
    
    
    --To Change Database Owner
    ALTER DATABASE db_name
    OWNER TO new_owner_name | current_user |current_role | session_user;
    
    --To Rename a Database
    ALTER DATABASE old_db_name 
    RENAME TO new_db_name;
    
    --To Alter a Tablespace
    ALTER DATABASE db_name
    SET TABLESPACE new_tablespace_name;
    
    -- To Alter Database Attributes
    ALTER DATABASE db_name
    WITH option;
    
    -- To Alter Configuration Variables
    ALTER DATABASE db_name
    SET configuration_parameter = value;
    
    -- To RESET Configuration Parameter
    ALTER DATABASE db_name
    RESET configuration_parameter; 
    
    -- To List all Databases
    \l

##  **PostgreSQL Schemas - Cheat Sheet**

Postgres provides different commands to work with schemas, such as CREATE SCHEMA, DROP SCHEMA, etc.

 **Create Schema**

To create a schema, use the **CREATE SCHEMA** statement as follows:
    
    
    CREATE SCHEMA [IF NOT EXISTS] new_schema;

 **Drop Schema**

To drop a schema, run the **DROP SCHEMA** statement with one of the following options:
    
    
    DROP SCHEMA schema_name 
    [RESTRICT | CASCADE];

 **Alter Schema**

The ALTER SCHEMA command is used in Postgres to modify the schema’s definition. This command/statement allows us to rename a schema, change the schema’s owner, etc.
    
    
    --To Rename a Schema
    ALTER SCHEMA schema_name 
    RENAME TO new_schema_name;
    
    --To Change Schema Owner
    ALTER SCHEMA schema_name
    OWNER TO{ new_owner_name | SESSION_USER | CURRENT_USER};
    
    --TO Show All Available Schemas
    \dn

##  **PostgreSQL Tables - Cheat Sheet**

Postgres offers several commands to perform different table operations, such as creating a table, dropping a table, selecting a table’s data, etc.

 **Create Table**

To create a new table, run the CREATE TABLE statement followed by the table name to be created, as follows:
    
    
    CREATE TABLE [IF NOT EXISTS] tab_name (
    column_name DATATYPE column_contraint,
    );

“IF NOT EXISTS” is an optional clause that creates a new table only if it doesn’t exist already. Specify the column names followed by their respective data types and constraints.

 **Drop Table**

To drop a table in Postgres, run the DROP TABLE statement with the following syntax:
    
    
    DROP TABLE [IF EXISTS] tab_name 
    [RESTRICT | CASCADE];

“ **IF EXISTS** ”, “ **RESTRICT** ”, and “ **CASCADE** ” are optional clauses. The “ **IF EXISTS** ” option drops a table if it already exists, the **RESTRICT** option denies the table deletion in case some objects depend on it, while the **CASCADE** option deletes a table along with its dependent objects.

 **Alter Table**

To modify the table’s definition in Postgres, run the ALTER TABLE command as follows:
    
    
    --To Rename a Table
    ALTER TABLE tab_name
    RENAME TO new_tab_name;
    
    --To Add new Columns
    ALTER TABLE tab_name
    ADD COLUMN new_col_name data_type constraint;
    
    --To Drop a Table Column
    ALTER TABLE tab_name
    DROP COLUMN col_name;
    
    --To Add a Constraint to a Table
    ALTER TABLE tab_name
    ALTER COLUMN col_name SET constraint_name;
    
    --To Drop/Remove a Constraint
    ALTER TABLE tab_name
    ALTER COLUMN col_name DROP constraint_name;
    
    --To Alter Column Data Type
    ALTER TABLE table_name
    ALTER COLUMN column_name TYPE new_data_type;
    
    --To Rename Table Columns
    ALTER TABLE tab_name
    RENAME COLUMN old_col_name TO new_col_name;
    
    --To Add a Primary Key
    ALTER TABLE tab_name 
    ADD PRIMARY KEY col_name;
    
    --To Remove a Primary Key
    ALTER TABLE tab_name 
    DROP CONSTRAINT primary_key_constraint_name;

 **Fetch the Table’s Data**

To fetch the table’s data, use the SELECT command, as follows:
    
    
    --To Fetch All Columns
    SELECT * FROM tab_name;
    
    --To Fetch Specific Columns
    SELECT col_1, col_2, ...
    FROM tab_name;

 **Insert Data Into a Table**

To insert data into a table, use the INSERT INTO query as follows:
    
    
    INSERT INTO tab_name(col_list)
    VALUES (value_list);

 **Delete Table Records**

To delete records from a table, run the following query:
    
    
    --To Delete all Records
    DELETE FROM tab_name;
    
    --To Delete Specific Records
    DELETE FROM tab_name
    WHERE condition;

 **List Tables**

To list all available tables, run the “\dt” command from SQL Shell, like this:
    
    
    \dt

##  **PostgreSQL Views - Cheat Sheet**

In PostgreSQL views are the virtual tables that are used to simplify complex queries. Postgres supports different types of views, such as materialized views, recursive views, etc. We can create, alter, or remove a view using different commands.

 **Create a View**

To create a new view in Postgres, run one of the following CREATE VIEW statements:
    
    
    --To Create a Standard View
    CREATE OR REPLACE viewName AS
    query;
    
    --To Create a Recursive View
    CREATE RECURSIVE VIEW viewName(col_list) AS
    SELECT col_list;
    
    --To Create a Materialized View
    CREATE MATERIALIZED VIEW viewName 
    AS
    query
    WITH <NO> DATA;
    
    --To refresh a Postgres MATERIALIZED view
    REFRESH MATERIALIZED VIEW CONCURRENTLY viewName;

 **Drop a View**

To drop a view run the below-given commands:
    
    
    DROP VIEW <IF EXISTS> viewName;
    --To drop a materialized view
    DROP MATERIALIZED VIEW viewName;

 **Rename a View**

To rename a Postgres view, execute the following command:
    
    
    ALTER VIEW viewName RENAME TO new_viewName;

##  **PostgreSQL Users - Cheat Sheet**

PostgreSQL users manage the database access and privileges. We can create new users, alter them when needed, or even drop them (when no longer needed).

 **Create User**

To create a user in PostgreSQL, use the **CREATE ROLE or CREATE USER** command followed by the role/user name to be created:
    
    
    CREATE USER use_name 
    WITH option;

Any privilege of your choice, such as SUPERUSER, LOG-IN, CREATEDB, CREATEROLE, CONNECTION LIMIT, PASSWORD, VALID UNTIL, etc., can replace the option.

 **Create Superuser**

To create a superuser, run the CREATE USER statement along with the SUPERUSER attribute, as follows:
    
    
    CREATE USER user_name 
    WITH SUPERUSER;

 **Drop User**

To drop any particular user in Postgres, specify the **DROP USER** statement followed by the user name to be dropped:
    
    
    DROP USER [IF EXISTS] user_name;

 **Find Users**

To find the users in PostgreSQL, fetch the “usename” column of the “pg_user” table using the **SELECT** query, as follows:
    
    
    SELECT usename, usesysid
    FROM pg_user;

 **Find Logged in Users**

To find the currently logged-in Postgres users, use the SELECT query with a system view named **“pg_stat_activity”** , as shown below:
    
    
    SELECT DISTINCT usename, usesysid
    FROM pg_stat_activity;

 **List Users**

Execute the “\du” or “\du+” commands from the SQL Shell to find the list of users:
    
    
    \du;

 **Alter Users**

To change the user’s definition, use the ALTER USER command with the suitable clause, as seen in the following snippet:
    
    
    --To Rename a User
    ALTER USER user_name
    RENAME TO new_user_name;
    
    --To Change User Password
    ALTER USER user_name
    WITH PASSWORD 'updated_password';
    
    --To Change Password Validity Date
    ALTER USER user_name
    WITH PASSWORD 'updated_password'
    VALID UNTIL 'expiry_date_time';
    
    --To Change a Normal User to a Superuser
    ALTER USER existing_user_name
    WITH SUPERUSER;
    
    --To Alter User Permissions
    ALTER USER user_name
    WITH user_privileges;

##  **PostgreSQL Indexes - Cheat Sheet**

Indexes improve the efficiency of the PostgreSQL database by finding and retrieving a table record quickly. To create an index in Postgres, simply employ the following syntax:
    
    
    CREATE [UNIQUE] INDEX indexName
    ON tableName (column_list);

Similarly, you can drop/remove an index using its name, as shown below:
    
    
    DROP INDEX indexName;

That’s all from this Postgres blog.

##  **Conclusion**

PostgreSQL offers a wide range of commands to work with databases, schemas, tables, and users/roles. For instance, CREATE command creates a database, schema, table, or a role/user; the ALTER command modifies a database, schema, table, or a user/role, etc. This blog presented a cheat sheet that assists us in working with the Postgres databases, schemas, tables, and users/roles, efficiently.

---
[View this page online](https://www.commandprompt.com/education/postgresql-cheat-sheet-databases-schemas-tables-users/)

---

# PostgreSQL Pattern Matching: LIKE VS NOT LIKE VS ILIKE

> The LIKE operator matches the search expression with the specified pattern and retrieves true if the match is found. The NOT LIKE operator negates the results …

In PostgreSQL, **LIKE, NOT LIKE,** and **ILIKE** operators are used along with the wildcards to perform the pattern matching. Two types of wildcards are used to specify a pattern: a percentage sign **“%”** and an underscore sign “_”. The percentage wildcard "%" matches sequences of characters, while the underscore "_" matches a single character.

## Quick Outline

This write-up will teach you the difference between LIKE, ILIKE, and NOT LIKE operators in PostgreSQL using the following outlines:

  *  **What is a LIKE Operator and How Does it Work in PostgreSQL?**
  *  **What is ILIKE Operator and How Does it Work in Postgres?**
  *  **What is a NOT LIKE Operator and How Does it Work?**
  *  **Wrap Up**



So, let’s begin!

##  **What is a LIKE Operator and How Does it Work in PostgreSQL?**

The **LIKE** operator matches the search expression with the specified pattern and retrieves true if the match is found. The LIKE operator is case sensitive, which means it considers “ABC” and “abc” two different strings and hence retrieves false in such a case.

Use the below-specified syntax to perform text matching using the **LIKE** operator:
    
    
    SELECT FROM tableName
    WHERE col_name LIKE pattern;

Use the wildcards to specify a pattern of your choice in place of a pattern.

> Read our dedicated guide on Wildcards in PostgreSQL to learn more about wildcards.

###  **Example 1: How Does the LIKE Operator Work?**

We have created a table named “article_info”, whose data is shown in the following snippet:
    
    
    SELECT * FROM article_info;

We will utilize the percent wildcard with the LIKE operator to find a substring “Function” from the article_title column:
    
    
    SELECT article_title 
    FROM article_info
    WHERE article_title LIKE '%Function%';

The output snippet proves that two titles in the “artile_info” table contain a substring “Function”.

###  **Example 2: Is the LIKE Operator Case-Sensitive?**

The LIKE operator is case-sensitive, so it will retrieve false if the perfect match is not found:
    
    
    SELECT article_title 
    FROM article_info
    WHERE article_title LIKE '%function%';

The specified substring "Function" exists in the targeted table; however, the LIKE operator retrieved no record for the specified pattern "%function%". This means the LIKE operator is case-sensitive.

##  **What is ILIKE Operator and How Does it Work in Postgres?**

The ILIKE operator matches the search expression with the given pattern irrespective of the letter case. Use the below-specified syntax to perform text matching using the **ILIKE** operator:
    
    
    SELECT FROM tab_name
    WHERE col_name ILIKE pattern;

###  **Example: How Does the ILIKE Operator Work?**

Let’s implement the ILIKE operator on the same previous example and see how it works:
    
    
    SELECT article_title 
    FROM article_info
    WHERE article_title ILIKE '%function%';

The output snippet proves that the “ILIKE” operator retrieves the data irrespective of the letter case.

##  **What is a NOT LIKE Operator and How Does it Work?**

The **NOT LIKE** operator negates the results of the **LIKE** operator, which means the NOT LIKE operator will retrieve false if the match is found and true if the match is not found in the string.

Use the below-specified syntax to perform text matching using the **NOT LIKE** operator:
    
    
    SELECT FROM tableName
    WHERE columnName NOT LIKE pattern;

Use the wildcards to specify a pattern of your choice in place of a pattern.

###  **Example: How Does the NOT LIKE Operator Work?**

In this example, we will use the NOT LIKE operator instead of the LIKE operator to find all those strings that don’t have the “Function” substring in the article_title column:
    
    
    SELECT article_title 
    FROM article_info
    WHERE article_title NOT LIKE '%Function%'

The output shows that the NOT LIKE operator retrieves all the strings other than those that contain a substring “Function”.

##  **Wrap Up**

The **LIKE** operator matches the search expression with the specified pattern and retrieves true if the match is found. The **NOT LIKE** operator negates the results of the **LIKE** operator, which means the NOT LIKE operator will retrieve false if the match is found and true if the match is not found in the string. The LIKE operator is case-sensitive while the ILIKE operator matches the search expression with the given pattern irrespective of the letter case. This write-up explains how to use the LIKE, NOT LIKE, and ILIKE operators in Postgres to perform pattern matching.

---
[View this page online](https://www.commandprompt.com/education/postgresql-pattern-matching-like-vs-not-like-vs-ilike/)

---

# How to Connect PostgreSQL to Java Using JDBC

> To connect PostgreSQL to Java via JDBC, integrate Postgres JDBC Driver with Java, and establish a new connection. After this, you can execute PostgreSQL Querie…

Postgres JDBC is a freely available API that allows us to connect Java with the PostgreSQL database. You can download its JAR file or use its maven dependency to integrate PostgreSQL with Java. After this, you can connect the PostgreSQL database with Java and execute PostgreSQL queries from a Java application.

In this guide, we’ll show you a step-by-step implementation of connecting a PostgreSQL database with a Java application.

##  **How to Connect PostgreSQL to Java Using JDBC**

To connect PostgreSQL to Java via JDBC, simply follow the below-mentioned steps:

  1. Integrate PostgreSQL JDBC Driver with Java
  2. Connect PostgreSQL With Java
  3. Run PostgreSQL Queries From Java



###  **Step1: Integrating Postgres JDBC Driver with Java Project**

First, integrate the JDBC driver within a Java project. We can do this by integrating a JAR file or using a Maven dependency.

###  **1) Using Maven Dependency**

The most convenient way of integrating PostgreSQL to Java is by adding the Maven dependency:
    
    
    <dependency>
     <groupId>org.postgresql</groupId>
     <artifactId>postgresql</artifactId>
     <version>42.7.3</version>
    </dependency>

###  **2) Using JAR File**

First, download the JDBC’s JAR file from [PostgreSQL’s website](<https://jdbc.postgresql.org/download/>). After this, create a Java application and embed the downloaded JAR file into your Java application. For this purpose, right-click on your Java application from the left pane and select the “Properties” option:

Now click on the “Libraries” tab and finally click on the “Add External JARs…” button. Upon clicking the “Add External JARs…” button, a new window pops up, select the downloaded JAR file, and click on the open button:

In the end, click on the “Apply and Close” button to complete the process:

###  **Step 2: Connect PostgreSQL With Java**

Once PostgreSQL is integrated with Java, establish a connection between PostgreSQL and Java using the below code snippet:
    
    
    import java.sql.*;
      public class PostgresJavaConnection {
       public static void main(String[] args) throws ClassNotFoundException, SQLException {
      String connect = "jdbc:postgresql://localhost:5432/postgres";
      String user = "postgres";
      String pwd = "postgres12345";
      Class.forName("org.postgresql.Driver");
      try (Connection conn =   DriverManager.getConnection(connect, user, pwd)) {
      System.out.println("PostgreSQL   has been Successfully Connected With Java!");
      } catch (SQLException exc) {
      exc.printStackTrace();
      }
     }
    }

In this code

\- First, we import all classes/interfaces from the “java.sql” package.

\- Next, we create string-type variables to specify a connection string, username, and password.

\- After this, we use the “forName()” method to register the JDBC driver.

\- Finally, we invoke the “getConnection()” method to establish a successful connection between Java and Postgres.

 **Output**

The output confirms that a connection has been established between PostgreSQL and Java:

###  **Step 3: Executing Select Query**

Now we are all set to execute database query from Java. In this example, we’ll show you how to execute a SELECT query from Java:
    
    
    Statement sql_statement =   conn.createStatement();
    ResultSet table = sqlStatement.executeQuery("SELECT * FROM   bike_details");
     while (table.next())   {
     String tableCol= table.getString("bike_number");
    System.out.println("Bike Number = " +   tableColumns);
    }

In this code,

\- We invoke the “createStatement()” method to send SQL queries to the PostgreSQL database.

\- After this, we call the executeQuery() method to run the SELECT query. As a result, the SELECT query will retrieve data from the bike_details table.

\- After this, we wrap the “next()” method within the while loop to iterate each record of the “bike_details” table.

\- In the end, we print each table record on the console:

###  **Step 4: Creating a New Table**

In this example, we’ll show you how to create a new PostgreSQL table from Java:
    
    
    Statement sql_statement =   conn.createStatement();
       String createNewTable = "CREATE TABLE cp_table ("
      + "cp_id serial PRIMARY KEY,"
      + "cp_title TEXT,"
      + "published_articles TEXT,"
      + "cp_email VARCHAR(255))";
       sql_statement.execute(createNewTable);
       System.out.println("Table Created!");

In this code,

\- We execute an SQL statement “CREATE TABLE” to create a new table named “cp_table” with four columns.

\- After this, we pass this SQL query as an argument to the execute() method to run this statement from Java.

\- Finally, a message will be printed on the console stating “Table Created!”.

Similarly, we can run any PostgreSQL command/query from Java to execute several database operations.

##  **Final Thoughts**

JDBC is a freely available driver that lets us connect PostgreSQL with Java. To do this, we can download the JAR file of JDBC and add it to the build path of our Java project.

Alternatively, we can create a Maven project, and add the Postgres JDBC dependency in its pom.xml file. Doing this will integrate the Postgres database with Java programming. Next, we can invoke the getConnection() method to connect PostgreSQL with Java.

After this, we can execute any PostgreSQL query from Java to perform different database operations.

---
[View this page online](https://www.commandprompt.com/education/connect-postgresql-java-jdbc/)

---

# PostgreSQL LENGTH() Function With Practical Examples

> The Postgres LENGTH() function accepts a string as an argument and calculates the total number of characters in that particular string.

PostgreSQL offers several built-in string functions to calculate the string’s length, for example, the **BIT_LENGTH(), CHAR_LENGTH(),** etc. Among them, the most popularly used function is the **LENGTH()** function which takes a string and retrieves its total length. For instance, passing "hello" to the LENGTH() function will return "5", indicating that the input string has five characters.

The purpose of this blog post is to demonstrate how to get the string's length in Postgres using the LENGTH() function. So, let’s get started.

##  **How Does the LENGTH() Function Work in PostgreSQL?**

The Postgres **LENGTH()** function accepts a string as an argument and calculates the total number of characters in that particular string. It retrieves an integer value indicating the total length of the **LENGTH()** function. In order to use the **LENGTH()** function in Postgres, users must follow the following syntax:
    
    
    LENGTH(‘str’);

Here, str represents a string whose length needs to be calculated.

Practicing a concept is the best way to understand it. So, let’s do it.

###  **Example 1: How to Use LENGTH() Function in Postgres?**

This particular example will show the practical usage of the LENGTH() function in Postgres:
    
    
    SELECT LENGTH('Welcome to commandprompt.com, the best site for Postgres Tutorials');

The output shows that the LENGTH() function retrieves the total length of the input string, including spaces and separators:

###  **Example 2: How to Use LENGTH() Function On Tables Data?**

This example is going to teach you how to use the **LENGTH()** function on a particular table. For this purpose, either you must have an existing table in your database, or you can create a new one. We already have some tables, so we are going to use one of them, i.e., “article_details”:
    
    
    SELECT * FROM article_detials;

The selected table has twelve records in it. Let’s utilize the **LENGTH()** function on the “article_title” column to find the character length of each title:
    
    
    SELECT article_title, LENGTH(article_title)
    FROM article_details;

The output snippet indicates that the LENGTH() function retrieves the length of each title:

###  **Example 3: How to Use LENGTH() Function With WHERE Clause?**

We can use the **LENGTH()** function with the collaboration of the **WHERE** clause to fetch only those strings that meet the length criteria:
    
    
    SELECT article_title, LENGTH(article_title)
    FROM article_details
    WHERE LENGTH(article_title) >= 25;

The WHERE clause is used in the above query to filter the article titles based on their character length. Only those titles will be fetched whose length is greater than or equal to 25:

The output shows that there are only two article titles whose length is greater than or equal to 25.

 **Example 4: How to Use BIT_LENGTH() and CHAR_LENGTH() Functions in PostgreSQL?**

We can also use the BIT_LENGTH() and CHAR_LENGTH() methods to compute the string length. The BIT_LENGTH() retrieves the total bits of the given string while the CHAR_LENGTH() method retrieves the total characters specified in the given string:
    
    
    SELECT BIT_LENGTH('Welcome to commandprompt.com, the best site for Postgres Tutorials'),
    CHAR_LENGTH('Welcome to commandprompt.com, the best site for Postgres Tutorials');

That's all about getting string length in Postgres using LENGTH() method.

##  **Conclusion**

The Postgres **LENGTH()** function takes a string as an argument and computes the total number of characters in that particular string. As a result, it retrieves an integer value, which represents the total length of the string passed to the **LENGTH()** function. Users can use the **LENGTH()** function with the collaboration of the **WHERE** clause to fetch only those strings that meet the length criteria. This blog post demonstrated the working of the LENGTH() function via practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-length-function-examples/)

---

# How to Show Databases in PostgreSQL

> In PostgreSQL, the “\l” command and “pg_databases” catalog are used to show the list of databases. Use the “\l+” command to show databases with more details.

Different database management systems adopt different approaches to show the list of available databases. For instance, to show the list of databases, the **“SHOW DATABASES”** statement is used in MySQL and MariaDB. However, this statement is not supported by Postgres. Instead, Postgres offers various other alternative approaches to show the available databases, such as **“\l”** , ** "pg_databases"** catalog, etc.

This write-up will teach you how to show databases in PostgreSQL via SQL Shell and pgAdmin. So, let’s get started.

##  **How to Show Databases in Postgres Using SQL Shell?**

Use the **“\l”** command from the SQL Shell to get the list of available databases. To achieve this purpose, use the following syntax:
    
    
    \l

>  **Important:** Don not specify a semi-colon at the end of the "\l" meta-command; otherwise, you may encounter an invalid command error.

 **Step 1: Launch SQL Shell**

In order to run the “\l” command, firstly, you need to log into SQL Shell. To do so, launch the SQL Shell(psql) from the Windows start menu:

Clicking on the “open” will show the following interface:

Fill in all the necessary details and hit the “ENTER” button. Consequently, the following window will appear:

Here, “postgres” shows that you are connected to the default database.

 **Step 2: Show Databases Using \l Command**

Once you are connected to the default database, execute the below-given statement to show the list of available databases:
    
    
    \l

The output authenticates the working of the “\l” command as it shows the list of available databases. Use the “\l+” command to get the list of available databases with more details such as size, tablespace, description, etc.

 **Step 3: Show Databases Using pg_databses**

In PostgreSQL, the pg_databses catalog holds all the details regarding databases. So, you can run the SELECT query in PostgreSQL to show the list of available databases in pg_databases:
    
    
    SELECT datname FROM pg_database;

>  **Note:** You can execute this query from pgAdmin's query tool to get the same result.

##  **How to Show Databases in Postgres Using pgAdmin?**

pgAdmin is a feature-rich Postgres administration and development tool that lets us perform different database operations conveniently. We can not execute the "\l" meta-command from pgAdmin, however, we can use the pg_database catalog to get the list of available databases. Also, we can use pgAdmin manually to show the available databases in Postgres.

Follow the below-listed stepwise instructions to get the list of available databases in Postgres via pgAdmin.

 **Step 1: Launch pgAdmin**

Open the pgAmin 4 from the Windows start menu:

Clicking on the “ **open** ” will lead you to the following interface:

Provide the password and hit the “OK” button to log into the pgAdmin.

 **Step 2: Show Databases Using Database Tree**

Expand the “ **Servers** ” tree located in the top left corner of the pgAdmin:

Click on “Databases” to see the list of databases:

Now select the properties tab to see detailed information about each database:

The above snippet shows detailed information about each database.

##  **Conclusion**

In PostgreSQL, the **“\l”** meta-command and **“pg_databases”** catalog are used to show the list of databases. The **“\l+”** command is used to get the list of available databases with more details such as size, tablespace, description, etc. Use the **“\l”** or **“\l+”** commands and the **“pg_databases”** catalog from the SQL Shell to get the list of available databases. While to show the list of databases using pgAdmin, click on the **“Servers”** , expand the **“Databases”** Tree, and then click on the **“properties”** tab. This write-up explained various methods to show databases in Postgres.

---
[View this page online](https://www.commandprompt.com/education/show-databases-postgresql/)

---

# How to Create a Database in PostgreSQL

> A Postgres database can be created using “CREATE DATABASE” or “createdb” commands. The difference is that the “createdb” can be executed from the command promp…

The initial step to get started with any database management system is to learn how to create a database. **PostgreSQL** , a feature-rich and globally used database, offers several ways to create a new database. It allows users to create a database using SQL queries as well as using a graphical user interface (GUI).

Once a database is created, you can perform any specific operation on that database like creating tables, views, sequences, performing crud operations, and so on.

This article explains multiple ways of creating a database in PostgreSQL.

  *  **How to Create a Database Via "CREATE DATABASE"**
  *  **How to Create a Database Via "createdb"**
  *  **Create a Postgres Database Manually via GUI/pgAdmin**
  *  **CREATE DATABASE Vs. createdb - What 's the Difference**
  *  **Final Thoughts**



So, let’s get started!

##  **How to Create a Database Via "CREATE DATABASE"**

In PostgreSQL, the **“CREATE DATABASE”** statement is used to create/make a new database. For this purpose, the basic syntax is tailored as:
    
    
    CREATE DATABASE databasename;

Let’s have a look at the below-listed points to understand what we have learned from the above snippet:

  * The **“CREATE DATABASE”** is a predefined command to create a database and the **“databasename”** is a user-defined database name.
  * From the above-given snippet, we can observe that the command is written in uppercase while the database name is written in lowercase.
  * We can write the command in lowercase as well. However, it is preferred to use the uppercase syntax for reserved keywords/commands and lowercase (or camel case) syntax for the user-defined names/attributes.



 ** _Important:_** _To create a database, you must be a superuser, or you must have "create database" privileges._

>  **Note:** To create a **PostgreSQL** database, we will execute the **“CREATE DATABASE”** command from the psql(SQL Shell). You can execute the same command from pgAdmin's query tool to create a database.

###  **How to List the Databases?**

Open the **psql** (SQL Shell) and execute the **“\l”** command to see the list of all databases:
    
    
    \l

From the above-given snippet, we can observe that by default, we have three databases **“postgres”** , **“templete0”** , and **“template1”**.

###  **Creating a New PostgreSQL Database**

You can type the below-given command in the **psql** to create a user-defined database named **“example”** :
    
    
    CREATE DATABASE example;

The response verifies that the database has been created successfully. Also, we can verify database creation by executing the **“\l”** command:
    
    
    \l

##  **How to Create a Database Via "createdb"?**

In PostgreSQL, you can use the **“createdb”** command to create/make a new database. You can run the "createdb" command directly from the Command Prompt, unlike the **“CREATE DATABASE”** command. The **“createdb”** command can add some comments/descriptions to the database altogether.

The basic syntax of the **createdb** command will go like this:
    
    
    createdb [argument/option...] [databaseName [description]]

Let’s consider the below-listed points for a profound understanding of the createdb command:

  *  **createdb:** it is a command that creates a new database in **PostgreSQL**.
  *  **option:** it represents a list of command-line arguments that a createdb command can accept.
  *  **databaseName:** it is a user-defined database name.
  *  **description:** it associates an optional comment/description with the newly created database.



###  **Command-line Options/arguments**

You can use any of the below-illustrated command line arguments with the createdb command to create a database with a specific purpose:

  *  **" –help":** It is used to get help regarding createdb arguments from SQL Shell.
  *  **" -D":** It is used to specify the tablespace for a new database.
  *  **" -e":** It displays all the commands sent to the server by the createdb command.
  *  **" -E":** It defines the character encoding to be applied in the database.
  *  **" -h":** It shows the server’s hostname.
  *  **" -I ":** It determines which locale will be used in the database.
  *  **" -O":** It specifies the user who will own the database.
  *  **" -p":** It specifies the TCP port that a server utilizes to listen for the connections.
  *  **" -T":** It specifies which database will be used as a template to generate a fresh database. If you didn’t specify the -T argument, then by default, a new database will be created using the “template1”.
  *  **" -U":** It specifies which user name to be used for the connection.
  *  **" -w"** Restricts createdb command to skip the password prompt.
  *  **" -W":** Restricts the createdb command to ask for the password before establishing a connection to a database.



Let’s jump into the practical implementation of the createdb command.

###  **How Does the createdb Command Work in PostgreSQL?**

Firstly, go to the directory where **PostgreSQL** is installed and copy its bin directory’s path. After that, open the Command Prompt and go to the bin directory of PostgreSQL using the **“cd”** command:

Once you are in the bin directory, execute the **“createdb”** command to create a new database:
    
    
    createdb -U postgres exampledb;

In this example, we utilized the **“createdb”** command followed by the **-U** argument that will create a database using the default user i.e. **“postgres”**. While **“exampledb”** is the user-defined name for the database:

>  ** _Note:_** _When we executed the above-given command, it asked for the password of the_ **_“postgres”_** _user. We entered the password and pressed the enter button to create the database._

Let’s verify whether the database has been created or not using the following command:
    
    
    \l

##  **Create a Postgres Database Manually via GUI/pgAdmin**

pgAdmin is a GUI-based tool for Postgres that is open-source and freely available for different platforms like Windows, MacOS, etc. It can be used to create a new database with or without executing any query. Follow the below-provided steps to create a new database without executing any SQL queries:

###  **Step 1: Locate Databases Tab**

Launch the pgAdmin, and navigate to the "databases" section under the servers, as shown below:

###  **Step 2: Create Database**

Right-click on the database tab to open the menu, hover over the "create" option, and click the "create database..." option:

Upon doing so, a new window will pop up asking you to provide database details like its name, owner, etc. Specify the required details and hit the "Save" button:

###  **Step 3: Verify Database Creation**

Now verify the database creation by simply navigating to the "Databases" section and listing down the available databases:

The newly created database can be seen in the list of available databases.

>  **Important:** Have you ever encountered a "database databaseName already exists" error while creating a database? No worries! you can fix it by following the linked guide.

##  **CREATE DATABASE Vs. createdb - What 's the Difference?**

The difference between these commands is that the “createdb” command can run directly from the command prompt while “CREATE DATABASE” cannot. Moreover, createdb can add some comments/descriptions to the database altogether.

##  **Final Thoughts**

 **To create a database in PostgreSQL, you can execute the commands “CREATE DATABASE” and “createdb” from psql and CMD, respectively.** You can execute the “CREATE DATABASE” command from pgAmin's query tool as well. In addition to this approach, pgAdmin can also be used to create a database manually (without executing any query).

All these approaches have their significance, users can use any of these approaches according to their preferences. This write-up has considered some examples to explain the working of **createdb** and **CREATE DATABASE** commands.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-database-in-postgresql/)

---

# How to Install PostgreSQL (psql) on Arch Linux

> To install PostgreSQL on the Arch system, use the default Pacman package manager tool. More specifically, using the “sudo pacman -S postgresql” command.

PostgreSQL is an advanced open-source RDBMS renowned for its extraordinary features. It lets us store and manipulate the data in a well-structured manner. One of the significant features of Postgres is its cross-platform compatibility (i.e., platform independent). It is accessible on all OS (including Windows, macOS, Linux, etc.), and that too without any cost.

Arch Linux is a well-known Linux distribution famous for its tremendous features like easy to use, flexible, lightweight, etc. If you are an Arch Linux user and want to install PostgreSQL on it, then this post is dedicated to you.

## Installing PostgreSQL(psql) on Arch Linux

To install Postgres on Arch Linux, go through the given steps:

  * Update System Repositories
  * Install Postgres
  * Verify Postgres Installation



### Step 1: Update System Repositories

Before proceeding with the Postgres installation make sure your system is up-to-date. For this purpose, run the given command from your system’s terminal:
    
    
    sudo pacman -Syu

### Step 2: Install PostgreSQL

Now execute the following command to install PostgreSQL from the official repository using the Paceman package manager:
    
    
    sudo pacman -S postgresql

Here, we use the “-S” option which instructs the paceman package manager to synchronize packages (install PostgreSQL from configured repositories):

### Step 3: Verify PostgreSQL Installation

To ensure the PostgreSQL installation on Arch Linux, run the below-given command:
    
    
    postgres --version

The output snippet confirms that the PostgreSQL version “16.1” has been successfully installed on our system:

##  **How to Configure PostgreSQL Server on Arch Linux**

Installing the Postgres package is a pre-requisite for configuring the Postgres server on Arch Linux. Once installed, initialize the database cluster to start the service. After this, you can set the super-user password and proceed with different database operations like creation, deletion, etc. To do that, just walk through the given stepwise instructions:

### Step 1: Switch to postgres User

First, execute the below command to switch from the Linux user to the postgres:
    
    
    sudo -iu postgres

The snippet below ensures that we switch to the postgres user:

### Step 2: Initialize Data Directory

Now execute the following command to initialize a new PostgreSQL database cluster with the specified locale settings, character encoding, and data directory:
    
    
    initdb --locale $LANG -E UTF8 -D '/var/lib/postgres/data

### Step 3: Initialize the Data Directory With Data Checksums

Enabling data checksums in PostgreSQL adds an additional/extra layer of data integrity by verifying the consistency of data at the storage level. To do this, we can use the --data-checksums argument with the above command.

Let’s check if the data checksum is enabled or not by running the below-given command:
    
    
    psql --tuples-only -c "SHOW   data_checksums"

The output shows that the checksum is not enabled yet:

To initialize the data directory with checksum enabled, all you need to do is run the following command:
    
    
    initdb --locale $LANG -E UTF8 -D '/var/lib/postgres/data/'   --data-checksums

The output makes things clear as it clearly states that the checksums are enabled:

##  **How to Enable the PostgreSQL Server on Arch Linux?**

To enable the Postgres server on Arch Linux, follow the below-listed steps:

### Step 1: Start PostgreSQL Server

Once the data directory is initialized, you need to start the PostgreSQL server to make it operational. To do that, execute the command:
    
    
    systemctl start postgresql

Executing the systemctl command will lead you to the following window. Provide the appropriate password and hit the Authenticate button to proceed:

### Step 2: Check PostgreSQL Status

Now execute the below-stated command to check the PostgreSQL status:
    
    
    systemctl status postgresql

The output snippet depicts that the PostgreSQL is active and running:

### Step 3: Enable Postgres

In case PostgreSQL is not enabled, run the systemctl command with the enable argument, as follows:
    
    
    systemctl enable postgresql

##  **How to Use PostgreSQL Server on Arch Linux**

Now we can use the PostgreSQL server on our Arch Linux, for this, access the psql(Postgres interactive terminal) as a postgres user:
    
    
    sudo -u postgres psql

From the below snippet, you can notice that we have successfully switched to the default Postgres user:

Now you can perform any database operation of your choice using SQL commands like CREATE TABLE, CREATE DATABASE, CREATE USER, DELETE TABLE, DROP TABLE, etc.

##  **How to Uninstall Postgres From Arch Linux**

If PostgreSQL is not required anymore, you can remove/uninstall it from your Arch Linux to free up some space. For this purpose, run the below command:
    
    
    sudo pacman -Rcns postgresql

On successful execution, Postgres will be completely uninstalled from your system along with its config files and dependencies.

##  **Final Thoughts**

PostgreSQL is an advanced open-source database system that allows users to enter SQL queries and immediately view the results. Anyone can install it easily on any operating system (since it is platform-independent). We can install Postgres(psql) on the Arch system using the default Pacman package manager tool. 

Once you have installed PostgreSQL, set it up by configuring the hostname, port, and database you want to connect to. When setting up the PostgreSQL server, ensure to enable data checksums to enhance data integrity and modify the authentication methods for both local and remote connections. 

This guide has illustrated all the necessary steps to install, setup, and uninstall PostgreSQL on Arch Linux.

---
[View this page online](https://www.commandprompt.com/education/install-postgresql-psql-arch-linux/)

---

# How to Use LIMIT Clause in PostgreSQL

> In PostgreSQL, the LIMIT clause and OFFSET clause allow us to retrieve only a subset of data returned/generated by the SELECT query.

PostgreSQL provides an optional clause for the SELECT query named **LIMIT**. The **LIMIT** clause limits the data/record returned by the SELECT query. An optional clause named **OFFSET** can be used with the **LIMIT** clause to omit/skip some rows. All in all, we can say that the **LIMIT** clause and **OFFSET** clause allow us to retrieve only a subset of data returned/generated by the SELECT query.

This write-up is going to present a detailed understanding of the **LIMIT** clause with the help of some examples. So, let’s start!

##  **How to Use LIMIT Clause in PostgreSQL**

A LIMIT clause restricts/limits the number of rows retrieved by the SELECT statement. Let’s have a look at the below syntax to get a basic understanding of the LIMIT clause:
    
    
    SELECT col_1, col_2, col_N
    FROM tab_name
    LIMIT number_of_rows;

Let’s understand how the **LIMIT** clause works in PostgreSQL:

  * col_1, col_2, col_3, …, col_N are the columns to be selected.
  * tab_name is a table whose columns will be selected.
  * “LIMIT number_of_rows” represents the number of rows to be selected from the result set returned by the SELECT query.



###  **Example 1: Using LIMIT Clause in Postgres SELECT Statement**

Suppose we already have a table named “bike_details”. Let’s run the SELECT query to fetch the table details:
    
    
    SELECT * FROM bike_details;

The output shows that there are ten rows in the bike_details table:

Now let’s execute the SELECT statement with the LIMIT clause to fetch only five rows of the bike_details table:
    
    
    SELECT * FROM bike_details
    LIMIT 5;

In the first step, we observed that there are ten rows in the bike_details table. However, the LIMIT clause allows us to fetch the desired number of rows from the selected table.

###  **Example 2: Fetching the First Three Rows of the bike_color and bike_number Columns**

Using the LIMIT clause, we can fetch any number of rows from any specific table column(s):
    
    
    SELECT bike_color, bike_number
    FROM bike_details
    LIMIT 3;

This time, the **LIMIT** clause retrieves the first three rows of the bike_color and bike_number columns.

###  **Example 3: Fetching the Last Three Rows of a Table in PostgreSQL**

In PostgreSQL, the **ORDER BY** clause is used to specify an order, such as ascending or descending. Let’s use the LIMIT and ORDER BY clauses to fetch the last three rows (for bike_id) of the bike_details table:
    
    
    SELECT * FROM bike_details
    ORDER BY bike_id DESC
    LIMIT 3;

This is how you can fetch the record of any specific table from the bottom.

##  **How to Use LIMIT Clause With the OFFSET Clause in PostgreSQL**

In PostgreSQL, an optional clause named OFFSET can be used with the collaboration of the LIMIT clause to skip some rows of a table.

###  **Example: How Does OFFSET Clause Work in PostgreSQL**

Let’s consider the following snippet to understand the workings of the **LIMIT** clause:
    
    
    SELECT * FROM bike_details
    LIMIT 3 OFFSET 2;

The above snippet will perform the following functionalities:

  * The SELECT statement fetches all the columns of the bike_details table.
  * The LIMIT clause retrieves only three rows.
  * The OFFSET skips the first two rows of the bike_details table.



The output clarifies that the OFFSET clause skipped the first two rows and the LIMIT clause retrieved the next three rows of the bike_details table.

##  **How to Use LIMIT With WHERE Clause in Postgres**

You can use LIMIT with the WHERE clause to fetch the limited set of table rows based on certain criteria(as specified in WHERE). We will implement this concept on an "employee_attendence" table whose details are shown below:

The table keeps a total of seven records (from emp_id 1-7). Let's execute the SELECT query with LIMIT and WHERE Clauses to fetch only three employees having IDs less than or equal to 5:
    
    
    SELECT * FROM employee_attendence
    WHERE emp_id <=5
    LIMIT 3;

##  **How to Get a Limited Number of Random Records in Postgres**

Normally, invoking the LIMIT clause retrieves a limited number of table rows from the top or bottom(depending on the specified ORDER). However, you can also fetch a limited number of random rows from a table using the LIMIT clause with the RANDOM() method:
    
    
    SELECT * FROM employee_attendence
    ORDER BY RANDOM()
    LIMIT 3;

Each time you execute the above query, you will get a different result:

That was all the necessary details related to the Postgres LIMIT Clause.

##  **Conclusion**

In PostgreSQL, an optional clause named LIMIT is used to limit the data/record returned by the SELECT query. The **OFFSET** clause can be used optionally with the **LIMIT** clause to omit/skip some rows of the selected table. This post has explained the several use cases of the LIMIT clause with the help of different examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-limit-clause-in-postgresql/)

---

# How to Install PostgreSQL on Ubuntu 24.04

> To install Postgres on Ubuntu 24.04, first update the system packages and then use the “sudo apt install postgresql postgresql-contrib -y” command.

PostgreSQL is an advanced, open-source, feature-rich relational database widely used across the globe. PostgreSQL is compatible with almost all major operating systems, including Ubuntu. Ubuntu 24.04 (codenamed Nobal Numbat) is the latest LTS Ubuntu version, released in April 2024. We can install PostgreSQL on Ubuntu 24.04 for a reliable and robust database management system.

In today’s guide, we’ll show you a step-by-step process of installing, using, and uninstalling PostgreSQL from Ubuntu 24.04.

## How to Install PostgreSQL(psql) on Ubuntu 24.04?

Go through the following stepwise instructions to install Postgres on Ubuntu 24.04:

  * Update System Packages
  * Install Postgres
  * Start Postgres Service
  * Use Postgres on Ubuntu 24.04



Let’s start the practical implementation of Postgres on Ubuntu 24.04:

###  **Step 1: Update System Packages**

Let’s use the below-given command to update the system packages before installing Postgres:
    
    
    sudo   apt update

###  **Step 2: Install Postgres**

After Updating the system packages, use the below command to install Postgres and its contrib package on Ubuntu 24.04:
    
    
    sudo apt install postgresql postgresql-contrib -y

###  **Step 3: Start Postgres Service**

After installing Postgres, execute the given command to start the Postgres service via the configurations specified in the “postgresql.service” file:
    
    
    sudo systemctl start postgresql.service

###  **Step 4: Use Postgres on Ubuntu 24.04**

After starting the Postgres service, we are all set to use it and perform different database operations. But before that, we need to switch to the “postgres” account, for this purpose, use the command:
    
    
    sudo -u postgres psql

The following output depicts that we have successfully switched to PostgreSQL’s default user “postgres”:

Alternatively, we can execute the “sudo -i” command to switch to the “postgres” user and then “psql” command to access the SQL Shell, like this:
    
    
    sudo -i -u postgres
    psql

Now we can perform any database operation like creating a new user, switching a user, creating a new database, table, etc. For instance, in the below code snippet, we execute the CREATE USER command to create a new user/role:
    
    
    CREATE USER cpUser WITH LOGIN PASSWORD 'asdf';

A new user named “cpUser” with the specified login privileges has been created successfully:

This way, we can execute any SQL query to accomplish a specific database operation.

##  **How to Uninstall/Remove Postgres From Ubuntu 24.04?**

We can use the following apt command with the “autoremove” option to uninstall Postgres along with its related packages from Ubuntu 24.04:
    
    
    sudo apt autoremove postgresql postgresql-*

We can run the following rm command to forcefully remove the complete “/etc/postgresql/” directory along with all its content:
    
    
    sudo rm -rf /etc/postgresql/

This is how we can install or uninstall Postgres to/from Ubuntu 24.04.

##  **Final Thoughts**

To install Postgres on Ubuntu 24.04, first update the system packages and then use the “sudo apt install postgresql postgresql-contrib -y” command. This will install Postgres along with the contrib package on Ubuntu 24.04. Once Postgres is installed on your system, start the Postgres service, access the SQL Shell, and then you can execute any SQL query to perform a database operation. This tutorial demonstrated a step-by-step guide on installing, using, and uninstalling PostgreSQL on Ubuntu 24.04.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-postgresql-on-ubuntu-2404/)

---

# How to Use RENAME TABLE Statement in PostgreSQL

> In PostgreSQL, the RENAME TO clause is used with the collaboration of the ALTER TABLE statement to rename an already existing table.

The "RENAME TABLE" statement is typically used in MySQL to rename/retitle a table. In PostgreSQL, the same functionality is achieved using the ALTER TABLE command. The ALTER TABLE command serves multiple functionalities regarding table modification, such as dropping a table column, renaming a table/column, etc. For this purpose, different clauses are used along with the ALTER TABLE command. To rename an already existing table, you must use the **RENAME** clause within the [ALTER TABLE](<https://commandprompt.com/education/how-to-use-the-alter-table-command-in-postgresql/>) statement.

This write-up will explain how to rename a table using the ALTER TABLE statement. So, let’s start!

##  **How to Use RENAME TABLE Statement in PostgreSQL**

In PostgreSQL, the **RENAME TO** clause is used with the below syntax to rename a specific table:
    
    
    ALTER TABLE old_Name
    RENAME TO new_Name;

  * ALTER TABLE is a statement that is used to alter a table.
  * Old_name represents the table’s original/existing name.
  *  **RENAME TO** is a clause in PostgreSQL that is used to **RENAME** a table.
  * New_name represents the table’s new/altered name.



All in all, on successful execution of the above-given query, the table’s old_Name will be renamed to new_Name.

###  **Example: How to Use RENAME TO Clause in PostgreSQL**

Open the SQL SHELL, connect to a database of your choice, and perform the following steps to rename a table:

###  **Step 1: Check the Available Tables in the Selected Database Using \dt Command**

Run the below-mentioned command in the SQL SHELL to see the list of available tables in the selected database i.e. **“example”** :
    
    
    \dt;

The output of the \dt command shows that there are 9 tables available in the example database.

###  **Step 2: Rename the Selected Table Using RENAME TO Clause**

Let’s say we need to rename the “team_info” table to “team_details”. Simply run the following query to rename a table in PostgreSQL:
    
    
    ALTER TABLE team_info
    RENAME TO team_details;

The above snippet shows that the selected table has been altered successfully.

###  **Step 3: Verify the Table Alteration Using \dt Command**

Run the \dt command to see whether the selected table has been renamed or not:
    
    
    \dt;

The output verified that the team_info table had been successfully renamed to team_details.

###  **Step 4: Verify the Table Content/Record Using SELECT Command**

You can execute the below-given command to see whether renaming the table affects the table’s content or not:
    
    
    SELECT * FROM team_details;

The output verified that the **RENAME TO** clause doesn’t affect the internal structure of the selected table.

##  **RENAME TO Clause With IF EXISTS Parameter**

In PostgreSQL, trying to RENAME a table that does not exist will throw an error. To avoid such an error, the **“IF EXISTS”** parameter is used with the ALTER TABLE statement. The modified syntax will be as follows:
    
    
    ALTER TABLE IF EXISTS old_Name
    RENAME TO new_Name;

Now, firstly, the ALTER TABLE command will check whether the specified table exists or not. If it exists, then further process will take place. If the specified table doesn’t exist, then PostgreSQL will show a notice instead of throwing an error.

###  **What is the Need for the “IF EXISTS” Parameter?**

Suppose someone tries to access a table that doesn’t exist in the targeted database, then in such a case, PostgreSQL will throw an error:
    
    
    ALTER TABLE car_details RENAME TO vehicle_details;

###  **Solution: Use the “IF EXISTS” Parameter**

Let’s modify the above example a little bit and use the IF EXISTS parameter to avoid the “relation/table not exist” error:
    
    
    ALTER TABLE IF EXISTS car_details RENAME TO vehicle_details;

The output verified that this time we got a notice instead of an error. This way, the normal flow of the query wouldn't be affected. In case the table doesn't exist, the ALTER TABLE statement will be skipped and the control will be moved/transferred to the next statement.

##  **How to RENAME Dependent Tables in PostgreSQL**

Suppose we have two tables that are dependent on each other via foreign key constraints, and their details are as follows:

Renaming a table will automatically modify the dependent object like a foreign key constraint. For example, the below code renames the "emp_team" table to "e_team":
    
    
    ALTER TABLE emp_team
    RENAME TO e_team;

Now, let's describe both tables one more time, and you will witness that changes made in one table are also implemented in the other table:

That's all about renaming a table Postgres using RENAME TO clause.

##  **Conclusion**

In PostgreSQL, the **RENAME TO** clause is used with the collaboration of the ALTER TABLE statement to rename an already existing table. Trying to rename a table that doesn’t exist will throw an error; however, the **IF EXISTS** parameter can be used to avoid such errors. This write-up has explained how to rename a table in PostgreSQL using different examples.

---
[View this page online](https://www.commandprompt.com/education/rename-table-postgresql/)

---

# PostgreSQL TIME Data Type With Examples

> To use TIME data type in Postgres, first, create a table with a TIME-type column. Once created, you can insert any time value into that column using the INSERT…

**TIME** is one of the built-in data types in PostgreSQL that assists us in managing/storing the time values. It takes 8 bytes to store a time value. It stores the time in the standard format, i.e., “HH:MM:SS”. You can create a table column with TIME data type and store any time value between the range of “ **00:00:00** ” to “ **24:00:00** ”. To learn more about the usage of the TIME data type in PostgreSQL, we will walk you through different examples.

##  **How to Use the TIME Data Type to Store Time Values in PostgreSQL**

To use TIME data type in Postgres, first, create a table with a TIME-type column. Once created, you can insert any time value into that column using the INSERT command. Also, you can invoke different date-time functions on that column to store and manage time values.

###  **Syntax**

Let’s look at the syntax below to learn how to create/declare a column with TIME data type:
    
    
    colName TIME(prc);

Here, “prc” represents precision. PostgreSQL allows us to store a time value with or without precision. A time value can have a precision of up to six digits.

Some commonly used TIME formats without precision are listed below:

  * HH:MI:SS, for example, 10:24:30.
  * HHMISS, for example, 102430.
  * HH:MI, for example, 1024.



The frequently used time formats with precision are illustrated below:

  * HH:MI:SS.pppppp, for example, 10:24:30.999999
  * HHMISS.pppppp, for example, 102430.999999
  * MI:SS.pppppp, for example, 24:30.999999



Here, we mentioned some commonly used time formats; however, PostgreSQL supports almost all the valid time formats including ISO 8601 formats, SQL-compatible formats, and so on.

###  **Example 1: How to Create a Column With TIME Data Type in PostgreSQL**

Let’s create a table named “employee_attendence” with three columns: emp_id, emp_check_in, and emp_check_out:
    
    
    CREATE TABLE employee_attendence( 
      emp_id INT PRIMARY KEY, 
      emp_check_in TIME NOT NULL, 
      emp_check_out TIME NOT NULL 
       );

The output shows that the employee_attendence table has been created successfully. Let’s verify the column names and their respective data types using the SELECT command:
    
    
    SELECT * FROM employee_attendence;

The output authenticates that the employee_attendence table has been created successfully.

###  **Example 2: How to Insert Time Values Into a Table**

Let’s insert the employee’s attendance record into the employee_attendence table:
    
    
    INSERT INTO employee_attendence (emp_id,   emp_check_in, emp_check_out)
     VALUES (5, '09:05:35', '05:15:00'),
       (1, '09:00:45', '05:15:00'),
       (4, '09:25:55', '06:00:14'),
       (3, '09:15:25', '05:35:00'),
       (2, '09:02:15', '05:00:20');

In this example, we inserted time values in “HH:MM:SS” format. Here is what we will get on successfully executing the INSERT query:

The output shows that five records have been inserted into the employee_attendence table. Let’s describe the table’s records using the SELECT command:
    
    
    SELECT * FROM employee_attendence;

The output proved that the **TIME** data type successfully stored the time values without a time zone.

###  **Example 3: How to Insert Current Time Into a Table**

You can either insert the current time manually or invoke a built-in Postgres method to insert the current time into a table. Invoking a built-in method is a recommended approach, as shown in the following code:
    
    
    INSERT INTO employee_attendence (emp_id, emp_check_in, emp_check_out)
     VALUES (6, '09:05:35', CURRENT_TIME);

In this example, we invoke the CURRENT_TIME method in the INSERT statement to store the current time in the “emp_check_out” column:

The output demonstrates that the current time has been inserted into the “emp_check_out” column. For more clarity, you can execute the SELECT query with the “*” wildcard as follows:
    
    
    SELECT * FROM employee_attendence;

The output shows that the stated method inserts the time with precision. If you want to store the current time without precision, execute the INSERT query as follows:
    
    
    INSERT INTO employee_attendence (emp_id, emp_check_in, emp_check_out)
     VALUES (7, '09:05:35', CURRENT_TIME(0));

You can cross-check the newly inserted record by executing the command:
    
    
    SELECT * FROM employee_attendence;

 **Note:** You can also employ the “LOCALTIME” method to insert/store local time into a Postgres table.

###  **Example 4: How to Extract/Fetch Only Specific Time Field From a Table**

If you need only a specific time field, instead of a complete time, you can use the EXTRACT() method with the desired field as follows:
    
    
    SELECT EXTRACT (HOUR FROM emp_check_out) AS checkOut_hour,
     EXTRACT (MINUTE FROM emp_check_out) AS checkOut_min
     FROM employee_attendence;

In this code, we extract the hour and minute fields from the “emp_check_out” column, as shown below:

###  **Example 5: How to Use Arithmetic Operators on Time Values**

We can perform different tasks using different arithmetic operators (like +, -, and *) on TIME values. For example, in the following code, we use the “-” operator to subtract “2” hours from the emp_check_out column:
    
    
    SELECT emp_check_out, emp_check_out - TIME '02:00:00' As modified_time
     FROM employee_attendence;

We use the SELECT query to fetch the actual “emp_check_out” column and modified time for “emp_check_out” column:

##  **How to Get Time Values With Time Zones in PostgreSQL**

The previous example shows that the TIME data type stores the time values without the time zone. Use the **“TIME WITH TIME ZONE”** data type to store the time values with the time zone. The TIME WITH TIME ZONE data type takes 12 bytes to store the time values with the time zone. Follow the below-given syntax to create a time column with a time zone:
    
    
    col_name TIME WITH TIME ZONE;

Let’s consider the following example to learn how the “TIME WITH TIME ZONE” data type works in PostgreSQL.

###  **Example 1: How to Create a Column Using “TIME WITH TIME ZONE” Data Type in PostgreSQL**

Let’s create a table emp_attendence that contains some columns of type “TIME WITH TIME ZONE”:
    
    
    CREATE TABLE emp_attendence (
       emp_id INT PRIMARY KEY,
       emp_check_in TIME WITH TIME ZONE NOT NULL,
       emp_check_out TIME WITH TIME ZONE NOT NULL 
       );

Let’s execute the SELECT command to see the table’s structure:
    
    
    SELECT * FROM emp_attendence;

The output shows that three columns with the respective data types have been created successfully.

###  **Example 2: How to Insert Time Values With Time Zone Into a Table**

Let’s insert some time values along with the time zone to the emp_attendence table:
    
    
    INSERT INTO emp_attendence (emp_id, emp_check_in, emp_check_out)
     VALUES (3, '09:00:00 BST', '05:00:00   BST'),
       (1, '09:05:45 BST', '05:05:45   BST'),
       (2, '09:12:15 BST', '05:12:15   BST');

In this example, we stored the time along with the BST (British Summer Time) time zone. Let’s execute the SELECT statement to describe the table details:

This is how the “TIME WITH TIME ZONE” data type works in PostgreSQL. That was all the necessary information regarding the TIME data type in PostgreSQL.

##  **Conclusion**

To use TIME data type in Postgres, create a table column with the following syntax “colName TIME”. Once you succeed in creating a TIME column, you can insert and store any time value in that particular column. The TIME data type stores the time values without the time zone. However, you can use the "TIME WITH TIME ZONE" data type to store time values with time zones. The TIME data type takes 8 bytes to store a time value while the TIME WITH TIME ZONE data type takes 12 bytes to store the time values. Use any of the mentioned data types that perfectly fulfill your program’s requirements.

---
[View this page online](https://www.commandprompt.com/education/postgresql-time-data-type-with-examples/)

---

# How to Use Insert Query in PostgreSQL

> How to use Insert with PostgreSQL

**PostgreSQL** offers a convenient statement named **“INSERT”** that is used to insert/add new records in a table. Using the **INSERT** query, an individual or several records can be added to the selected table. It allows users to insert data of any valid data type into a table easily. Later on, different commands and queries can be used to perform any specific operations on this inserted data.

##  **Quick Outline**

This Postgres blog will walk you through the following content regarding the Postgres INSERT query:

  *  **How to Use the INSERT Query in Postgres**
  *  **How to Insert a Single Row to a Table in PostgreSQL**
  *  **How to Insert Several/Multiple Rows to a Table in PostgreSQL**
  *  **How to Use the SELECT Query With the RETURNING Clause in PostgreSQL**
  *  **How to Insert a Date Value to a Column in PostgreSQL**
  *  **How to Insert a Row Into a Postgres Table Using pgAdmin | GUI Method**
  *  **Final Thoughts**



So, let’s learn how to use **INSERT** Query in **PostgreSQL** with the help of some practical examples.

##  **How to Use the INSERT Query in Postgres**

As we have discussed earlier, the **INSERT** command/statement is used to insert new records in any specific table. Let’s consider the below-listed points for a profound understanding of the **INSERT** query:

  * The character data must be enclosed in single quotes (‘), such as 'INSERT QUERY'.
  * Use the “YYYY-MM-DD” format to insert a date into a table.
  * In **PostgreSQL** , omitting the mandatory columns in the **INSERT** command will throw an error.
  *  **Postgres** will utilize the column’s default value if someone skips the optional columns.
  * Use the Keyword **“DEFAULT VALUES”** to insert default values into the columns.



Following will be the basic syntax of the **INSERT INTO** command in **PostgreSQL** :
    
    
    INSERT INTO tab_name (col_1, col_2, col_3,...col_N)
    VALUES (val_1, val_2, val_3,...val_N);

The above snippet utilizes the following standards:

  * First, it specifies the **INSERT INTO** command to insert a specific record into the targeted table.
  *  **tab_name** is the name of the targeted table while **col_1, col_2, col_3, . . . , col_N** are the column names.
  *  **VALUES** is a clause used between the column names and an ordered list of comma-separated values.



All in all, the **INSERT INTO** command takes a list of column names and values in a specific order and inserts them into the selected table. There must be the same order of the column names and values.

##  **How to Insert a Single Row to a Table in PostgreSQL**

Follow the below-given step-by-step guidelines to insert data into a specific table in Postgres:

 **Step 1: Select a Table Using \dt Command**

Firstly, select a table where you want to insert the data. To do so, run the **“\dt”** command:
    
    
    \dt;

Let’s say we need to insert data into the **“team_info”** table.

 **Step 2: Describe the Selected Table Using \d Command**

Type the **“\d”** command followed by the table name, i.e., **“team_info”** , and hit the enter button to illustrate the table details:
    
    
    \d   team_info;

To avoid errors, keep this table structure in mind when inserting data into the selected table.

 **Step 3: Run the INSERT Query**

Let’s execute the **INSERT INTO** command to insert some data into the **“team_info”** table:
    
    
    INSERT INTO team_info (team_id, team_name, team_ranking)
    VALUES (1, 'Pakistan', 1);

The output shows that one row has successfully been inserted into the **team_info** table.

 **Step 4: Verify the Inserted Data Using Select Command**

Execute the **SELECT** query to check whether the data has been inserted into the selected table or not:
    
    
    SELECT * FROM team_info;

The **“SELECT** ***”** command will fetch all the column’s data, as shown in the following output:

The output authenticates that the data has been inserted into the selected table.

##  **How to Insert Several/Multiple Rows to a Table in PostgreSQL**

In this example, we will use the comma-separated syntax to insert multiple rows in the **“team_info”** table using the **“INSERT”** query:

 **Step 1: Execute the INSERT Query**

Run the **INSERT INTO** statement to insert some data into the **“team_info”** table:
    
    
    INSERT INTO team_info (team_id, team_name, team_ranking)
     VALUES 
       (2, 'England', 4),
       (3, 'Australia', 2),
       (4, 'South Africa', 5),
       (5, 'Srilanka', 3);

In the above snippet, we utilized the **INSERT INTO** query to insert four rows into the team_info table.

 **Step 2: Verify the Inserted Data Using Select Command**

Use the **SELECT** command to verify whether the data has been added to the selected table or not:
    
    
    SELECT * FROM team_info;

The output shows that the data has been inserted into the selected table successfully.

##  **How to Use the INSERT Query With the RETURNING Clause in PostgreSQL**

Use the **RETURNING** clause with the **“INSERT INTO”** command to get the last entered/inserted ID from the selected table.

Here is the basic syntax of the **RETURNING** clause of the **INSERT** statement in **Postgres** :
    
    
    INSERT INTO tab_name (col_1, col_2, col_3,...col_N)
    VALUES (val_1, val_2, val_3,...val_N),
    RETURNING id;

The above-given query will insert the values into the specified columns and will return the last inserted ID.

 **Example: How Does the RETURNING Clause Work With INSERT Statement?**

Let’s run the **RETURNING** clause with the collaboration of the **INSERT INTO** statement to get the last inserted ID:
    
    
    INSERT INTO team_info (team_id, team_name, team_ranking)
    VALUES (6, 'West Indies', 7)
    RETURNING team_id;

The output shows that the **RETURNING** clause returns the last entered ID:

##  **How to Insert a Date Value to a Column in PostgreSQL**

 **Postgres** allows us to insert a date into a column using the **DATE** type. To do this, we must follow the Year-month-day format, i.e., **“YYYY-MM-DD”**.

 **Example: How to Insert a Date to a Specific Table?**

In this example, we will insert a date value to a particular table, i.e., “article_details”:

 **Step 1: Insert Date Value into a Table Using INSERT Query**

Run the **INSERT** query to insert the date value into the **“article_details”** table:
    
    
    INSERT INTO article_details (article_id, article_title, published_date)
    VALUES (1, 'Postgres   INSERT Query', '2022-07-22');

 **Step 2: Verify the Working of INSERT Query Using SELECT Command**

Let's run the **" SELECT"** query to see if the specified date has been inserted into the table:
    
    
    SELECT * FROM article_details;

The output verifies that the “date” value has been entered into the **“article_details”** table.

##  **How to Insert a Row Into a Postgres Table Using pgAdmin? | GUI Method**

 **pgAdmin** is a GUI-based management tool for Postgres that can be used to perform database operations effectively. It allows us to execute the SQL commands and queries to perform different database operations. It also allows us to use its graphical interface to perform various database operations, such as inserting new rows into a table.

Expand the database in which the desired table resides, select the “public” schema, and then navigate to the “tables” section to select the desired table:

Select the table of your choice, right-click on it, hover over “View/Edit Data”, and select the “All rows” option:

From the popup output, select the below-highlighted “add row” option to insert a new record/row into the table:

Double-click on the field in which you want to insert data, and then click on the “save data changes” option to store the data in the selected table:

That’s all about inserting data into a Postgres table using psql and pgAdmin.

##  **Final Thoughts**

In **PostgreSQL,** the **“INSERT”** statement is used to insert/add new records in a particular table. The **INSERT** query inserts an individual or several records into the selected table. In **Postgres** , the **RETURNING** clause is used with the collaboration of the **INSERT** statement to get the last entered/inserted ID from the selected table. This post has explained the workings of the **INSERT** query with the help of suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-insert-query-in-postgresql/)

---

# PostgreSQL IF Statement With Examples

> If statement executes only those expressions that satisfy the specified condition. Otherwise the control will be moved to the next statement.

PostgreSQL provides some statements that assist users in decision-making scenarios. These statements take a decision based on some specific criteria/condition and are hence referred to as control statements. In Postgres, the **if-statement** is one of the most valuable and frequently used control statements. It executes only those expressions that satisfy the specified condition. The below flow charts demonstrate the workflow of the Postgres IF statement:

Now, let’s explore the use of PostgreSQL if-statement with examples.

##  **How to Use IF Statement in PostgreSQL?**

In Postgres, the IF statement only treats the true condition. The syntax of the IF statement is as follows:
    
    
    IF condition
    THEN statement(s);
    END IF;

Here, the “condition” represents a criterion that must be satisfied to execute the “statements” specified within the THEN block.

>  ** _Important:_** _If an expression doesn’t satisfy the specified criteria, then the if-statement moves the control to the next statement._

###  **Example 1: How Does the IF Statement Work in PostgreSQL?**

Let’s consider a scenario to understand the working of the IF statement:
    
    
    DO $$ DECLARE
    user_age INT := 25;
    BEGIN
    IF user_age > 18 THEN
    RAISE NOTICE 'Access Granted';
    END IF;
    IF user_age < 18 THEN
    RAISE NOTICE 'Access Denied';
    END IF;
    RAISE NOTICE 'Control Shifted Out of IF Statement';
    END $$;

  * Firstly, we utilized the DO statement which indicates that we are going to execute all the statements that come under it.
  * Next, we declared a variable user_age and assigned it a value of 25.
  * After that, we utilized the BEGIN statement to start the execution.
  * Next, we utilized the IF statement that checks if the “user_age > 18”. If yes, then show the message “Access granted”.
  * If no, then the control will be moved to the next statement after the first END IF; where the variable’s value will be tested against the second condition i.e. “user_age < 18”.
  * Once done with IF conditions, the control will be moved to the next statement specified after the “END IF” statement.



Let’s modify the variable’s value and see how the if-statement works in that case:
    
    
    user_age INT := 15;

This time the variable’s value will be tested against the first condition i.e. user_age > 18.

  * The if-statement will return false, so the statements associated with the first condition will be skipped.
  * The control will be moved to the second condition i.e. user_age<18.
  * The if statement will compare the user’s age with the specified condition, i.e. 15 < 18\. Consequently, it will return the following output:



The notice “Access Denied” authenticates the working of the IF statement.

###  **Example 2: IF Statement With False Condition**

As discussed earlier, the Postgres **IF** statement works perfectly fine only with true conditions, however, it doesn’t deal with false conditions. For instance, in the following code block, none of the specified conditions are true; let’s see how the **IF** statement deals with it:
    
    
    DO $$ DECLARE
    user_age INT := 18;
    BEGIN
    IF user_age > 18 THEN
    RAISE NOTICE 'Access Granted';
    END IF;
    IF user_age < 18 THEN
    RAISE NOTICE 'Access Denied';
    END IF;
    RAISE NOTICE 'Control Shifted out of IF Statement';
    END $$;

This time,

  * We initialize the variable “user_age” with a value “18”.
  * In the BEGIN block, the “user_age” will be checked against both IF conditions. The specified age doesn’t satisfy any of the IF statements. So, the control will be moved to the next statement specified after the “END IF” statement.



The output confirms that the IF statement doesn’t deal with the FALSE condition, instead, it simply moves the control to the next statement.

###  **Example 3: Dealing With False Conditions**

From the above examples, we can conclude that it doesn’t matter how many IF statements we use, they only deal with true conditions, and they have nothing to do with the FALSE conditions. So, the question is how to address the false conditions. Well! The IF-ELSE statement comes in handy here. The below syntax will help you understand this concept better:
    
    
    IF condition THEN            --Executes if condition returns TRUE
    statements;
    ELSE                         --Executes otherwise (FALSE condition)
    alternative-statements;
    END if;

Let’s modify the code of example 3 by embedding the ELSE condition in it:
    
    
    DO $$ DECLARE
    user_age INT := 18;
    BEGIN
    IF user_age > 18 THEN
    RAISE NOTICE 'Access Granted';
    END IF;
    IF user_age < 18 THEN
    RAISE NOTICE 'Access Denied';
    ELSE 
    RAISE NOTICE 'Try Again';
    END IF;
    RAISE NOTICE 'Control Shifted out of IF Block;
    END $$;

This time the “FALSE” condition is successfully tackled using the ELSE condition, as shown in the following output:

To learn more use cases of the ELSE condition, go through the following dedicated guide on [IF-ELSE](<https://www.commandprompt.com/education/postgresql-if-else-statement-with-examples/>).

###  **Example 4: Dealing With Multiple Conditions**

Use the IF-THEN-ELSIF instead of a simple IF-ELSE if you have to evaluate multiple conditions. In such a case, if the specified condition is true, the associated statement within that branch will be executed. If all the specified conditions are evaluated to FALSE, then the control will be moved to the “else” branch, and the associated statements within it will be executed.

Here is how you can implement IF-THEN-ELSIF in Postgres:
    
    
    IF condition1 THEN
      statement1;
    ELSEIF condition2 THEN
      statement2
    ...
    ELSEIF conditionN THEN
      statementN;
    ELSE
      statement;
    END IF;

Here, the “TRUE” conditions will be tackled by the “IF” statement, and the false conditions(that don’t satisfy the IF statement) will be addressed by ELSEIF. While the conditions that neither meet the IF statement nor the ELSEIF statement will be addressed by the ELSE block.

Here is a code example that demonstrates how multiple false conditions can be addressed using the “IF-THEN-ELSIF” statement:
    
    
    DO $$
    DECLARE
    emp1_salary INT := 55000;
    emp2_salary INT := 54000;
    BEGIN
    IF emp1_salary < emp2_salary THEN
    RAISE NOTICE 'emp1_salary is less than emp2_salary';
    ELSIF emp1_salary > emp2_salary THEN
    RAISE NOTICE 'emp1_salary is greater than emp2_salary';
    ELSE
    RAISE NOTICE 'emp1_salary is equal to emp2_salary';
    END IF;
    END $$;

In this example, the salaries of two employees are compared, and a notice is raised accordingly. In the considered example, the condition specified in the ELSIF block is evaluated as TRUE, so the notice/message associated with that block is retrieved in the output:

> To learn more about the usage of ELSE IF in Postgres, read our dedicated guide on PostgreSQL [Else If Statement](<https://www.commandprompt.com/education/postgresql-else-if-statement-with-examples>).

##  **Conclusion**

In PostgreSQL, the if-statement is one of the most valuable and frequently used control statements. The If statement executes only those expressions that satisfy the specified condition. If an expression doesn’t satisfy the specified criteria, then the if-statement moves the control to the next statement. This post considered several examples to explain the working of the if statement in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-if-statement-with-examples/)

---

# How to Rename Databases in PostgreSQL

> To rename a database in Postgres, use the ALTER DATABASE statement with the RENAME TO clause. Also, you can use pgAdmin to rename a database manually.

To rename a database in Postgres, use the **ALTER DATABASE** statement with the **RENAME TO** clause. In Postgres, the current database cannot be renamed. So, to rename a database, firstly, you must establish a connection with any other database.

Once the connection is established, you can run the **“ALTER DATABASE”** command with the collaboration of the **“RENAME TO”** clause from that particular database to rename the targeted database.

This blog post will explain how to rename a database in PostgreSQL using the following context:

  1.  **How to Rename Databases in PostgreSQL Using psql?**
  2.  **How to Rename Databases in PostgreSQL Using pgAdmin?**



So, let’s start.

##  **How to Rename Databases in PostgreSQL Using psql**

Following are the prerequisite steps that must be performed to rename a database in PostgreSQL:

  * Firstly, terminate/disconnect the database that you want to rename.
  * Establish a connection with any other database.
  * Close all the connections that are associated with the targeted database.
  * Finally, run the **ALTER DATABASE** statement with the collaboration of the **RENAME TO** clause to rename the database.



###  **Syntax:**

To rename a database in PostgreSQL, specify an **ALTER DATABASE** command, followed by the database's old name, after that specify the **RENAME TO** clause followed by the database's new name:
    
    
    ALTER DATABASE old_dbname RENAME TO new_dbname;

Let’s implement it practically.

###  **Example: Renaming a Database in Postgres**

This example will provide stepwise instructions to rename a database in PostgreSQL:

###  **Step 1: Create a New Database**

Firstly, create a new database named “example_db” using the following command:
    
    
    CREATE DATABASE example_db;

The “example_db” database is created successfully.

###  **Step 2: Make a Connection With Database**

Connect to any database other than the database to be renamed:
    
    
    \c commandprompt;

The connection is successfully established with the “commandprompt” database.

###  **Step 3: Check Active Connections**

Execute the below statement to check the active connections:
    
    
    SELECT * FROM pg_stat_activity WHERE datname = ‘example_db’;

On successful execution, you will get the list of active connections.

###  **Step 4: Terminate Active Connections**

Run the following statement to sack/close all the active connections:
    
    
    SELECT pg_terminate_backend (pid)
    FROM pg_stat_activity
    WHERE datname = 'example_db';

###  **Step 5: Rename Database**

Once the active connections are terminated, now you can rename a database using the **ALTER TABLE** command as follows:
    
    
    ALTER DATABASE example_db RENAME TO modified_db;

The output snippet verifies that the selected database has been modified/renamed successfully.

###  **Step 6: Verify Database Name**

Let’s verify that whether the selected database has been renamed or not:
    
    
    \l;

The output snippet proves that the “ **example_db”** database has been renamed to “ **modified_db** ”.

##  **How to Rename a Database in PostgreSQL Using pgAdmin**

If you are a GUI lover and want to rename a database without executing any query, then opt for the pgAdmin(GUI-based development platform for Postgres). Using pgAdmin you can rename a database either by using GUI (manually) or by executing queries (using its query tool).

To rename a Postgres database manually using pgAdmin walk through the following steps:

### Step 1: Select the Database to Rename

Open the pgAdmin, and navigate to the "Object Explorer" Pane > expand the "Servers" tree > click the "Databases" option to expand it > select the database to rename and right-click on it, as follows:

Click on the "Properties..." option to open the database properties.

###  **Step 2: Rename the Database**

In the properties windows, you can modify database attributes/properties like name, owner, default privileges, tablespace, etc. To rename a database, stay on the "General" tab, navigate to the "Database" field, and rename it to any valid name of your choice:

Hit the "Save" button to update the database name.

###  **Step 3: Rename the Database**

Now navigate back to the "Databases" section in the left pane, and you will witness that the selected database has been renamed successfully:

That's all about renaming a database in Postgres using psql and pgAdmin.

##  **Conclusion**

To rename a database in Postgres, use the **ALTER DATABASE** statement with the **RENAME TO** clause. To do so, specify an **ALTER DATABASE** command, followed by the database’s old name, and after that, specify the **RENAME TO** clause followed by the database’s new/modified name. This blog post demonstrates a thorough guide on renaming a PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/rename-databases-postgresql/)

---

# A Comprehensive Guide on psql Meta-Commands

> The meta-commands are the commands offered by psql to perform certain operations. These commands start with the backslash.

Meta commands are the instructions given to the client engine/psql by the user to display some functionalities or perform certain operations. These commands are also called the “slash or backslash command” because they begin with a backslash followed by some command verb. Arguments can also be specified in the meta-commands. The SQL Shell (psql) supports a long list of meta-commands.

This tutorial will demonstrate the most frequently used meta-commands in psql.

##  **A Comprehensive Guide on psql Meta-Commands**

The meta-commands are small commands written/prefixed with the backslash. These commands are used to perform different operations like managing users, databases, tables, etc. There is a long list of meta-commands provided by the psql and a few of them are listed below:

  *  **\l - Lists All the Databases**
  *  **\c <database_name> \- Connect to a Specific Database**
  *  **\d - Display Objects**
  *  **\x - Set the Expanded Display**
  *  **\set - Display Internal Variables**
  *  **\echo <text> \- Print Message**
  *  **\? - get help**
  *  **\a - Toggles Alignment of the Output Format**
  *  **\C <caption> \- Sets the Title/Caption of a Table**
  *  **\r - Resets the Query Buffer**
  *  **\z - Lists All the Tables With Their Revoked Permissions**
  *  **\q - Quit psql**



We will go over them one by one with the implementation.

###  **\l - Lists All the Databases**

The \l meta-command lists all the databases in the system. Let's see how it works:
    
    
    \l

>  ** _Important:_** _The \l command must be executed without a semi-colon; otherwise, you wouldn 't get the desired results._

###  **\c <database_name> \- Connect to a Specific Database**

The \c<database_name> command is used to get connected to the database whose name is specified in the command:
    
    
    \c test_db

The output demonstrates that running the "\c" command connects us to the specified database, i.e., "test_db".

###  **\d - Display Objects**

The \d meta-command displays all the objects. These objects include a table, view, index, schema, and database. We will implement the \d command with different options to display different database objects.

  *  **\dt - Display Tables**



This meta-command displays all the tables in the database when it is used as “\dt”:
    
    
    \dt

The above enlisted are the tables available in my default database.

  *  **\dv - Display Views**



This meta-command will give us all the views present in our database. In my case, I have never created any view so the command will find no such relation. The **\dm** is used to **display** the **materialized view**. The same will be the output for this case:
    
    
    \dv;
    \dm;

  *  **\di - Display Indexes**



To display indexes, we use the \di command as follows:
    
    
    \di

  *  **\dn -** **Display Schemas**



The “\dn” command will give the list of schemas present in the system:
    
    
    \dn

  *  **\dT - Display the Data Types**



The \dT command displays the user-defined data types:
    
    
    \dT

>  ** _Note_** _that the “\dt” is different from “\dT”. The \dt displays tables._

  *  **\ds - Display the Sequences**



The “\ds” command displays all the sequences of a database.

  *  **\dtS - Displays System Catalog Tables**



The system catalog tables consist of the tables and views and describe the structure of the database. These can be displayed in the psql command line using the \dtS command:
    
    
    \dtS

  *  **\du - Displays all the Roles in the Database**



This meta-command gives all the user roles defined in the system:
    
    
    \du

In my case, the only user role defined is the Postgres.

###  **\x - Set the Expanded Display**

We can toggle the expanded display using the "\x" command. This is useful for large tables. We can set it to auto or can be toggled on or off:
    
    
    \x

###  **\set - Display Internal Variables**

The **\set** command is used to list all the internal variables, as shown below:
    
    
    \set

 **\unset <name_of_variable>\- Delete an Internal Variable**

This command will delete the internal variable from the list.

###  **\echo <text> \- Print Message**

This command is used to get the text/message printed to the console:
    
    
    \echo Hello From Command Prompt!

###  **\? - get help**

This command is used to get help from the psql, particularly regarding meta-commands:
    
    
    \?

###  **\a - Toggles Alignment of the Output Format**

The “\a” command aligns and unaligns the output format, as demonstrated in the following snippet:
    
    
    \a

###  **\C <caption> \- Sets the Title/Caption of a Table**

The “ **\C <caption>**” command sets the title for the database table:
    
    
    \C hello

###  **\r - Resets the Query Buffer**

This command resets the query buffer:
    
    
    \r

###  **\z - Lists All the Tables With Their Revoked Permissions**

The “\z” command displays the list of tables with their objects as Access Control Lists i.e. ACLs:
    
    
    \z

###  **\q - Quit psql**

By running the “\q” query you can quit the psql, as illustrated in the following snippet:
    
    
    \q

Now by pressing any key, you can simply exit from the psql.

###  **Additional Information**

You can execute multiple meta-commands at the same time to perform the desired operation like this:

In the above example, we have used three commands to display the table caption, and the table, and toggle the alignment respectively and simultaneously.

We can add a **“+”** sign to every command to get some additional technical information about whatever is the output. For example; running the “\dt” gives:

While if we execute the “\dt+” command. There is some additional information displayed.

That's all the essential details regarding the psql meta-commands.

##  **Conclusion**

The meta-commands are the commands offered by psql to perform certain operations. These commands start with the backslash and are executable only in psql. In this post, we have seen many meta-commands that are being used widely.

---
[View this page online](https://www.commandprompt.com/education/a-comprehensive-guide-on-psql-meta-commands/)

---

# A Comprehensive Guide on PostgreSQL SCHEMA

> Postgres offers various built-in commands, such as CREATE SCHEMA, ALTER SCHEMA, and DROP SCHEMA, to create, modify, and drop the Postgres schemas.

A Postgres schema is a namespace that holds the database objects like tables, functions, views, etc. Schemas assist us in organizing the database objects, controlling the database access, preventing unauthorized access, etc. Postgres automatically creates a schema named “public” whenever a new database is defined/created.

## Quick Outlines

This post covers all the essential aspects of Postgres schemas using the following outlines.

  *  **How to Create a Schema in Postgres**
  *  **How to Show Schemas in Postgres**
  *  **How to Alter a Schema in Postgres**
  *  **How to Drop a Schema in Postgres**
  *  **How to Modify the Schema Path in PostgreSQL**



##  **How to Create a Schema in Postgres**

To create a new schema in Postgres, use the following syntax:
    
    
    CREATE SCHEMA [IF NOT EXISTS] name_of_schema;

“ **IF NOT EXISTS** ” is an option that creates a schema only if the schema to be created doesn’t exist already.

###  **Example 1: Creating a Postgres Schema Using psql**

Open the psql, provide the login details, and execute the CREATE SCHEMA command to create a new schema, for example, “sample_schema”:
    
    
    CREATE SCHEMA sample_schema;

The “CREATE SCHEMA” message in the output proves that the desired schema has been created successfully:

###  **Example 2: Creating a Postgres Schema Using pgAdmin**

To create the schema using pgAdmin, navigate to the "schemas" tab and right-click on it, hover over the "create", and click on the "schema..." option:

Upon doing so, a new window will pop up, type the desired schema name, and click on the "Save" button:

As soon as you click the "Save" button a new schema will be added to the schema list:

##  **How to Show Schemas in Postgres**

In SQL Shell, the “\dn” command is used/executed to show the already created schemas:
    
    
    \dn;

The “\dn” meta-command retrieves all available schemas:

Open the pgAdmin, select the desired database, and expand the schemas section to see the available schemas using the GUI method:

##  **How to Alter a Schema in Postgres**

In Postgres, the ALTER SCHEMA command is used to modify an existing schema's definition. The stated command allows us to rename a schema and change the schema’s owner.

To rename a schema, use the below-provided syntax:
    
    
    ALTER SCHEMA name_of_schema
    RENAME TO new_name_of_schema;

To modify the schema’s owner, use the following syntax:
    
    
    ALTER SCHEMA name_of_schema
    OWNER TO new_owner;

Let’s put the ALTER SCHEMA command into practice.

###  **Example 1: Changing Schema’s Name Using psql**

In the following code, the ALTER SCHEMA command is used to rename the “sample_schema” to “postgres_schema”:
    
    
    ALTER SCHEMA sample_schema
    RENAME TO postgres_schema;

Use the “\dn” command to verify the schema’s name:
    
    
    \dn;

The output shows that the “sample_schema” has been successfully renamed to “postgres_schema”.

###  **Example 2: Changing Schema’s Owner Using psql**

In the following code, the ALTER SCHEMA command is used to change the schema’s owner from “postgres_schema” to “sample_user”:
    
    
    ALTER SCHEMA postgres_schema 
    OWNER TO sample_user;

Use the “\dn” command to verify the schema’s owner:
    
    
    \dn;

The schema owner has been successfully modified to “sample_user”.

###  **Example 3: Alter Schema Using pgAdmin**

To alter a schema using pgAdmin, navigate to the desired schema from the available schema list, right-click on it, and select the "Properties..." option:

Upon doing so, a new pop-up window for the selected schema will appear, alter the schema name or owner, and hit the "Save" button:

##  **How to Drop a Schema in Postgres?**

A particular schema can be dropped from a database using the DROP SCHEMA command, as shown in the following syntax:
    
    
    DROP SCHEMA name_of_schema;

###  **Example 1: Removing a Postgres Schema Using psql**

In the following example, the “DROP SCHEMA” command is used to remove the “example” schema:
    
    
    DROP SCHEMA example;

Use the “\dn” command to verify the schema’s removal:
    
    
    \dn;

The selected schema has been removed successfully.

###  **Example 2: Removing a Postgres Schema Using pgAdmin**

Right-click on the schema to be removed from the list of available schemas and select either DELETE or DELETE (CASCADE) option to drop the unwanted schema:

Doing so will prompt a confirmation message, click on the "Yes" option to get rid of the selected schema:

##  **How to Modify the Schema Path in PostgreSQL**

In Postgres, “public” is the default schema; however, it can be changed using the “SET SEARCH_PATH” command:
    
    
    SET SEARCH_PATH TO 'name_of_schema';

###  **Example: Setting a Schema**

The “SHOW SEARCH_PATH” command is used to see the current schema:
    
    
    SHOW SEARCH_PATH;

To change the “public” schema to “postgres_schema”, use the following command:
    
    
    SET SEARCH_PATH TO 'postgres_schema';

Let’s check the current schema via the following command:
    
    
    SHOW SEARCH_PATH;

The current schema has been changed for the current session.

> Read the following guide to learn how to change the default schema permanently.

##  **Conclusion**

Postgres offers various built-in commands, such as **CREATE SCHEMA, ALTER SCHEMA,** and **DROP SCHEMA** , to create, modify, and drop the Postgres schemas. Use the “ **\dn** ” command to show the available schemas. To alter/change the default schema, users must execute the SET SEARCH_PATH command followed by the schema name. This post presented a comprehensive guide on Postgres schemas using practical examples.

---
[View this page online](https://www.commandprompt.com/education/comprehensive-guide-postgresql-schema/)

---

# Comparison Operators in PostgreSQL

> PostgreSQL offers a wide range of comparison operators, including basic and advanced ones, such as =, &lt;, &lt;&gt;, BETWEEN, IN, etc.

**Comparison operators** in PostgreSQL are used for comparing values and determining whether they meet certain conditions/criteria. Postgres offers a wide range of basic and advanced comparison operators to compare values logically. Using these operators you can determine if a value is equal to, less than, greater than, check the existence of some value, etc.

This post will explain the usage of some basic and advanced comparison operators in Postgres via practical examples. So, let’s start!

##  **Comparison Operators in PostgreSQL**

Postgres offers various comparison operators, for example, =, <, !=, <=, etc. Postgres also provides advanced comparison operators, such as the BETWEEN operator to check if a value is within a range, the IN operator to check if a value belongs to a list of values, and so on. Postgres offers the following comparison operators:

  1.  **“=”:** The “equal” operator in Postgres is used to check the equality.
  2.  **“!=”:** The “not equal” operator opposes the working of the equal operator.
  3.  **“ <>”:** Works the same way as **“!=”**.
  4.  **“ >”:** The “greater than” operator is used for finding the greater/maximum value.
  5.  **“ >=”:** Finds a value greater than or equal to the specified/given value.
  6.  **“ <”:** Finds the less/minimum value.
  7.  **“ <=”:** Finds a value less than or equal to the given/specified value.
  8. [ **BETWEEN**](<https://www.commandprompt.com/education/how-to-use-between-operator-in-postgresql/>): Finds a value within the specified range.
  9. [ **LIKE**](<https://www.commandprompt.com/education/postgresql-pattern-matching-like-vs-not-like-vs-ilike/>) **:** Performs pattern matching.
  10.  **IS NULL** **:** Checks a null value.
  11.  **IS NOT NULL** **:** Checks a non-null value.
  12. [ **IN**](<https://www.commandprompt.com/education/how-to-use-in-operator-in-postgresql/>) **:** Check if a value belongs to a list of values.
  13.  **NOT:** Retrieves the opposite results for the specified condition.



Let's put these operators into practice and see how they work.

###  **Example 1: How to Use = Operator in Postgres?**

We have already created a table named “emp_information”, whose data is shown in the following snippet:
    
    
    SELECT * FROM emp_information;

Suppose we want to find the name of an employee whose salary equals “4000”. For that, we will use the “=” operator as follows:
    
    
    SELECT emp_name 
    FROM emp_information
    WHERE emp_salary = 4000;

The output proves the working of the equal “=” operator.

###  **Example 2: How to Use <> Operator in Postgres?**

In this example, we will use the not equal to operator to fetch those employees whose salary is not equal to “4000”:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary <> 4000;

The output proves the working of the not-equal operator in Postgres.

###  **Example 3: How to Use Greater Than > Operator in Postgres?**

Let’s learn how the greater-than operator works in Postgres:
    
    
    SELECT emp_name, emp_salary
    FROM emp_information
    WHERE emp_salary > 4000;

The above query will retrieve the names of the employees whose salary is greater than “4000”:

The output proves the working of the greater than “>” operator.

###  **Example 4: How to Use Less Than or Equal to <= Operator in Postgres?**

This example will show you the working of the “<=” operator:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary <= 4000;

This way, the “less than or equal to” operator works in Postgres.

###  **Example 5: How to Use Between Operator in Postgres?**

Suppose we want to fetch all those employees whose salary is greater than “3800” but less than “5000”. For this purpose, we will use the BETWEEN operator as follows:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary BETWEEN 3800 AND 5000;

The output proves the working of the BETWEEN operator.

###  **Example 6: How to Use NOT Operator in Postgres?**

Using the NOT operator with the BETWEEN operator will negate the original result of the BETWEEN operator:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary NOT BETWEEN 3800 AND 5000;

The above snippet proves the working of the NOT operator in Postgres.

###  **Example 7: How to Use IN Operator in Postgres?**

Let’s learn how to use the IN operator in Postgres via the following example:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary IN(3800, 3851, 4500, 5000);

The IN Operator will check the existence of the specified values in the emp_salary column:

The output snippet authenticates the working of the IN operator.

###  **Example 8: How to Use IS NOT NULL Operator in Postgres?**

The below-specified query will retrieve the non-null values from the “ **emp_salary** ” column:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary IS NOT NULL;

Similarly, you can use the “IS NULL” operator, to find the null values in the specified column/expression.

###  **Example 9: How to Use LIKE Operator in Postgres?**

Use the LIKE operator to find the employees whose name starts with “J”:
    
    
    SELECT *
    FROM emp_information
    WHERE emp_name LIKE 'J%';

The output shows that the LIKE operator retrieves the data of all those employees whose name starts with the letter “J”;

That’s all from this guide!

##  **Conclusion**

PostgreSQL offers a wide range of comparison operators, including basic and advanced ones, such as =, <, <>, BETWEEN, IN, etc. In Postgres, comparison operators are used for comparing values and determining whether they meet certain conditions/criteria. This blog explained the working of various comparison operators using practical examples.

---
[View this page online](https://www.commandprompt.com/education/comparison-operators-in-postgresql/)

---

# PostgreSQL INTEGER Data Type With Examples

> In PostgreSQL, the INTEGER data type facilitates the user to store the numerical data between the range of -2,147,483,648 to +2,147,483,647 numbers.

PostgreSQL provides the **INTEGER** or **INT** data type that occupies 32-bit(4 bytes) of memory. It is the common data type that is utilized for storing numeric values. Its range starts from -2,147,483,648 to +2,147,483,647 numbers. The INTEGER data type is classified into multiple types, i.e., **INTEGER** , **BIGINT**, and **SMALLINT**. These data types have different storage sizes and ranges for storing numeric values. Users can not store the values that exceed the allocated range of a particular data type otherwise they will encounter an error.

Today, we will guide you about the Postgres INTEGER data type along with different examples. Let's start with the first example.

##  **How to Use INTEGER | INT Data Type in Postgres**

You must follow the below-given syntax to create a table column with INTEGER data type:
    
    
    CREATE TABLE tableName(
    columnName INTEGER constraint
    );

###  **Step 1: Create a Column With INTEGER Data Type in PostgreSQL**

First of all, let’s create a table in the PostgreSQL database using the “ **CREATE TABLE** ” statement:
    
    
    CREATE TABLE school_info( 
    std_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    fee INT NOT NULL);

The table consists of three columns: std_id, name, and fee. The std_id and fee columns are initialized with the **INTEGER** data type to store the numerical values while the name column is of type TEXT:

Now, you can verify the table's structure through the “ **SELECT** ” statement, as follows:
    
    
    SELECT * FROM school_info;

The output shows that the “ **std_id** ”, “ **name** ” and “ **fee** ” columns have been created with integer, text, and integer data types, respectively.

###  **Step 2: Insert INTEGER Data to a Table in PostgreSQL**

This section illustrates how to use the “ **INSERT INTO** ” statement to add values in the integer-type columns like “ **std_id** ” and “ **fee** ” columns:
    
    
    INSERT INTO school_info(std_id, name, fee)
    VALUES(1, 'Peter', 4500),
    (2, 'Harry', 2000),  
    (3, 'Willey',5000), 
    (4, 'Henry', 1700),
    (5, 'John', 5000);

The integer values have been successfully inserted in the “ **std_id** ” and “ **fee** ” columns of the table. To display all values of the table, use the “ **SELECT *** ” statement followed by the table name as shown in the below statement:
    
    
    SELECT * FROM school_info;

This way, users can insert the integer data into any specific table.

##  **How to Perform Mathematical Operations on INTEGER Data Type**

You can invoke built-in mathematical methods and operators to perform different functionalities on the integer data. For example, you can use operators like "+", "-", "/", etc., to perform basic arithmetic operations. Similarly, you can employ methods like FACTORIAL(), MOD(), ABS(), etc., to perform intermediate to advanced mathematical operations. Let's consider a code example to learn the working of these methods and operators on INT data type.

###  **Example: Performing Mathematical Operations on INTEGERS**

In the below code, we use the built-in "DIV()" function to half the students' free. Also, we use the "+" operator to add 500 hundred in the fee column:
    
    
    SELECT *, 
    DIV(fee, 2) AS half_fee, 
    fee + 500 AS modified_fee
    FROM school_info;

Let's execute the code and see how the stated operators and methods work in Postgres:

This is how the integer/int data type works in Postgres.

##  **Conclusion**

In PostgreSQL, the INTEGER data type is used to store the numerical data between the range of -2,147,483,648 to +2,147,483,647 numbers. This data type is most widely utilized for storing numbers in tables. This article has explained the usage of INTEGER data type along with practical implementation in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/postgresql-integer-data-type-with-examples/)

---

# How to Create PostgreSQL Tables With psql and pgAdmin

> In PostgreSQL, a table is used to organize the complex, detailed, and unordered data. A table can be created using the &quot;CREATE TABLE&quot; statement.

Tables in any database, including **PostgreSQL** , are used to organize or summarize complex, detailed, and unordered data. To create a table in **PostgreSQL** , the first step is creating a database and [selecting](<https://commandprompt.com/education/how-to-selectaccess-a-database-in-postgresql/>) the desired one. Once a database is created, you can create a table of your choice and perform multiple operations on that table like insertion, deletion, searching, and updating. A table in **PostgreSQL** stores the data in a structured way, i.e. in the form of rows and columns.

In this write-up, you will learn how to create a table in PostgreSQL using pgAdmin, and SQL SHELL(psql).

##  **How to Create a Table Using SQL SHELL(psql)**

You can execute/run the **“CREATE TABLE”** command from the **SQL SHELL** for creating a table in **PostgreSQL**. Here is the basic syntax for table creation using psql:
    
    
    CREATE TABLE table_name(
    first_column data_type,
    second_column data_type,
    third_column data_type,
    .....
    nth_column data_type
    );

Here,

  *  **“CREATE TABLE”** is a statement that creates a table.
  * table_name is a user-defined table’s name.
  * first_column, second_column, and nth_column are the names of the columns.
  * data_type represents the column type; it can be any type like int, String, char, etc.



>  **Note:** The table name must be unique and table columns must be separated using a comma.

###  **What are the Parameters of the CREATE TABLE Command?**

The **CREATE TABLE** statement can accept some parameters to perform different functionalities. The table below will illustrate some of the most commonly used parameters of the **“CREATE TABLE”** statement:

  *  **If not exists:** It shows a notice/warning instead of throwing an error.
  *  **Temp/Temporary:** It generates a temporary table.
  *  **Unlogged:** It is used to create an unlogged table. It doesn’t specify the data in the write-ahead log.



Let's go through the below-listed examples to create a table in **PostgreSQL** using **SQL SHELL (psql).**

###  **Example 1: Create a New Table**

Let’s execute the “\l” command to check the list of available databases:
    
    
    \l

 **Step 2: Select Database**

You can select the database by executing the **"\c"** command:
    
    
    \c example

The command mentioned above will select the requested database, i.e., **“example”** :

 **Step 3: Create Table**
    
    
    CREATE TABLE staff_details(
    id int PRIMARY KEY, 
    name VARCHAR(40),
    designation VARCHAR(50),

In the above-given table:

  *  **CREATE TABLE** is a predefined command to create a new table.
  * staff_details is a user-defined table name.
  * id, name, and designation are user-defined column names.
  * int is a data type.
  *  **PRIMARY KEY** is a predefined reserved keyword that makes a column a unique identifier.
  *  **VARCHAR** is a character data type that stores limited characters.



Let’s execute this statement in SQL SHELL(psql):

 **Step 4: List of Tables**

Let’s verify whether the table has been created or not. To do that, type the **“\d”** command:
    
    
    \d

The above snippet verified that a table named **“staff_details”** had been created successfully.

 **Step 5: Describe the Created Table**

Type the **“\d”** command followed by the table name to describe the details of a specific table:
    
    
    \d staff_details;

###  **Example 2: Create a Duplicate Table and Fix the “Relation Already Exists” Error**

Let’s recreate an existing table:
    
    
    CREATE TABLE staff_details(
    id int PRIMARY KEY, 
    name VARCHAR(40),
    designation VARCHAR(40),

An error occurs stating that the “table/relation already exists”:

We can specify/use the **"IF NOT EXISTS"** parameter to fix the stated error:
    
    
    CREATE TABLE IF NOT EXISTS staff_details(
    id int PRIMARY KEY, 
    name VARCHAR(40),
    designation VARCHAR(40),

The above snippet verified that this time a notice/warning occurred instead of an error.

###  **Example 3: Create a TEMP Table**

The CREATE TABLE statement can be executed with the “TEMP” clause to create a table for the current session only. The temp/temporary table automatically dropped/deleted once the current session expired:
    
    
    CREATE TEMP TABLE test_info(
    test_id SERIAL PRIMARY KEY,  
    std_name TEXT,
    score INT);

A temporary table has been successfully created:

>  ** _Note:_** _A temporary/temp table can have the same name as a normal Postgres table._

This is how we can utilize the parameters along with the **“CREATE TABLE”** statement to achieve different functionalities.

##  **How to Create a Table Using pgAdmin**

You can use the pgAdmin to create a table manually or using SQL queries. To create a table via Postgres queries, open the pgAdmin, enter your password, select the database, launch the query tool, and finally execute the CREATE TABLE command.

Follow the below-given procedure to create a table in **PostgreSQL** using **pgAdmin (** manually **)** :

 **Step 1: Select the Database**

Firstly, open the **pgAdmin** and select the desired database:

Choose the database where you want a table to be created.

 **Step 2: Select the Schema**

Click on the **“schemas”** under the selected database:

 **Step 3: Create Table**

Now right-click on the **“public”** , then left-click/hover on the **“create”** option, and finally click on the **“Table...”** , as shown in the below snippet:

Consequently, the following window will appear:

 **Step 4: Enter Table Details**

Specify the table name under the **“General”** tab:

Now, open the columns tab to specify more details:

Click on the **“+”** sign to add a new row, insert the relevant details in each row, and finally click on the **“Save”** button.

 **Step 5: Resultant Output**

Scroll down a little bit to reach the “tables” section. You will see that the specified table has been created successfully:

Click on the **“SQL”** tab to open the resultant query created for the **“staff_details”** table.

##  **Conclusion**

In **PostgreSQL** , a table can be created using SQL SHELL (psql) or pgAdmin. To create a table using SQL query, execute the **"CREATE TABLE"** command in psql or pgAdmin's Query tool. To create a table manually using **pgAdmin** , follow the steps appropriately as described in this write-up. This post has explained some table creation methods in **PostgreSQL** using relevant screenshots.

---
[View this page online](https://www.commandprompt.com/education/different-methods-to-create-a-table-in-postgresql/)

---

# PostgreSQL JSON Data: How it Works

> The term “JSON” is the acronym for “JavaScript Object Notation”. It is an open standard format for transferring data between a server and web apps. Postgres offers various operators and functions to manipulate the JSON data.

PostgreSQL is a famously used relational database that stores and manipulates data securely, effectively, and effortlessly. It uses different data types to store the data, such as INT, CHAR, TEXT, etc. Other than these commonly used data types, it offers some special types to achieve specific tasks. One such data type is JSON which stores the data in the form of key-value pairs. The term “JSON” is the acronym for “JavaScript Object Notation”. It is an open standard format for transferring data between a server and web apps. Postgres offers various operators and functions to manipulate the JSON data.

This post will demonstrate how to work with JSON data in PostgreSQL. In this regard, this blog will discuss the following topics:

  *  **How to Define a Table’s Column With JSON**
  *  **How to Insert Data into a JSON Field/Column**
  *  **How to Query JSON Data in PostgreSQL**
  *  **How to Query JSON Data Using JSON Operators**
  *  **How to Get a Specific Node From a JSON Object in PostgreSQL**
  *  **How to Filter JSON Data in PostgreSQL**
  *  **How Do Aggregate Functions Work With the JSON Data?**



##  **How to Define a Table’s Column With JSON**

To create a table’s column with JSON data type, you can specify the column’s name followed by the “JSON” data type:
    
    
    col_name JSON;

In the following example, we create a table named “order_details” with two columns: “o_id” and “o_details”:
    
    
    CREATE TABLE order_details(
    o_id SERIAL PRIMARY KEY,
    o_details JSON
    );

The “o_details” column will accept JSON data:

The table named “order_details” with a JSON column has been created.

##  **How to Insert Data into a JSON Field/Column**

The “ **INSERT INTO** ” statement is used in Postgres to insert **JSON** data into a specific table’s column. However, make sure that the data to be inserted is in a valid JSON format (i.e., key-value pairs):
    
    
    INSERT INTO order_details(o_details)
    VALUES
    ('{ "cust_name": "Joseph", "pro_description": {"pro_name": "Laptop","qty": 1}}'),
    ('{ "cust_name": "Joe", "pro_description": {"pro_name": "Charger","qty": 3}}'),
    ('{ "cust_name": "Mike", "pro_description": {"pro_name": "Keyboard","qty": 2}}'),
    ('{ "cust_name": "Stephen", "pro_description": {"pro_name": "Mouse","qty": 4}}'),
    ('{ "cust_name": "Kane", "pro_description": {"pro_name": "USB Flash Drives","qty": 5}}');

The output snippet verifies that the JSON data has been inserted into the selected Postgres table.

##  **How to Query JSON Data in PostgreSQL**

You can use/execute the below-provided query to fetch the data from the “order_details” table:
    
    
    SELECT * FROM order_details
    ORDER BY o_id ASC;

To query only JSON column/data from the selected table, you can use the SELECT query as follows:
    
    
    SELECT o_details FROM order_details;

The output signifies that the SELECT query retrieves the data from the JSON column.

##  **How to Query/Fetch JSON Data Using JSON Operators**

A couple of native operators are used in PostgreSQL to get a JSON object or a specific node. For instance, the short arrow “->” retrieves the JSON object by “key”, while the “->>” operator retrieves the JSON object by “text”.

In the following code snippet, we utilize the “->” operator to get the product description in the form of JSON:
    
    
    SELECT o_details -> 'cust_name' As Names
    FROM order_details;

The output snippet signifies that the “->” operator retrieves the data in JSON format. Replacing the “->” operator with the “->>” operator will retrieve the data in text format:
    
    
    SELECT o_details ->> 'cust_name' As Names
    FROM order_details;

The output snippet shows that the “->>” operator retrieves the data in TEXT format.

##  **How to Get a Specific Node From a JSON Object in PostgreSQL**

To get a specific node from a JSON object, you must use the “->” and “->>” operators together. The “->” operator will retrieve a JSON object while the “->>” operator will retrieve a specific node from that object. For instance, we utilize the “->>” operator that will retrieve a JSON object:
    
    
    SELECT o_details -> 'pro_description' As product_info
    FROM order_details;

Now, we will use the “->>” operator with the “->” operator to get only the “pro_name” node from the given JSON object:
    
    
    SELECT o_details -> 'pro_description' ->> 'pro_name' As product_name
    FROM order_details;

This way, you can access a specific node of a JSON object.

##  **How to Filter JSON Data in PostgreSQL**

You can use the JSON operators, such as short arrow and long arrow along with the WHERE clause to filter the result set of a query (JSON Data). For instance, in the following example, we will filter the result set to find out the customer names who bought a “laptop” or “USB Flash Drives”:
    
    
    SELECT o_details -> 'cust_name' As customer_name
    FROM order_details
    WHERE o_details -> 'pro_description' ->> 'pro_name' = 'Laptop' OR 
    o_details -> 'pro_description' ->> 'pro_name' = 'USB Flash Drives';

The output snippet demonstrates that the JSON operators retrieve the filtered data based on the specified condition.

##  **How Do Aggregate Functions Work With the JSON Data?**

Postgres allows us to use aggregate functions on the JSON data to achieve different functionalities. Suppose we want to calculate the most sold product, least sold product, average sold product, and total sold products. For this purpose, we will use the aggregate functions, as follows:
    
    
    SELECT 
    MAX (CAST (o_details -> 'pro_description' ->> 'qty' AS INTEGER)) AS most_sold,
    MIN (CAST (o_details -> 'pro_description' ->> 'qty' AS INTEGER)) AS least_sold,   
    AVG (CAST (o_details -> 'pro_description' ->> 'qty' AS INTEGER)) AS average_sold,
    SUM (CAST (o_details -> 'pro_description' ->> 'qty' AS INTEGER)) AS total_sold
    FROM order_details;

In the above snippet, the CAST operator is utilized to convert the data type of the “pro_description” column to INTEGER. The aggregate functions MAX(), MIN(), AVG(), and SUM() are used to find the most sold product, least sold product, average sold product, and total sold products, respectively.

This is how the Aggregate functions work with the JSON data.

>  **Important: Go through the** **linked article** **to learn more about JSON Functions and Operators.**

##  **Conclusion**

 **The JSON data type in PostgreSQL stores the data in the form of key-value pairs.** To create a table’s column with JSON data type, you can specify the column’s name followed by the “JSON” data type like this: "col_name JSON". You can use the JSON operators and functions to manipulate the JSON data efficiently.

This blog has covered the basics of the JSON data type, such as how to create a JSON data type, how to insert data into a JSON column, how to query JSON data, etc.

---
[View this page online](https://www.commandprompt.com/education/working-with-postgresql-json-data/)

---

# Understanding PostgreSQL Arrays

> Understanding PostgreSQL Arrays Understanding With Examples

Arrays play a very significant role in a database like PostgreSQL. Postgres provides the flexibility to create arrays of any data type, such as INT[], TEXT[], and more. It allows us to define a table’s column as an array of any built-in, user-defined, or enumerated data type.

To import the array-related capabilities, PostgreSQL offers several array manipulation functions that serve different functionalities on the arrays.

##  **Quick Outline**

This write-up will demonstrate the below-listed concepts related to PostgreSQL arrays with examples:

  *  **How to Create Arrays in PostgreSQL**
  *  **How to INSERT Data Into Arrays in PostgreSQL**
  *  **How to Fetch Arrays Data in PostgreSQL**
  *  **How to Filter Array Records Based on Specific Criteria**
  *  **How to Update Arrays Data in PostgreSQL**
  *  **How to Search a Specific Record Within an Array**
  *  **What Does Array Expansion Mean in PostgreSQL**



Let’s start with the array creation.

##  **How to Create Arrays in PostgreSQL**

You can create arrays in PostgreSQL by specifying the column name followed by the column’s type and a couple of square brackets. The below snippet will assist you in this regard:
    
    
    CREATE TABLE tab_name(
    col_name data_type[],
    );

Let’s describe the syntax stepwise:

  * CREATE TABLE is a command to create a table.
  * tab_name and col_name are the user-defined table and column names, respectively.
  * data_type represents the array type such as TEXT, INT, etc.
  * The square brackets represent that it’s an array.



###  **Example: How to Create an Array in PostgreSQL**

Let’s create a table named student_details using the CREATE TABLE command:
    
    
    CREATE TABLE student_details(
    std_id INT NOT NULL,
    std_name TEXT,
    std_email TEXT[]
    );

The above query will create a student_details table with three columns: std_id, std_name, and std_email. **A student can have more than one email id, so we created a string array named std_email** :

Let’s validate the table creation using the SELECT statement:
    
    
    SELECT * FROM student_details;

The above snippet shows that the three columns with their respective types have been created successfully.

##  **How to INSERT Data Into Arrays in PostgreSQL**

To insert the data into the student_details table, we will run the INSERT INTO command as follows:
    
    
    INSERT INTO student_details(std_id, std_name, std_email) 
    VALUES
    (1, 'Ambrose', '{"ambrose123@gmail.com", "ambrose123@hotmail.com"}'),
    (2, 'Alex', '{"alex123@gmail.com", "alex123@hotmail.com"}'),
    (3, 'John', '{"john123@gmail.com"}'),
    (4, 'Mike', '{"mike@gmail.com"}');

Four rows have been inserted into the student_details table:

In the above query, we inserted the array’s data using curly brackets; however, we can insert the data using the “ARRAY” constructor as well.

For a better understanding, let’s insert two more rows into the student_details table using the ARRAY constructor as follows:
    
    
    INSERT INTO student_details(std_id, std_name, std_email)
    VALUES (5, 'Joe', ARRAY['joe123@gmail.com','joe123@hotmail.com']),
    (6, 'Seth', ARRAY['seth123@gmail.com']);

Two more rows have been inserted into the student_details table.

##  **How to Fetch Arrays Data in PostgreSQL**

You can run the select statement to fetch/show the array’s data from the selected table, i.e., "student_details":
    
    
    SELECT std_name, std_email
    FROM student_details;

The output indicates that the array’s data is enclosed in the curly braces:

Also, you can fetch the data of specific array indexes as follows:
    
    
    SELECT std_name, std_email[1]
    FROM student_details;

In PostgreSQL, array indexing starts from 1st index, so specifying the std_email[1] will fetch only the first email address of each student:

  
This way, you can get the array data from a specific array index.

##  **How to Filter Array Records Based on Specific Criteria**

You can use the WHERE clause along the select command to filter the array’s data based on specific criteria. Suppose we have to fetch the std_id of a student whose second email address is “joe123@hotmail.com”:
    
    
    SELECT std_id
    FROM student_details
    WHERE std_email [2] = 'joe123@hotmail.com';

This is how you can filter the array's data based on a specific array column.

##  **How to Update Arrays Data in PostgreSQL**

You can use the UPDATE command to update/modify only a specific or all the array elements. Suppose we want to update the email address of Mike from “joe123@hotmail.com” to “joe123@yahoo.com”. To do that, we will run the update command as follows:
    
    
    UPDATE student_details
    SET std_email[2] = 'joe123@yahoo.com'
    WHERE std_id = 5;

You can verify the updated record via the SELECT query, as follows:

If you want to update all the array indexes of the selected record, specify the records to be updated in the curly brackets, as follows:
    
    
    UPDATE student_details
    SET std_email = '{joe123@abc.com, joe456@abc.com}'
    WHERE std_id = 5
    RETURNING *;

We use the RETURNING * statement to retrieve the updated records:

This way, you can update any array record using the update query.

##  **How to Search a Specific Record Within an Array**

PostgreSQL allows us to search any specific record regardless of the element’s position in the array. To do that, we can use the Postgres ANY() function.

The student_details table has the following records:
    
    
    SELECT * FROM student_details;

Now use the ANY() method to find the student whose ID is "alex123@gmail.com" as follows:
    
    
    SELECT std_name, std_id
    FROM student_details
    WHERE 'alex123@gmail.com' = ANY(std_email);

The output proves that the ANY() function offers the desired results.

##  **What Does Array Expansion Mean in PostgreSQL?**

The process of splitting the array values into rows is known as array expansion. To do this, Postgres provides a built-in function named **unnest()**.

In the student_details table, we observed that some students contain more than one email address. Suppose we have to split them into various rows. To achieve this purpose, we will utilize the unnest() function as follows:
    
    
    SELECT std_id, std_name,
    unnest(std_email)
    FROM student_details;

From the result set, you can observe that the array elements have been split into the rows successfully:

That's it! You have learned all the required information about PostgreSQL arrays.

##  **Conclusion**

PostgreSQL allows us to create an array of any data type such as INT[], TEXT[], CHARACTER[], etc. Once an array is created in PostgreSQL, you can perform different functionalities on that array, such as data insertion, data fetching, filtering the array data, etc. Moreover, you can use the array manipulation functions to perform different functionalities on the arrays. This post provided an in-depth overview of the PostgreSQL arrays using examples.

---
[View this page online](https://www.commandprompt.com/education/understanding-postgresql-arrays-with-examples/)

---

# PostgreSQL CREATE DATABASE IF NOT EXISTS

> Postgres doesn’t support the “IF NOT EXISTS” option for the CREATE DATABASE command. To achieve the functionality of the “IF NOT EXISTS” option, a subquery can…

In Databases like MySQL, you can use the **“IF NOT EXISTS”** option with the **CREATE DATABASE** command to create a database only if it doesn’t exist already. However, PostgreSQL doesn’t support the **“IF NOT EXISTS”** option for the **CREATE DATABASE** statement. But thankfully Postgres supports an alternative to the "IF NOT EXISTS" option.

You can use the subqueries to achieve the functionality of the **“IF NOT EXISTS”** option. So, let’s learn how to create a database that doesn’t exist.

##  **PostgreSQL CREATE DATABASE IF NOT EXISTS**

While creating a database in Postgres, users often encounter an error "Database already exists" that occurs if a database with the defined name already exists.

A query that appears/comes within another query is referred to as a subquery. You can use a subquery to create a non-existing database without encountering the mentioned error. Let's understand how to do it using the below syntax:
    
    
    SELECT 'CREATE DATABASE <db_name>'
    WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '<db_name>')\gexec

In this syntax, the NOT EXISTS is used within the WHERE Clause, which will check the existence of a targeted database. If the specified database doesn’t exist, then the sub-query will retrieve “True”. In such a case, the CREATE DATABASE statement will execute, and the non-existing database will be created.

>  **Note:** \gexec parameter runs the just-entered statements and sends each field as an SQL command to the server instead of printing the output.

Let’s understand it via practical examples.

###  **Example: How to Create a Non-existing Database in PostgreSQL**

This example explains how to achieve the functionality of the **“CREATE DATABASE IF NOT EXISTS”** via subquery. To do so, you need to follow the below-listed stepwise instructions:

###  **Step 1: List Databases**

To get the list of available databases, users must run the “\l” command:
    
    
    \l

The output shows all the available databases:

###  **Step 2: CREATE DATABASE IF NOT EXISTS**

Let’s create a non-existing database named “ **exp_db** ” via the following command:
    
    
    SELECT 'CREATE DATABASE exp_db' 
    WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'exp_db')\gexec

The output authenticates that the database named **exp_db** has been created successfully:

###  **Step 3: Verify Databases**

You can verify the database’s creation by executing the following command:
    
    
    \l

The output verifies that the desired database has been created successfully:

###  **Step 4: Create Already Existing Database**

Let’s try to create a new database with the same name and see how Postgres deals with such situations:
    
    
    SELECT 'CREATE DATABASE exp_db' 
    WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'exp_db')\gexec

When we executed the above statement, it didn’t perform any action. This proves that the “exp_db” already exists, so it can’t be created again:

That's all from this Postgres blog post.

##  **Conclusion**

Postgres doesn’t support the **“IF NOT EXISTS”** option for the **CREATE DATABASE** command. To achieve the functionality of the **“IF NOT EXISTS”** option, a subquery can be used in Postgres. For this purpose, you can specify the **NOT EXIST** operator in the WHERE clause to check if the desired database already exists. If the given database doesn’t exist, then the sub-query will retrieve “ **True** ”. In such a case, the **CREATE DATABASE** statement will execute, and the non-existing database will be created. This blog post explained how to create a non-existing database in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-create-database-if-not-exists/)

---

# PostgreSQL Data Types Explained

> PostgreSQL is a versatile open-source relational database management system (RDBMS) that supports built-in as well as user-defined data types. These data types help us store, retrieve, and manipulate the data efficiently and effortlessly.

PostgreSQL is a versatile open-source relational database management system (RDBMS) that supports built-in as well as user-defined data types. These data types help us store, retrieve, and manipulate the data efficiently and effortlessly. However, selecting an appropriate/right data type is crucial. Are you finding it difficult to understand when and where to use which data type? No need to worry, because in this guide, we will solve all your issues related to data types, and that too with examples.

##  **Outline**

This blog will walk you through the following PostgreSQL data types using appropriate examples:

  *  **Numeric Data Types in PostgreSQL**
  *  **SERIAL Data Types**
  *  **Character Data Types**
  *  **Temporal Data Types**
  *  **Boolean Data Type**
  *  **Array Data Type**
  *  **JSON Data Type**
  *  **UUID Data Type**



Let’s begin with the Numeric data types.

##  **Numeric Data Types in PostgreSQL**

PostgreSQL offers several built-in data types to work with the numeric data, such as floating-point, integer, numeric, and serial. All of them differ in range and serve unique purposes. We will understand each of these data types using suitable examples.

###  **Integer Data Types**

[ **SMALLINT**](<https://www.commandprompt.com/education/postgresql-smallint-data-type-with-examples/>), [**INTEGER**](<https://www.commandprompt.com/education/postgresql-integer-data-type-with-examples/>), and [**BIGINT**](<https://www.commandprompt.com/education/postgresql-bigint-data-type-with-examples>) are the frequently used 2-byte, 4-byte, and 8-byte signed integer data types in PostgreSQL. The below table shows the storage size, minimum range, and maximum range of each integer data type:

The following example creates a table with different integer data types:
    
    
    CREATE TABLE student_info(
      student_Id INT PRIMARY KEY,
      student_Age SMALLINT,
      student_Name TEXT,
       );

The desired “student_info” table is successfully created with the “student_Id”, “student_Age”, and “student_Name” columns:

###  **Floating-point Data Types**

Postgres offers a couple of floating point data types to deal with the fractional values. These types include “ **DOUBLE PRECISION** ” and “ **FLOAT** ”. The “FLOAT” data type consumes 4 bytes while “DOUBLE PRECISION” consumes 8 bytes of storage. The following code uses the DOUBLE PRECISION data type to store the student marks:
    
    
    CREATE TABLE student_info(
      student_Id INT PRIMARY KEY,
      student_Marks DOUBLE PRECISION,
      );

###  **NUMERIC Data Type**

[ **NUMERIC**](<https://www.commandprompt.com/education/postgresql-numeric-data-type-with-practical-examples/>) data type allows us to store exact figures in the database. It is capable of storing a number with several digits. The NUMERIC type can accept two options: “precision” and “scale”. Where the precision indicates the total digits to store and the scale refers to the total digits in the fractional part. The following query creates a table named “emp_info” with two columns: “emp_Id” and “emp_salary”:
    
    
    CREATE TABLE emp_info(
      emp_Id INT PRIMARY KEY,
      emp_salary NUMERIC(6, 2),
       );

The emp_salary column will store a numeric value of 6 digits. Out of which the fractional part can have at max 2 digits. Now add/insert some new records into the emp_info table to get a better understanding:
    
    
    INSERT INTO emp_info(emp_id, emp_salary)
     VALUES (1, 1234.561234),
       (2, 880.45678),
       (3, 1234)
       RETURNING *;

From the output, you can observe that three values have been successfully inserted according to the specified scale and precision:

##  **SERIAL Data Types**

Postgres offers three SERIAL types that help us create auto-increment columns. These data types are “[ **BIGSERIAL**](<https://www.commandprompt.com/education/bigserial-smallserial-and-serial-data-types-in-postgresql/>)”, “[ **SMALLSERIAL**](<https://www.commandprompt.com/education/bigserial-smallserial-and-serial-data-types-in-postgresql/>)”, and “[ **SERIAL**](<https://www.commandprompt.com/education/postgresql-serial-how-to-create-auto-increment-columns/>)”. The storage range of these sudo types is different, as illustrated in the following table:

The main factor that differentiates the mentioned data types from each other is the range of numbers they can save/store. The BIGSERIAL data type can keep the largest range of values, which is followed by the SERIAL data type, and finally, the SMALLSERIAL type which stores the least range of values.

For example, the following query creates a table with the SERIAL and SMALLSERIAL pseudotypes:
    
    
    CREATE TABLE emp_info(
      emp_Id SERIAL PRIMARY KEY,
      emp_name TEXT 
       );

Let’s insert some records into the newly created table to understand how the SERIAL types work in PostgreSQL:
    
    
    INSERT INTO emp_info(emp_name)
     VALUES('Joseph'), ('John'), ('Seth');

The output shows that three auto-incrementing IDs have been successfully added to the emp_info table:

##  **Character Data Types**

Postgres supports three [**character types**](<https://www.commandprompt.com/education/postgresql-character-data-types-char-varchar-and-text/>): **CHAR** , **TEXT** , and **VARCHAR**. You can employ any of the mentioned types to store the textual data. The following table illustrates these data types with respect to different parameters:

>  ** _Note: In the fixed-length data types, exceeding the specified limit will result in a “value too long for type dataType” error._**

The below code block creates a table with four columns: “emp_Id”, “emp_name”, “gender”, and “address”:
    
    
    CREATE TABLE emp_details(
      emp_Id SERIAL PRIMARY KEY,
      emp_name TEXT,
      gender CHAR,
      address VARCHAR
       );

A table with the desired columns and data types is created successfully. Now you can insert data into this table and perform any data operation on it according to your preferences.

##  **Temporal Data Types**

In databases, date and time play a crucial role. Therefore, Postgres offers several temporal data types to work with date and time data. The commonly used temporal data types include time, date, interval, and timestamp. The [**DATE**](<https://www.commandprompt.com/education/postgresql-date-data-type-with-examples/>) **,** [**TIME**](<https://www.commandprompt.com/education/postgresql-time-data-type-with-examples/>) **,** and [**TIMESTAMP**](<https://www.commandprompt.com/education/how-to-insert-a-timestamp-into-a-postgresql-table/>) data types store the data in the “YYYY-MM-DD”, “HH:MI:SS”, and the “YYYY-MM-DD HH:MI:SS” formats, respectively. Let’s create a table with these data types to store the temporal data:
    
    
    CREATE TABLE student_details(
      std_Id SERIAL PRIMARY KEY,
      std_name TEXT,
      admission_date DATE,
      std_arrives_at TIME,
      std_leaves_at TIME,
      exam_starts_at TIMESTAMP,
      exam_duration INTERVAL
      );

The student_details table with seven columns is created successfully:

Let’s insert a record into this newly created table to get a better insight into temporal data types:
    
    
    INSERT INTO student_details(std_name, admission_date, std_arrives_at, std_leaves_at,   exam_starts_at, exam_duration)
     VALUES('Joseph', '2023-01-01', '08:30:45', '01:30:00', '2023-05-01 11:30:00', '3 hours')
     RETURNING *;

Here is what you will experience on successful execution of the stated query:

##  **Boolean Data Type**

The [**Boolean data type**](<https://www.commandprompt.com/education/postgresql-boolean-data-type-with-examples/>) is used in scenarios where we have only two possible outcomes, such as “Yes/No”, “True/False”, “0/1”, etc. For example, the following code will create a table “product_details” with three columns: pro_Id, pro_name, and is_availble. The is_availble is a boolean-type column that shows the availability of a product (it will be either true or false):
    
    
    CREATE TABLE product_details(
      pro_Id SERIAL PRIMARY KEY,
      pro_name TEXT,
      is_available BOOLEAN
       );

The table with the desired boolean column is created successfully:

We insert the data of two products and their availability:
    
    
    INSERT INTO product_details(pro_name, is_available)
     VALUES('Laptop', 'Yes'),
       ('Laptop Charger', 'No')
       RETURNING *;

The output shows that the product “Laptop” is available in the stock while “Laptop Charger” isn’t:

##  **Array Data Type**

If you want to store several values of the same type, then use the [**ARRAY data type**](<https://www.commandprompt.com/education/understanding-postgresql-arrays-with-examples/>). For example, a person can have multiple emails, multiple bank accounts, etc. In that cases, you can use the Postgres’ Array Data type:
    
    
    CREATE TABLE std_info (
      std_id SERIAL PRIMARY KEY,
      std_name VARCHAR(50),
      std_emails TEXT[] NOT NULL
       );

We create a text array for the std_emails:

Up next, we execute the insert query to insert the data of two students: “Joseph” and “John”:
    
    
    INSERT INTO std_info (std_name, std_emails)
     VALUES('Joseph', ARRAY ['joseph@joseph.com', 'joseph@xyz.com']),
       ('John', ARRAY ['john@john.com', 'john@xyz.com'])
       RETURNING *;

The output shows that the emails are inserted/stored in the text array “std_emails”:

##  **JSON Data Type**

The [**JSON data type**](<https://www.commandprompt.com/education/working-with-postgresql-json-data/>) allows us to insert the data in the form of key-value pairs. It is used when we have to keep/store complex data structures that can be serialized and deserialized, effortlessly.

The following code block creates a table “customer_info” with two columns: cust_id and product_info.
    
    
    CREATE TABLE customer_info (
      cust_id SERIAL PRIMARY KEY,
      product_info JSON
       );

Here the product_info is a JSON-type column:

Let’s insert a couple of JSON records to see how we can store key-value pairs in Postgres:
    
    
    INSERT INTO customer_info (product_info)
     VALUES('{ "cust_name": "Joseph", "product_purchased": {"product_name": "Laptop", "price": 40000, "quantity": 2}}')
     RETURNING *;

A JSON record has been successfully inserted and retrieved, as shown below:

##  **UUID Data Type**

Postgres supports some special data types that are not available in other DBMSs. “[UUID](<https://www.commandprompt.com/education/a-complete-guide-to-uuids-in-postgresql/>)” or “Universal unique identifier” is one of them that stores 128-bit unique identifier values. To use this data type first, you need to create its extension as it doesn’t come by default:
    
    
    CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Now create a customer_details table with a UUID-type column:
    
    
    CREATE TABLE customer_details (
      cust_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
      name TEXT
       );

Let’s insert the customer name into the name column of the customer_details table:
    
    
    INSERT INTO customer_details (name)
     VALUES('Joseph')
     RETURNING *;

An auto-generated unique identifier value is added to the UUID column:

>  ** _Important: Other than these built-in data types, you can also_** [**_create user-defined data types_**](<https://www.commandprompt.com/education/how-to-create-a-user-defined-data-type-in-postgresql/>) ** _using the CREATE DOMAIN and CREATE TYPE statements._**

##  **Conclusion**

PostgreSQL provides a wide range of data types, such as textual, numeric, and temporal, for efficient data storage and manipulation. The choice of any data type is aligned with your specific needs and preferences. However, choosing the right data type is crucial for better memory management, and maintaining data accurately and efficiently. Having a profound knowledge of data types enables a user to make the right decisions at the right moment. This way you can store and manipulate your data securely and effectively.

In this guide, we have exercised different Postgres data types along with appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-data-types-explained-with-examples/)

---

# PostgreSQL Aggregate Functions With Practical Examples

> To perform calculations on a set of rows, the aggregate functions are used. These functions perform calculations on the table rows and return only a single row…

**Aggregation** refers to the concept where a specific outcome is formed from the combination of several elements. In Postgres, aggregation is performed via different built-in methods, such as SUM(), AVG(), COUNT(), etc. All these methods serve a unique purpose, however, one thing is common in all of them i.e., accept multiple elements and return a single outcome.

The PostgreSQL aggregate functions allow us to compute/calculate a set of rows. These functions perform calculations on the table rows and return only a single row.

##  **Quick Outline**

Today, we will walk you through the following Postgres aggregate functions:

  1.  **PostgreSQL SUM() Function.**
  2.  **PostgreSQL COUNT() Function.**
  3.  **PostgreSQL AVG() Function.**
  4.  **PostgreSQL MAX() Function.**
  5.  **PostgreSQL MIN() Function.**
  6.  **PostgreSQL STRING_AGG() Function.**
  7.  **PostgreSQL ARRAY_AGG() Function.**
  8.  **PostgreSQL JSON_AGG() Function.**
  9.  **PostgreSQL JSONB_AGG() Function.**



This write-up will discuss each of the functions mentioned above through Practical examples. So, let's begin.

##  **PostgreSQL SUM() Function**

PostgreSQL provides a built-in **SUM()** function that is used to perform the addition on a set of values. The below snippet illustrates the syntax of the SUM() function:
    
    
    SUM(exp);

Here, “exp” represents an expression.

###  **Example: How to Use SUM() Function on Table’s Data?**

Let’s say we have a table bike_details. We will execute the SELECT query to fetch all the records of the bike_details table:
    
    
    SELECT * FROM bike_details;

Let’s perform the addition on the bike_price column using the SUM() Function:
    
    
    SELECT SUM(bike_price) AS total_price
    FROM bike_details;

The output authenticates that the SUM() function returns the sum of the bike_price column.

##  **PostgreSQL COUNT() Function**

The table rows can be counted using PostgreSQL's **COUNT()** function. In PostgreSQL, the COUNT() function is used to get all the rows, including duplicates and NULL. The below snippet illustrates the syntax of the Postgres COUNT(*) function:
    
    
    SELECT COUNT(*) 
    FROM tab_name;

The COUNT(*) function will fetch all the rows(including duplicates and NULL) from the targeted table based on the specified condition.

###  **Example: How Does the COUNT(*) Function Work in PostgreSQL?**

The bike_details table has some duplicated and null values. The following query will calculate the total number of rows in the bike_details table:
    
    
    SELECT COUNT(*) 
    FROM bike_details;

The output shows that the bike_details table has 10 rows. It proves that the COUNT(*) function counted all the rows, including the duplicates and null.

##  **PostgreSQL AVG() Function**

PostgreSQL provides a built-in [**AVG()**](<https://commandprompt.com/education/how-to-use-avg-function-in-postgresql/>) function that is used to retrieve the average of a set. The below snippet demonstrates the basic syntax of the AVG() function:
    
    
    AVG(col_name);

Let’s implement the AVG() function practically to get profound knowledge.

###  **Example: How to Use AVG() Function on Table’s Data?**

Let’s compute the average of the bike_price column using the AVG() Function:
    
    
    SELECT AVG(bike_price)
    FROM bike_details;

Let’s run the below query to get the average up to specific decimal places:
    
    
    SELECT AVG(bike_price)::numeric(10, 3) 
    FROM bike_details;

The above query will return the average of the bike_price column in an easily understandable format, i.e., the AVG() will return the result up to three decimal places:

Output proves the working of the AVG() function.

##  **PostgreSQL MAX() Function**

PostgreSQL offers a built-in **MAX()** function that is used to retrieve the maximum value of a set. The below snippet will show you the basic syntax of the MAX() function:
    
    
    MAX(exp);

Here, exp represents an expression. Let’s practically implement the MAX() function to get profound knowledge about it.

###  **Example: How to Use MAX() Function on Table’s Data?**

Let’s find the bike with the maximum price using the MAX() Function:
    
    
    SELECT MAX(bike_price)
    FROM bike_details;

The output shows that in the bike_details table, the most expensive bike costs 150000.

##  **PostgreSQL MIN() Function**

PostgreSQL offers a built-in MIN() function that retrieves a set's minimum value. The below snippet will show you the basic syntax of the MIN() function:
    
    
    MIN(exp);

Here, exp represents an expression. Let's implement it practically to understand the MIN() function in a better way.

###  **Example: How to Use the MIN() Function in Postgres?**

Let’s find the bike with the minimum price. To do that, we will use the Postgres MIN() Function:
    
    
    SELECT MIN(bike_price)
    FROM bike_details;

The output shows that the bike_details table's most cost-effective bike costs 80000.

##  **PostgreSQL STRING_AGG() Function**

 **STRING_AGG()** is a well-known Postgres aggregate function that accepts input data as an argument, creates a concatenated string, and returns it as output. It concatenates/combines the string values using a separator or delimiter, as shown in the below syntax.
    
    
    STRING_AGG ( exp, separator [ORDER BY ASC | DESC] )

Here, the “exp” can be a table’s column or an expression. The separator can be any valid separator/delimiter like a comma “ **,** ”, hyphen “ **-** ”, etc. Moreover, users can sort the aggregated data using the ORDER BY clause, however, it's optional(can be skipped).

###  **Example: How Does STRING_AGG() Work in Postgres?**

In this example, we will use the STRING_AGG() function to aggregate the bike numbers based on bike color:
    
    
    SELECT bike_color, STRING_AGG(bike_number, ',')
     FROM bike_details 
     GROUP BY bike_color;

Here, the **STRING_AGG()** function combines all the bike_numbers using a comma, and the GROUP BY clause groups the bikes based on bike colors:

Visit the following dedicated guide on the **STRING_AGG()** function to learn more about it with proper examples.

##  **PostgreSQL ARRAY_AGG() Function**

 **ARRAY_AGG()** is an aggregate function that helps us group/aggregate the data in an array. To do that, it accepts an expression (which can be an expression or a table’s column), aggregates the given data, and retrieves an array of given data. The data type of the retrieved array will be the same as of given data.
    
    
    ARRAY_AGG(exp, [ORDER BY [sort_exp | column_name {ASC | DESC}], [....]);

Users can use the ORDER BY clause to sort the aggregated data using the, however, it's optional and can be skipped.

###  **Example: How Does ARRAY_AGG() Work in Postgres?**

Execute the provided code to aggregate the values of the bike_model column of the bike_details table using the ARRAY_AGG() function:
    
    
    SELECT ARRAY_AGG(bike_model)
    FROM bike_details;

The ARRAY_AGG() function successfully aggregates the values of the bike_model column in an integer-type array (since the type of the provided column was INTEGER).

You can explore more use cases of the stated function by reading our dedicated guide on the [ARRAY_AGG()](<https://www.commandprompt.com/education/postgresql-array_agg-function-with-examples/>) function.

##  **PostgreSQL JSON_AGG() Function**

The [JSON_AGG()](<https://www.commandprompt.com/education/postgresql-json_agg-function-by-practical-examples/>) function accepts an expression/column, aggregates them, and retrieves a single JSON array. The return type of this function is JSON:
    
    
    JSON_AGG(exp)

Here, “exp” can be any valid expression or a table column.

###  **Example: How Does JSON_AGG() Work in Postgres?**

In the following code, the JSON_AGG() function is implemented on “bike_number” column of the “bike_details” table:
    
    
    SELECT JSON_AGG(bike_number)
    FROM   bike_details;

All bike numbers including null values are aggregated into a single array whose data type is “JSON”:

##  **PostgreSQL JSONB_AGG() Function**

The JSONB_AGG() function is also an aggregate function that works similarly to **JSON_AGG()**. The only difference is it retrieves a JSONB array instead of a JSON array.
    
    
    JSONB_AGG(exp);

The return type of this function is JSONB:

###  **Example:** **How Does JSONB_AGG() Work in Postgres?**

Let’s implement the **JSONB_AGG()** function on the same code to see how it works in Postgres:
    
    
    SELECT JSONB_AGG (bike_number)
    FROM bike_details;

From the output, you can observe that the stated function has returned a JSONB array:

That’s all about Postgres aggregate functions.

##  **Conclusion**

In PostgreSQL, we can perform computations/calculations on a set of rows using Postgres aggregate functions. These functions perform calculations on the table rows and return only a single row. This post has explained the working of several aggregate functions, including SUM(), COUNT(), AVG(), MAX(), MIN(), ARRAY_AGG(), etc., using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-aggregate-functions-with-practical-examples/)

---

# How to Use GROUP BY Clause in PostgreSQL

> The GROUP BY clause in PostgreSQL is used with the collaboration of the SELECT statement to group several rows/items.

In PostgreSQL, the **GROUP BY** clause executes with the collaboration of a **SELECT** statement to group several items. It groups rows with identical or corresponding data returned by the SELECT statement. In most cases, it is employed to eliminate redundancy and calculate aggregates. You can use the GROUP BY clause with various functions like SUM() and COUNT() to perform different functionalities on the grouped items.

##  **How to Use GROUP BY Clause in Postgres?**

PostgreSQL users can specify an individual or multiple columns in the **GROUP BY** clause. As a result, the stated clause groups the rows based on the values in those specified columns.

The below figure demonstrates the evaluation precedence of the GROUP BY clause:

  * The FROM clause and WHERE clause will come prior to the GROUP BY clause.
  * The HAVING, DISTINCT, ORDER BY, and LIMIT clauses will come after the GROUP BY clause.



 **Syntax**

Follow the comma-separated syntax to specify multiple columns within the GROUP BY clause:
    
    
    SELECT list_of_columns
    FROM tab_name
    GROUP BY col_1, col_2....col_N

Let’s illustrate the above syntax step-by-step:

  * Specify a column list in the SELECT statement that you want to group.
  * Replace “tab_name” with the table name to which the selected columns belong.
  * Replace the col_1, col_2, …, col_N with the columns to be grouped.



Let’s head into the practical implementation of the Postgres GROUP BY clause:

###  **Example 1: A Basic Example of GROUP BY Clause**

A table named "bike_details" has already been created that contains the following records:
    
    
    Select *  FROM bike_details;

The below-given query will get the record of the selected table, and it will group the result based on bike_model:
    
    
    SELECT bike_model FROM bike_details
    GROUP BY bike_model;

The output shows that the GROUP BY clause has eliminated the duplicated/redundant records.

###  **Example 2: GROUP BY With ORDER BY**

In Postgres, various clauses of the SELECT statement can be used with the GROUP BY clause, such as ORDER BY, WHERE, etc. In this example, we use the ORDER BY clause with the GROUP BY clause to sort and group the bike_model column in descending order:
    
    
    SELECT bike_model
     FROM bike_details
     GROUP BY bike_model
     ORDER BY bike_model DESC;

The output verified that this time the GROUP CLAUSE removed the redundant data and sorted the result-set in descending order.

##  **How to Use GROUP BY With Aggregate Functions**

Postgres users use the GROUP BY clause with the aggregate function to execute different tasks on the grouped data. Examples include calculating the sum or averages of group data.

###  **Example 1: GROUP BY With SUM()**

Let’s run the below-given query to find the sum of group items using the SUM() function:
    
    
    SELECT bike_model, SUM (bike_price)
     FROM bike_details
     GROUP BY bike_model;

In this example, we utilized the GROUP BY clause to group the bikes with respect to their model. Next, we utilized an aggregate function named sum() that calculated the sum of group items.

###  **Example 2: Postgres GROUP BY With COUNT()**

In this example, we use the COUNT() function to count the number of bikes available for each model:
    
    
    SELECT bike_model, COUNT (bike_model)
     FROM bike_details
     GROUP BY bike_model;

The output shows that in the result set, there are two bikes for the 2022 and 2021 models.

###  **Example 3: Postgres GROUP BY With AVG()**

The following code uses the AVG() function to compute the average price of bikes based on their models:
    
    
    SELECT bike_model, AVG(bike_price)
     FROM bike_details
     GROUP BY bike_model;

###  **Example 4: Postgres GROUP BY With STRING_AGG()**

Users often use the GROUP BY clause with the STRING_AGG() function to join values from multiple rows into a single string based on a specific grouping condition. Here is an example:
    
    
    SELECT bike_model, STRING_AGG(bike_color, ',')
     FROM bike_details
     GROUP BY bike_model;

The stated query will show the available bike colors for each bike_model:

###  **Example 5: Postgres GROUP BY With HAVING and an Aggregate Function**

In the following code, we use the SUM() function, the HAVING clause along the GROUP BY clause to find those bikes whose group sum is more than 200000:
    
    
    SELECT bike_model, SUM(bike_price)
     FROM bike_details
     GROUP BY bike_model
     HAVING SUM(bike_price) >= 200000;

###  **Example 6: Postgres GROUP BY With LIMIT and an Aggregate Function**

The following code uses the GROUP BY With LIMIT clause and SUM() function to group the bikes based on their models and find the sum of only three bike_model:
    
    
    SELECT bike_model, SUM(bike_price)
     FROM bike_details
     GROUP BY bike_model
     LIMIT 3;

That was all the basic information regarding the Postgres **GROUP BY** clause.

##  **Conclusion**

The **GROUP BY** clause in PostgreSQL is used with the collaboration of the SELECT statement to group several items. In this write-up, we have explained different use cases of the GROUP BY for various clauses, and aggregate functions. We have seen that the GROUP BY clause groups identical rows removes redundancy, and computes aggregates.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-group-by-clause-in-postgresql/)

---

# BIGSERIAL, SMALLSERIAL, and SERIAL Data Types in PostgreSQL

> In PostgreSQL, the main difference between the BIGSERIAL, SMALLSERIAL, and SERIAL is the range of numbers they can hold/store.

In PostgreSQL, **SERIAL** is a pseudo-type type that creates a column that automatically increments its value. When you specify SERIAL as the data type of a column, PostgreSQL automatically generates unique values for that particular column. PostgreSQL supports three types of SERIAL pseudotypes: **BIGSERIAL** , **SMALLSERIAL** , and **SERIAL**. All these data types differ in terms of range.

This post demonstrates how to override a SERIAL column in PostgreSQL using suitable examples.

##  **BIGSERIAL, SMALLSERIAL, and SERIAL Data Types in PostgreSQL**

The main parameter that distinguishes BIGSERIAL, SMALLSERIAL, and SERIAL is the range of numbers they can hold/store. BIGSERIAL can store the biggest range of values, followed by SERIAL, and then SMALLSERIAL.

  * The range of BIGSERIAL is "-9223372036854775808" to "9223372036854775807"
  * The SERIAL data type has a range of "-2147483648" to "2147483647"
  * The SMALLSERIAL has a range of "-32768" to "32767".



The choice of which pseudotype to use depends entirely on the specific requirements or preferences of the user.

Consider the following steps for a profound understanding of the SERIAL data types in Postgres:

###  **Step 1: Create Auto-Incrementing Columns**

Let’s first create auto-incrementing (SERIAL) columns. For this purpose, specify the desired pseudotype for a specific column at the time of table creation:
    
    
    CREATE TABLE command_prompt_1( 
    bigSerial_col BIGSERIAL,
    serial_col SERIAL PRIMARY KEY, 
    smallSerial_col SMALLSERIAL, 
    msg TEXT
    );

A table named “command_prompt” with the specified SERIAL data types has been successfully created:

###  **Step 2: Verify Column 's Default Value**

Execute the "\d" meta-command with the newly created table name to check the column's default value:
    
    
    \d command_prompt_1;

The serial types have been set as default values of the selected columns.

###  **Step 3: INSERT Data**

Now insert a couple of records in the command_prompt table by executing the following query:
    
    
    INSERT INTO command_prompt_1 (msg) 
    VALUES ('blog 1'), 
    ('blog 2'), 
    ('blog 3')
    RETURNING *;

The “RETURNING *” clause is utilized in the above query to get the newly inserted records. From the below-provided output snippet, you can observe that the SERIAL columns are automatically filled with the sequence of unique values:

That’s all about creating a column with SERIAL Data Types in PostgreSQL.

##  **Conclusion**

PostgreSQL supports three types of SERIAL pseudotypes: BIGSERIAL, SMALLSERIAL, and SERIAL. The main parameter that distinguishes BIGSERIAL, SMALLSERIAL, and SERIAL is the range of numbers they can hold/store. BIGSERIAL can store the biggest range of values, followed by SERIAL, and then SMALLSERIAL. The choice of which pseudotype to use totally depends on the user's needs. This write-up has demonstrated a complete guide on overriding a SERIAL column in PostgreSQL.

>  ** _Related Articles:_** _PostgreSQL SERIAL- How to Create Auto-increment Columns_ _,  
> _ Can a User Override a SERIAL Column in PostgreSQL?

---
[View this page online](https://www.commandprompt.com/education/bigserial-smallserial-and-serial-data-types-in-postgresql/)

---

# PostgreSQL - DATEADD - Add Interval to DateTime

> Postgres allows us to add intervals to date time using the “+” and “-” operators. This post demonstrated various examples of adding intervals to DateTime value…

In databases like SQL, MySQL, MariaDB, etc., users can add intervals to DateTime values using built-in functions. For instance, DATEADD() in SQL Server, DATE_ADD() in MySQL, ADDDATE() in MariaDB, etc. However, In Postgres, there is no such function that offers the same functionality. Now the question is how to Add intervals to the DateTime value in Postgres. Well! Nothing to worry about because Postgres allows us to add intervals to date time using the “+” and “-” operators.

This post will demonstrate:

  *  **How Do I Add an Interval to the Current Date in Postgres?**
  *  **How Do I Subtract/Deduct an Interval From the Current Date in Postgres?**
  *  **How to Add Intervals to Particular DateTime Values?**
  *  **How to Subtract Intervals From Particular DateTime Values?**
  *  **How to Add or Subtract an Interval From the Table’s Data?**



##  **How Do I Add an Interval to the Current Date in Postgres?**

In the following code snippet, the “+” operator is used to add an interval to the current DateTime:
    
    
    SELECT NOW(), NOW() + INTERVAL '1 Month 2 Days 3 Hours';

In the above snippet, the NOW() function is first used to get the current DateTime. After that, an interval “1 Month, 2 Days and 3 Hours” is added to the current DateTime using the “+” operator:

The output shows the current DateTime and current DateTime after 1 month, 2 days, and 3 hours.

##  **How Do I Subtract/Deduct an Interval From the Current Date in Postgres?**

In the below code, the “-” operator is used to subtract an interval from the current DateTime:
    
    
    SELECT NOW(), NOW() - INTERVAL '1 Month 2 Days 3 Hours';

In the above snippet, an interval “1 Month, 2 Days and 3 Hours” is subtracted from the current DateTime using the “-” operator:

The output shows the current DateTime and current DateTime before 1 month, 2 days, and 3 hours.

##  **How to Add Intervals to Particular DateTime Values?**

Let’s use the “+” operator to add an interval to a specific DateTime:
    
    
    SELECT DATE '2015-07-12' + INTERVAL '3 Month 5 Days 3 Hours 2 Minutes';

In the above snippet, an interval “1 Month, 2 Days and 3 Hours” is added to a date “2015-07-12” using the “+” operator:

The specified interval has been added to the given date using the “+” operator.

##  **How to Subtract Intervals From Particular DateTime Values?**

The below example demonstrates the usage of the “-” operator to subtract an interval from a specific DateTime:
    
    
    SELECT DATE '2015-07-12' - INTERVAL '3 Month 5 Days 3 Hours 2 Minutes';

In the above snippet, an interval “1 Month, 2 Days and 3 Hours” is added to a date “2015-07-12” using the “+” operator:

The specified interval has been subtracted from the given date using the “-” operator.

##  **How to Add or Subtract an Interval From a Table’s Data?**

The below snippet shows the staff information, including the joining date and contract duration:

Suppose we have to find the contract expiry date for each staff member. To do that, we will execute the following code:
    
    
    SELECT staff_name, joining_date + contract_duration AS contract_expiry_date
    FROM staff_info;

This way, you can attain the functionality of the DATEADD function in Postgres.

##  **Conclusion**

Postgres allows us to add or subtract intervals to date time using the “+” and “-” operators. Other than these operators, there is no alternative way in Postgres to add or remove intervals from a DateTime field. This post demonstrated various examples of adding intervals to DateTime values.

---
[View this page online](https://www.commandprompt.com/education/postgresql-dateadd-add-interval-to-datetime/)

---

# How to Insert or Delete Multiple Rows in PostgreSQL

> Use the INSERT query with comma-separated syntax to insert multiple rows into a Postgres table. To delete multiple rows, use the DELETE statement with IN claus…

**Inserting** new data to a table or **deleting** unnecessary data from a table are frequently performed operations in any database, including PostgreSQL. PostgreSQL provides **INSERT** and **DELETE** statements to insert or delete the records from a table. In Postgres, use the comma-separated syntax with the INSERT query to insert multiple rows into a table. And use the delete statement with an IN clause to delete multiple records from a table.

This post will teach you how to insert or delete multiple/bulk rows from a PostgreSQL table via practical examples.

## How to Insert or Delete Multiple Rows in PostgreSQL

Follow the steps below to insert or delete multiple/bulk rows.

  *  **Create a Sample Table**
  *  **Insert Multiple Rows**
  *  **Delete Multiple Rows**



So, let’s get started with the table creation.

###  **Create a Sample Table**

Firstly, we create a sample table with multiple columns: st_id, st_name, st_department, st_age:
    
    
    CREATE TABLE staff_information(
    st_id INT PRIMARY KEY,
    st_name TEXT,
    st_department TEXT,
    st_age SMALLINT
    );

The “ **CREATE TABLE** ” message in the output window indicates that the “staff_information” table has been created. You can verify the table’s creation via the below command:
    
    
    SELECT * FROM staff_information;

The table’s structure shows that the staff_information table has been created with four columns: st_id, st_name, st_department, and st_age.

###  **Insert Multiple Rows**

To insert multiple rows simultaneously into the staff_information table, execute the INSERT statement with comma-separated syntax as follows:
    
    
    INSERT INTO staff_information(st_id, st_name, st_department, st_age)
    VALUES (1, 'Joe', 'Writing', 26),
    (2, 'Joseph', 'Graphic Designing', 25),
    (3, 'William', 'Graphic Designing', 27),
    (4, 'Natie', 'Web Development’, 26),
    (5, 'Joe', 'Web Development’, 26),
    (6, 'Stephanie', 'HR', 26);

We utilize the INSERT INTO statement to insert rows into the staff_information table. After that, we utilize the VALUES keyword with the comma-separated syntax to specify the values/rows to be inserted in the staff_information table.

The output window shows that multiple rows have been inserted into the staff_information table. Verify the table’s data via the command:
    
    
    SELECT * FROM staff_information;

The output snippet verifies that all records have been successfully inserted into the staff_information table.

###  **Delete Multiple Rows**

Run the DELETE statement with the IN clause to delete/remove multiple rows from a Postgres table. Suppose we need to delete four rows from the staff_information table having ids “1, 3, 4, 6”:
    
    
    DELETE FROM staff_information
    WHERE st_id IN (1, 3, 4, 6);

In the above snippet,

  * We Specified the table’s name after the DELETE FROM keyword.
  * Next, we specified the column’s name within the WHERE clause.
  * Finally, we specified the rows to be deleted within the IN clause.



The output proves that four rows have been deleted from the staff_information table. To verify the deletion of the rows, run the below command:
    
    
    SELECT * FROM staff_information;

The output shows that only two rows have been left in the staff_information table, which confirms the bulk deletion.

##  **Conclusion**

PostgreSQL provides **INSERT** and **DELETE** statements to insert or delete the records from a Postgres table. In Postgres, the comma-separated syntax is used with the INSERT query to insert multiple rows into a table. The DELETE statement is used with an IN clause to delete multiple records from a table. This blog post explained how to insert or delete multiple rows from a table in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-insert-or-delete-multiple-rows-in-postgresql/)

---

# PostgreSQL Create Table IF NOT EXISTS

> In Postgres, creating a table that already exists will result in an error stating that the &quot;relation already exists&quot;. To avoid such errors, the IF NOT EXISTS c…

**CREATE TABLE** is a PostgreSQL command for creating tables. In Postgres, attempting to create a table that already exists will result in an error stating that the "relation already exists". To avoid such errors, the **IF NOT EXISTS** clause can be used with the **CREATE TABLE** command.

##  **Quick Outline**

This write-up will show you how to use the **IF NOT EXISTS** clause with the **CREATE TABLE** command.

  *  **How to Create a Table in Postgres?**
  *  **Understanding PostgreSQL “CREATE TABLE IF NOT EXISTS” Statement**
  *  **CREATE TABLE Vs. CREATE TABLE IF NOT EXISTS - What’s the Difference?**
  *  **Conclusion**



So, let’s start with table creation.

##  **How to Create a Table in Postgres**

In Postgres, the CREATE TABLE command assists us in [creating a new table](<https://www.commandprompt.com/education/different-methods-to-create-a-table-in-postgresql/>). Here is the very simple yet effective syntax to create a table in PostgreSQL:
    
    
    CREATE TABLE tab_name(
    first_col data_type,
    second_col data_type,
    third_col data_type,
    .....
    nth_col data_type,
    );

Here, tab_name represents a table to be created. first_col, second_col, …, nth_col are the column names to be defined in the desired table with their respective data types.

 **Example #1: Create a Table**

Let’s create a new table named “emp_record”:
    
    
    CREATE TABLE emp_record(
    emp_id INT PRIMARY KEY,
    emp_name TEXT, 
    emp_leaves INT,
    emp_salary INT);

In this example, we created four columns: emp_id, emp_name, emp_leaves, and emp_salaray. The emp_name column has a TEXT data type, while the remaining three columns have an INT data type:

The emp_record table with four columns has been created successfully. Now, you can [insert](<https://commandprompt.com/education/how-to-use-insert-query-in-postgresql/>) as many records as you want. Let’s insert the following three records into the newly created table:
    
    
    INSERT INTO emp_record(
    emp_id, emp_name, emp_leaves, emp_salary)
    VALUES (1, 'Joe', 1, 40000),
    (2, 'Seth', 0, 50000),
    (3, 'John', 2, 45000);

Three new records have been inserted into the emp_record table.

##  **Understanding PostgreSQL “CREATE TABLE IF NOT EXISTS” Statement**

If a database already has a table with the same name, then a "relation already exists" error will appear in Postgres. To avoid such a situation, PostgreSQL provides an **IF NOT EXISTS** clause that can be used with the **CREATE TABLE** command as follows:
    
    
    CREATE TABLE IF NOT EXISTS tab_name(
    first_col data_type,
    second_col data_type,
    third_col data_type,
    .....
    nth_col data_type
    );

Here, the IF NOT EXISTS clause will first check the existence of the targeted table. If the table already exists, then a notice will be issued instead of throwing an error. However, a new table with the specified name will be created in the database if the desired table doesn’t exist.

 **Example #1: What is the Need For IF NOT EXISTS Clause?**

Let’s create a new table with the same name, i.e., emp_record:
    
    
    CREATE TABLE emp_record(
    emp_name TEXT,
    emp_age INT);

Postgres throws an error stating that the targeted table already exists in the database.

From the above example, it is clear that Postgres throws an error while creating an existing table. The following code will demonstrate how to avoid the “relation already exists” error:
    
    
    CREATE TABLE IF NOT EXISTS emp_record(
    emp_name TEXT,
    emp_age INT);

The output clarifies that the IF NOT EXISTS clause shows a notice instead of throwing an error.

##  **CREATE TABLE Vs. CREATE TABLE IF NOT EXISTS - What’s the Difference?**

In the case of a simple “CREATE TABLE” statement, the program will be terminated immediately if a table already exists and no further statement will be executed. While in the case of “CREATE TABLE IF NOT EXISTS” a notice will be raised for the create statement and the program’s execution will be moved to the next statement (instead of terminating the program). Let’s learn it via the following example:
    
    
    DO $$ 
    BEGIN
    CREATE TABLE test_info(
    test_id INT PRIMARY KEY,  
    std_name TEXT,
    score INT);
    RAISE NOTICE 'Welcome to commandprompt.com';
    END $$;

In the above code, the “DO” keyword is used to execute a block, while the BEGIN and END keywords are used to start and terminate the transaction block. Two statements are enclosed in the block, the first one is to create a new table while the other one is to raise a greeting message. Let’s execute it and see the respective output:

From the output, you can observe that a “relation already exists” error arises and the program terminates immediately. Also, it didn’t execute the remaining statements.

Let’s use the same code with the “IF NOT EXISTS” option and see how it works:
    
    
    DO $$ 
    BEGIN
    CREATE TABLE IF NOT EXISTS test_info(
    test_id INT PRIMARY KEY,  
    std_name TEXT,
    score INT);
    RAISE NOTICE 'Welcome to commandprompt.com';
    END $$;

This time a notice is raised indicating that the relation to be created already exists in the database. Postgres skips the “CREATE TABLE” statement and moves the control to the subsequent statement, which gets executed successfully:

In this way, you can use the IF NOT EXISTS clause with the CREATE TABLE command to avoid the “relation already exists” error.

##  **Conclusion**

In PostgreSQL, the **CREATE TABLE** command assists us in creating a new table. In Postgres, attempting to create a table that already exists will result in an error stating that the "relation already exists". To avoid such errors, the **IF NOT EXISTS** clause is used with the **CREATE TABLE** command. This article used various examples to demonstrate how the PostgreSQL **CREATE TABLE IF NOT EXISTS** command works in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-create-table-if-not-exists/)

---

# PostgreSQL Date Types: Functions, Formats, and Intervals

> This blog post explained date data types, functions, operators, formats, and intervals with the help of appropriate examples.

PostgreSQL's **DATE** data type allows you to store and manipulate date values in your database. You can easily track events, deadlines, and other important dates by storing dates in your database. Apart from storing dates, Postgres offers various operators and functions. These functions and operators enable us to perform different operations on dates, such as finding intervals between two dates or extracting a specific part from a timestamp.

## Content Overview

  *  **What is Date Data Type, and How to Use it in Postgres?**
  *  **Built-in Date Functions in Postgres**
  *  **How to Format a Date in Postgres?**
  *  **How to Get an Interval Between Two Dates in Postgres?**



So, let’s begin!

##  **What is DATE Data Type, and How to Use it in Postgres?**

In Postgres, the DATE data type is used to store the date values in a table(by default, it stores the dates in “YYYY-MM-DD” format). The syntax of the DATE data type is as simple as any other built-in data type, such as TEXT, INT, NUMERIC, etc.
    
    
    CREATE TABLE tbl_name(
    column_name DATE
    );

The above syntax creates a date-type column in any particular table "tbl_name".

###  **Example: How Does the DATE Data Type Work in Postgres?**

Firstly, let’s create a table with a date-type column:
    
    
    CREATE TABLE published_articles(
    article_id SERIAL PRIMARY KEY, 
    article_name TEXT,
    published_date DATE
    );

A table named “published_artices” has been created. Let’s learn how to insert the data into a Postgres table via the INSERT INTO command:
    
    
    INSERT INTO published_articles(article_name, published_date)
    VALUES ('IF Statement in Postgres', '2022-07-01'),
    ('How to Count Unique Values in Postgres', '2022-08-28'),
    ('How to Delete Duplicates in Postgres', '2022-09-15'),
    ('AVG() Function in PostgreSQL', '2022-07-10'),
    ('Delete Table PostgreSQL', '2022-07-01');

To verify the data insertion, you can execute the “SELECT *” command as follows:
    
    
    SELECT * FROM published articles;

This is how you can create a date-type column, insert data into it, or fetch data from it.

##  **Built-in Date Functions in Postgres**

Postgres offers multiple built-in functions to work with dates. In this Postgres blog, we are going to discuss the most frequently used date functions via Practical examples:

###  **1)** **Postgres CURRENT_DATE Function**

The below-mentioned points illustrate the working of the Postgres [CURRENT_DATE](<https://commandprompt.com/education/how-to-format-a-date-in-postgresql/>) function:

  * In PostgreSQL, the **CURRENT_DATE** function is used to get the current/today’s date and time.
  *  **Return type:** “DATE”.
  * It retrieves the date in “YYYY-MM-DD” format.



 **Basic syntax**
    
    
    CURRENT_DATE;

The CURRENT_DATE function doesn’t accept any argument.

 **Example: How to Use CURRENT_DATE in Postgres?**

This example shows that the CURRENT_DATE function retrieves the current date in “ **YYYY-MM-DD** ” format:
    
    
    SELECT CURRENT_DATE;

###  **2)** **Postgres NOW() Function Function**

Consider the following points to comprehend the working of the [NOW()](<https://commandprompt.com/education/how-to-format-a-date-in-postgresql/>) function:

  * Postgres offers an inbuilt date function named NOW() that retrieves the current date, time, and timezone.
  *  **Return type:** TIMESTAMPTZ.
  * It retrieves the date in the “ **YYYY-MM-DD HH-MM-SS.MS-TZ** ” format.



 **Basic Syntax**
    
    
    NOW();

The NOW() function doesn’t require any argument.

 **Example: How to Use NOW() Function in Postgres?**

This example uses the Postgres’ NOW() function to retrieve the current date, time, and time zone based on the system’s date:
    
    
    SELECT NOW();

###  **3)** **Postgres CURRENT_TIMESTAMP Function**

The below-listed points elaborate on the working of the [CURRENT_TIMESTAMP](<https://www.commandprompt.com/education/postgresql-current_timestamp-function-with-examples/>) function:

  * The **CURRENT_TIMESTAMP** function in Postgres retrieves the current date, time, and timezone at which a transaction begins.
  * Return Type: TIMESTAMPTZ.
  * It retrieves the date/time in the “YYYY-MM-DD HH-MM-SS.MS-TZ” format.



 **Basic Syntax**
    
    
    CURRENT_TIMESTAMP;

The syntax shows that the CURRENT_STAMP function will be used without parentheses and arguments.

 **Example: How to Use CURRENT_TIMESTAMP in Postgres?**

Executing the below line of code will show you that the targeted function retrieves the timestamp with the time zone:
    
    
    SELECT CURRENT_TIMESTAMP;

###  **4)** **Postgres LOCALTIMESTAMP Function**

The below-listed points will help you understand the working of the [LOCALTIMESTAMP](<https://www.commandprompt.com/education/postgresql-current_timestamp-vs-localtimestamp/>) function:

  * Another widely used built-in function is LOCALTIMESTAMP, which retrieves the time and date at which the current transaction began.
  * Return Type: TIMESTAMP.
  * It retrieves the date and time in the “YYYY-MM-DD HH-MM-SS.MS” format.



 **Basic Syntax**
    
    
    LOCALTIMESTAMP;

The syntax shows that the **LOCALTIMESTAMP** function doesn’t accept any argument and will be used without parentheses.

 **Example: How to Use the LOCALTIMESTAMP Function in Postgres?**

Run the following line of code to get the current date and time without the time zone:
    
    
    SELECT LOCALTIMESTAMP;

###  **5)** **Postgres DATE_PART() Function**

[DATE_PART()](<https://commandprompt.com/education/how-to-use-date_trunc-function-in-postgresql/>) is a built-in function in Postgres that is used to get only a specific part/field of timestamp, date, interval, etc.

  * Return Type: **DOUBLE PRECISION**.
  * It accepts a field and a source as arguments.
  * The value for the “field” argument must be valid.



 **Basic Syntax**
    
    
    DATE_PART(field, source);

The above snippet shows that the DATE_PART() function accepts two arguments: a field and a source. The DATE_PART() function will extract/pull out the field from the specified source.

 **Example: How to Use DATE_PART() Function in Postgres?**

Suppose we want to pull out a year from a specific date; for this purpose, we will use the DATE_PART() function as follows:
    
    
    SELECT DATE_PART('Year', TIMESTAMP '2022-12-09');

###  **6)** **Postgres DATE_TRUNC() Function**

In PostgreSQL, DATE_TRUNC() is a built-in date function that truncates/trims the unnecessary part from the date/time.

  * Return Type: TIMESTAMP.
  * It accepts a “datePart” and a “field” as arguments.
  * The value for the “field” argument must be valid.
  * It retrieves the trimmed part with a specific precision level.
  * Using the DATE_TRUNC() function, all values of the given field except the specified date will be reset to their initials.



 **Basic Syntax**
    
    
    DATE_TRUNC(datePart, field);

The datePart must be valid, as described in the “[DATE_TRUNC() Function in Postgres](<https://commandprompt.com/education/how-to-use-date_trunc-function-in-postgresql/>)” blog. While in place of a field argument, you can specify an INTERVAL or TIMESTAMP.

 **Example: How to Use DATE_TRUNC() Function in Postgres?**

Let’s learn how the DATE_TRUNC() function work in Postgres:
    
    
    SELECT DATE_TRUNC('Year', TIMESTAMP '2022-08-02 11:12:14');

The output shows that the DATE_TRUNC() function resets all the values of the input timestamp(other than the specified date part, i.e., “Year” in the above example) to their initials.

###  **7)** **Postgres EXTRACT() Function**

In Postgres, the built-in [EXTRACT()](<https://commandprompt.com/education/how-to-use-extract-function-in-postgresql/>) function that works the same way as the **DATE_PART()** function:

  * It is used to extract a particular field from the input **TIMESTAMP**.
  * The return type of the **EXTRACT()** function is **DOUBLE PRECISION**.



 **Basic Syntax**
    
    
    EXTRACT(Field FROM Source);

The above syntax shows that the **EXTRACT()** function accepts two arguments: a field and a source. The EXTRACT() will extract the specified field from the given source.

 **Example: How Does the EXTRACT() Function Work in Postgres?**

Suppose we need to extract the minutes from the current date/time; to do that, we will utilize the EXTRACT() function as follows:
    
    
    SELECT EXTRACT('MIN' FROM NOW());

The output snippet shows that minutes were successfully extracted from the current date and time.

###  **8)** **Postgres TO_DATE() Function**

Postgres offers an in-built [TO_DATE()](<https://commandprompt.com/education/postgresql-to_date-function-convert-string-to-date/>) function that is used to convert a string/text into a date:

  * It accepts a string and a date format as arguments.
  * The date format must be a valid pattern/format, as demonstrated in the following blog: “[Postgres’ TO_DATE() Function](<https://commandprompt.com/education/postgresql-to_date-function-convert-string-to-date/>)”.
  * It converts the input string into a date based on the defined format.
  * The return type of the **TO_DATE()** function is “ **DATE** ”.



 **Basic Syntax**
    
    
    TO_DATE(string, date_format);

The above snippet indicates that the **TO_DATE()** function accepts a string and a date_format as an argument. Consequently, it will convert the input string into a date based on the specified date_format.

 **Example: How Does the TO_DATE() Function Work in Postgres?**

Execute the below-provided command to see how it works:
    
    
    SELECT TO_DATE('2022-12-09','YYYY-MM-DD');

The output authenticates that the given string has been converted into the DATE data type.

###  **9)** **Postgres AGE() Function**

Postgres provides a built-in [AGE()](<https://www.commandprompt.com/education/postgresql-age-function-with-examples/>) function that accepts two dates as arguments and finds the interval between the given dates.

  * The second time stamp will be subtracted from the first one, and the resultant interval will be returned as output.
  * Return Type: INTERVAL.



 **Basic Syntax**
    
    
    AGE(TIMESTAMP_1, TIMESTAMP_2);

The above snippet shows that the AGE() function accepts two timestamps/dates as arguments.

 **Example: How Does the AGE() Function Work in Postgres?**

Let’s suppose we want to calculate the age of a person whose birth date is “1990-01-01”. For this purpose, we will execute the AGE() function as follows:
    
    
    SELECT AGE(CURRENT_DATE, '1990-01-01');

The output shows that the AGE() function calculates the age and retrieves an INTERVAL.

##  **How to Format a Date in Postgres?**

In Postgres, the **TO_CHAR()** function is used to format a date value to a specific date format:

  * TO_CHAR() function accepts two arguments: a date and a valid format mask.
  * The following blog describes the valid formats: “[How to format a date in Postgres](<https://commandprompt.com/education/how-to-format-a-date-in-postgresql/>)”.
  * The Return type of the TO_CHAR() function is TEXT.



 **Basic Syntax**
    
    
    TO_CHAR(field, format);

 **Example 1: How to Format a Date Using TO_CHAR() Function?**

Let’s pass a date and a valid format of your choice to format the input date into the specified format:
    
    
    SELECT TO_CHAR('12 Jan, 2022'::DATE, 'YYYY-MM-DD');

In the above example:

  * The TO_CHAR() function accepts a date in the “DD Mon, YYYY” format as the first argument.
  * The cast operator “ **::** ” is used to perform the type conversion.
  * A valid date format, “YYYY-MM-DD”, is passed to the TO_CHAR() function.
  * Consequently, the given date will be formatted into the “YYYY-MM-DD” format, as shown in the following snippet:



The output snippet proves that the given date has been formatted into the user-specified date format.

 **Example 2: How to Format Current Date Using TO_CHAR() Function?**

Suppose we want to format the current date into “ **DD Mon, YYYY** ” format; for this, we will utilize the **TO_CHAR()** function as follows:
    
    
    SELECT TO_CHAR(NOW(), 'DD Mon, YYYY');

In this example, the TO_CHAR() function takes two values as arguments:

1) [The NOW() function](<https://www.commandprompt.com/education/postgresql-now-function-with-practical-examples/>) is passed as a first argument to the TO_CHAR() function that will retrieve the current date in “YYYY-MM-DD” format.  
2) A date format is passed to the TO_CHAR() function. The date retrieved by the NOW() function will be formatted according to the given format.

The output shows that the current date has been formatted according to the specified format.

##  **How to Get an Interval Between Two Dates in Postgres?**

In PostgreSQL, the “ **-** ” operator and the AGE() function are used to get an interval between the two dates. Use the following syntax to get the interval via the “ **-** ” operator:
    
    
    'date_1'::DATE - 'date_2'::DATE;

The above query will retrieve the days between the given dates.

 **Example 1: How to Get the Interval Between the Two Dates Using “-” Operator?**

Execute the following query to get the total days between the input dates:
    
    
    SELECT '2022-12-12'::DATE - '2021-11-01'::DATE;

The output shows that the difference between the given dates is 406 days.

 **Example 2: How to Use the “-” Operator on the Table’s Data?**

Suppose we want to find the total duration of the published articles. For this purpose, we can use the “-” operator as follows:
    
    
    SELECT (CURRENT_DATE - published_date) total_days
    FROM published_articles;

In the above snippet, we utilized the “-” operator to find the interval between the current date and the articles’ published date:

The output snippet shows that the “-” operator finds the interval between the current_date and published_date successfully.

 ** _Note:_** _You can also use the AGE() function to achieve the same functionality._

##  **Conclusion**

In Postgres, the **DATE** data type stores or manipulates the date values. It stores the dates in “ **YYYY-MM-DD** ” format. Moreover, Postgres offers various built-in functions and operators to work with the dates. For instance, the functions like NOW(), CURRENT_DATE, etc., are used to obtain today’s date. The EXTRACT(), DATE_PART() function extracts a specific date part. The “-” operator and AGE() function are used to find an interval between two dates, and so on. This blog post explained date data types, functions, operators, formats, and intervals with the help of appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-date-types-functions-formats-and-intervals/)

---

# How to Check/Get PostgreSQL Version

> To check which PostgreSQL version is active on your system, users can run “psql –version” command from the command prompt, or the “SELECT VERSION()” command fr…

New versions of PostgreSQL [are released](<https://www.postgresql.org/docs/release/>) by the PostgreSQL Global Development Group on a regular basis. The major releases of Postgres are usually scheduled yearly and focus on improving key features as well as performance and security. In contrast, minor releases are scheduled nearly every three months. The minor releases focus on resolving evolving security issues and fixing bugs.

> Try the new PgManage (Open Source) and get rid of PgAdmin!

If you intend to implement new software, you should check if it is compatible with your Postgres version, whether the latest security patch is available, etc. In such cases, knowing **_which Postgres version is active on your system might be useful_**.

> [ ** _Contact us_**](<https://commandprompt.com/contact-us/>) **today for all your Postgres and Open Source consulting and support needs.**

##  **Quick Outline**

This blog post will teach you how to check the current version of Postgres running on your system using the following content.

  * How to Check/Get Postgres Version on Windows?
  * How to Check/Get Postgres Version on macOS?
  * How to Check/Get Postgres Version on Linux?
  * Final Thoughts



So, let’s get started!

##  **How to Check/Get Postgres Version on Windows?**

To check the Postgres version on the Windows operating system different methods like CMD (Command Prompt), psql (SQL Shell), and pgAdmin are used. All these methods will be discussed in this section using appropriate screenshots:

###  **Method 1: How to Check PostgreSQL Version Using the Command Prompt**

Follow the below-given stepwise guidelines to check the currently installed PostgreSQL version on your system via the command prompt.

 **Step1: Access Bin Directory**

Firstly, open the command prompt and run the following command to navigate to the Postgres bin folder:
    
    
    cd C:\Program Files\PostgreSQL\14\bin

Hit the “ **Enter** ” button to access the desired directory/path:

The above snippet indicates the successful entry into the “bin” directory.

 **Step2: Check Postgres Version**

Now execute the “psql -v” command to check the Postgres version:
    
    
    psql -V

Alternatively, you can execute the “psql –version” command to find the Postgres version:
    
    
    psql –version

The output shows that the “Postgres 14.4” version is running on your computer.

###  **Method 2: How to Check the PostgreSQL Version Using SQL Shell**

 **SQL Shell** is a default Postgres terminal that helps us execute different SQL commands and meta-commands. Different commands like “ **SELECT VERSION()** ”, and “ **SHOW_VERSION** ” can be executed from SQL Shell to Check the Postgres version.

Launch the SQL Shell, fill in the login details, and run the below command to check which version of PostgreSQL is running on your machine:
    
    
    SELECT VERSION();

Alternatively, you can utilize the following command to check the server version:
    
    
    SHOW SERVER_VERSION;

The output proves that the specified command returns the PostgreSQL version.

###  **Method 3: How to Check PostgreSQL Version Using pgAdmin**

pgAdmin is a feature-rich GUI-based tool that is an open-source and freely available management tool for Postgres. Using pgAdmin, you can find the current Postgres version either manually or by executing SQL queries.

To check the PostgreSQL version via pgAdmin, users can follow the below-mentioned steps:

 **Step 1: Expand “Servers” Tree**

Open the pgAdmin, specify the superuser password, and left-click on the “Servers” tree to expand it:

 **Step 2: Select Properties**

Left-click on the “PostgreSQL” located under the “Servers” tree, and then click on the “Properties” tab:

Under the properties tab, you can check the currently installed PostgreSQL version on your system.

 ** _Note:_** _You can also execute the “_ ** _SELECT VERSION();_** _” and “_ ** _SHOW SERVER_VERSION;_** _” commands in the pgAdmin’s query tool._

##  **How to Check/Get Postgres Version on macOS?**

Mac users can find the Postgres version either by using a terminal or pgAdmin. To find the Postgres version via pgAdmin, perform the same steps as we did for Windows. While to check the PostgreSQL version via the Mac Terminal, execute the command:
    
    
    postgres -V

##  **How to Check/Get Postgres Version on Linux?**

To find the Postgres version on Linux, the “ **SQL Shell** ”, “ **pg_config** ” utility, the “ **dpkg** ” command, and the “ **apt-cache** ” command are used. All these methods are discussed with practical illustration in our dedicated guide on “[ **Check Postgres Version on Linux**](<https://www.commandprompt.com/education/how-to-check-postgresql-version-on-ubuntu/>)”.

##  **Final Thoughts**

PostgreSQL is among the top databases that keep its users up-to-date by releasing new versions regularly. Postgres users can upgrade the currently used version to the latest one to avail the latest features. But before that, it’s recommended to check which Postgres version you are currently using.

To do that on the Windows system, users can run the “psql --version” command from the Command Prompt, the “SELECT VERSION()” command from SQL Shell, or use pgAdmin’s properties tab. Linux users can use the “SQL Shell”, “pg_config” utility, the “dpkg” command, or the “apt-cache” command to check the currently installed Postgres version. This blog post explained various approaches for checking the PostgreSQL version on Windows, MacOS, and Linux via practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-checkget-postgresql-version/)

---

# How to Kill a Process ID in PostgreSQL

> To kill a process in Postgres, first, find the “pid” for all the processes, and then run the “pg_cancel_backend(pid)” and “pg_terminate_backend(pid)” commands.

Users write queries to perform specific database operations/actions in PostgreSQL. There may be cases when it becomes necessary to terminate a running query. This can occur when the user interface stops responding, but the query process continues to run. Also, it may be necessary to terminate a query that is taking an unusually long time to complete. To deal with such situations, PostgreSQL provides a couple of commands that help us terminate the process or halt its further execution.

This article will thoroughly cover the method to kill a process ID in PostgreSQL.

##  **How to Kill a Process ID in PostgreSQL?**

Killing a process involves several steps. First, we will be getting all the currently running queries in the PostgreSQL and then we will kill them. We will go through the following steps to kill a specific process using its ID:

  1. Find the Running Processes
  2. Find Non-Idle Processes
  3. Kill the Process ID
  4. Verify Process Termination



Let’s begin with finding the running processes.

###  **Step 1: Find the Running Processes**

The first step is to find the currently running processes in Postgres. To do that, use the query:
    
    
    SELECT * 
    FROM pg_stat_activity;

In the above query, the “pg_stat_activity” view is used to get all the database connections to respond to the PostgreSQL server. Most importantly, it is used to get all the currently running queries/processes in PostgreSQL.

The query will return the detailed table showing the running queries/processes. In our case, the result set looks like this:

Let’s break down the above view so that we can understand what the table contains.

  *  **datename** \- It represents the name of databases.
  *  **pid** \- It indicates the process id.
  *  **Usename** \- usename is the name of the user in the PostgreSQL server.
  *  **Client_addr** \- client_addr specifies the client address which is shown as the client IP. Using this IP address, the client and server establish a connection.
  *  **Client_port** \- The client _port specifies the port numbers for all clients that are available on the server.
  *  **Xact_start** \- The xact_start means the start time transaction.
  *  **Backend_start** \- The backend _start column specifies the start time of the respective process when the client is connected.
  *  **Query_start** \- The query_start shows the time when the query begins/starts its execution.
  *  **State** \- This specifies the current status of the process/transaction that can be active or idle.
  *  **Query** \- This shows all executed queries.



In the above query, all columns of the “pg_stat_activity” view were being fetched. Let’s make the query concise and fetch only those columns that are necessary for getting the process information:
    
    
    SELECT datname, pid, usename, query
    FROM pg_stat_activity;

###  **Step 2: Find Non-Idle Processes/Queries**

To show all the **non-idle queries** we will execute the following command:
    
    
    SELECT datname, pid, usename, query 
    FROM pg_stat_activity 
    WHERE STATE !='idle';

The result set contains all the non-idle queries at the current instant.

The output shows all the non-idle processes. Similarly, we can also check the active processes by executing the following query:
    
    
    SELECT datname, pid, usename, query 
    FROM pg_stat_activity WHERE STATE ='active';

On successful execution, the stated query will retrieve all the currently active queries.

###  **Step 3: Kill the Process ID**

Now you have found all the idle and non-idle processes (process IDs). These processes can be killed by using their “PID”. For this particular purpose, use two basic queries to kill a process. The first one is the “ **pg_cancel_backend(pid)** ” and the other one is the “ **pg_terminate_backend(pid)** ”.

We always run the “pg_cancel_backend(pid)” query first. The syntax for killing a process having “pid = 20280” is
    
    
    SELECT pg_cancel_backend(20280);

We run the “pg_cancel_backend(pid)” query before the “pg_terminate_backend(pid)” because the “pg_cancel_backend(pid)” query is safer than the “pg_terminate_backend(pid)”. The “pg_cancel_backend(pid)” tends to be lenient and takes more time to run.
    
    
    SELECT pg_terminate_backend(20280);

It is important to note that the pg_terminate_backend() can terminate the whole process leading to the restart of the whole database.

###  **Step 4: Verify Process Termination**

Execute the below-stated query to verify if the selected process has been killed or not:
    
    
    SELECT datname, pid, usename, query 
    FROM pg_stat_activity WHERE STATE !='idle';

The absence of the “20280” process from the pid column proves the termination of the selected process.

##  **Long-running PostgreSQL Queries: How to Find and Kill Them?**

In this example, we will let you know how a long-running query can be killed in PostgreSQL. For a profound understanding, consider the following stepwise demonstration:

  1. Find the Long-Running Queries
  2. Stop the Long-Running Queries
  3. Kill the Long-Running Queries
  4. Verify Queries Termination



Let’s start with finding the long-running queries.

###  **Step 1: Find the Long-Running Queries**

In the following Code snippet, the pg_stat_activity view will be utilized to find all the queries that have been running from the last ten minutes:
    
    
    SELECT
      pid AS process_id,
      now() - pg_stat_activity.query_start AS query_duration,
      query, state
     FROM pg_stat_activity
     WHERE (now() - pg_stat_activity.query_start) > interval '10 minutes';

In this code block,

\- First, the process IDs are fetched using the pg_stat_activity view.

\- After that, the query’s running duration is computed by subtracting the query’s start time from the current DateTime.

\- Finally, the queries and respective states are fetched.

###  **Step 2: Stop the Long-Running Queries**

Now use the “pg_cancel_backend” to stop any particular query using its process id, as follows:
    
    
    SELECT pg_cancel_backend(11404);

The above code block will cancel the query having process id “11404”:

The Boolean “true” verifies the cancellation of the selected process.

###  **Step 3: Kill the Long-Running Queries**

Now, use the pg_terminate_backend() with the process ID to kill the selected long-running query:
    
    
    SELECT pg_terminate_backend(11404);

The Boolean true proves that the selected long-running query has been successfully terminated.

###  **Step 4: Verify Queries Termination**

You can confirm the termination of the selected query by executing the following code:
    
    
    SELECT
      pid AS process_id,
      now() - pg_stat_activity.query_start AS query_duration,
      query, state
     FROM   pg_stat_activity
     WHERE (now() - pg_stat_activity.query_start) > interval '10 minutes';

The stated query retrieves all those queries whose running time is more than ten minutes:

From the output snippet, it can be noted that the query having a process ID equal to “11404” has been successfully terminated.

##  **Final Thoughts**

To kill a process in PostgreSQL, first, find out the “pid” for all the processes by using the “pg_stat_activity” view. The pg_stat_activity view retrieves detailed information about the processes. After that, run the “pg_cancel_backend(pid)” and “pg_terminate_backend(pid)” commands to kill the selected processes. This article has covered the complete procedure of killing a process using step-by-step demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-kill-a-process-id-in-postgresql/)

---

# Understanding PostgreSQL Sequence Functions

> PostgreSQL provides various sequence functions like SETVAL(), NEXTVAL(), CURRVAL(), and LASTVAL() to work with sequences efficiently.

In PostgreSQL, a "sequence" is a database object that helps us create unique numbers automatically. PostgreSQL provides functions like **SETVAL()** , **NEXTVAL()** , **CURRVAL()** , and **LASTVAL()** to work with sequences efficiently. Each of these functions offers a distinct functionality and serves a unique purpose.

##  **Quick Outline**

This write-up will illustrate the use of sequence function in Postgres using the following content:

  *  **How to Use NEXTVAL() in Postgres?**
  *  **How to Use CURRVAL() in Postgres?**
  *  **How to Use LASTVAL() in Postgres?**
  *  **How to Use SETVAL() in Postgres?**



##  **How to Use NEXTVAL() in Postgres?**

The NEXTVAL() is a built-in sequence function in Postgres that proceeds the specified sequence to its next value and retrieves that value. Use the below-stated syntax to execute the NEXTVAL() function on a specific sequence:
    
    
    SETVAL(seq_name TEXT);

Here, **seq_name** represents a sequence upon which the stated function will be implemented.

###  **Example: Using NEXTVAL() in Postgres**

First, create a sample sequence and name it “cp_seq”:
    
    
    CREATE SEQUENCE cp_seq 
    START 172;

The specified sequence is initialized with a start value of "172":

Let’s execute the NEXTVAL() function to proceed the cp_sequence to its next value and retrieve the current value:
    
    
    SELECT NEXTVAL('cp_seq');

##  **How to Use CURRVAL() in Postgres?**

The CURRVAL() function is a sequence function in PostgreSQL that retrieves the current/latest value of the specified sequence in the recent session. However, invoking the CURRVAL() function before the NEXTVAL() function in the current session will throw an error. Use the below-stated syntax to execute the CURRVAL() function on a specific sequence:
    
    
    CURRVAL(seq_name TEXT)

Here, **seq_name** represents a targeted sequence to which the stated function will be applied.

 **Example: Using CURRVAL() in Postgres**

Invoke the CURRVAL() function on the selected sequence to see how it works:
    
    
    SELECT CURRVAL('cp_seq');

##  **How to Use LASTVAL() in Postgres?**

The LASTVAL() function is a sequence function in PostgreSQL that retrieves the current/latest value of the specified sequence in the recent session. It is quite similar to CURRVAL(), but it doesn't need any argument value:
    
    
    LASTVAL();

 **Example: Using LASTVAL() in PostgreSQL**

Invoke the LASTVAL() function to get the most recent value of the NEXTVAL() function:
    
    
    SELECT LASTVAL();

##  **How to Use SETVAL() in Postgres?**

 **SETVAL()** is one of the sequence functions that resets the current value of the selected sequence and retrieves the specified value. Use the below-stated syntax to execute the SETVAL() function on a specific sequence:
    
    
    SETVAL(seq_name TEXT, current_val BIGINT, is_called BOOLEAN);

Here, **seq_name** represents a sequence upon which the stated function will be implemented. The **current_val** indicates the current value of the selected sequence. The **is_called** parameter determines whether the specified current value is recalled.

 **Example: Using SETVAL() in Postgres**

Invoke the SETVAL() function to set the sequence value to 180:
    
    
    SELECT SETVAL('cp_seq', 180);

That’s all about the sequence functions in PostgreSQL.

> To learn more about these sequence functions and their different use cases, read the following dedicated guides: **SETVAL()**, **NEXTVAL()**, **CURRVAL()**, and **LASTVAL()** **.**

##  **Conclusion**

PostgreSQL provides various sequence functions like **SETVAL()** , **NEXTVAL()** , **CURRVAL()** , and **LASTVAL()** to work with sequences efficiently. For example, the NEXTVAL() function proceeds the specified sequence to its next value and retrieves that value, the SETVAL() function resets the current value of the selected sequence and retrieves the specified value, etc. This post has demonstrated the working of various sequence functions in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/understanding-postgresql-functions/)

---

# PostgreSQL List Users, Databases, Schemas, Tables

> PostgreSQL database management system provides a variety of features and options for storing and organizing data. However, “with great power comes great responsibility”. For instance, While working with Postgres, you need to deal with tables, schemas, views, users, etc. Therefore keeping track of all the different elements in a database is critical.

PostgreSQL database management system provides a variety of features and options for storing and organizing data. However, “with great power comes great responsibility”. For instance, While working with Postgres, you need to deal with tables, schemas, views, users, etc. Therefore keeping track of all the different elements in a database is critical.

Step-by-step instructions are provided in this blog for listing users, databases, schemas, and tables in PostgreSQL. The content of this blog is organized as follows:

  *  **PostgreSQL List Users/Roles.**
  *  **PostgreSQL List Databases.**
  *  **PostgreSQL List Schemas.**
  *  **PostgreSQL List Tables.**



Let’s start with the Postgres users.

##  **PostgreSQL List Users/Roles**

In Postgres, the “ **pg_catalog** ”, “\ **du** ”, and “\ **du+** ” commands are used to find the list of all users. The “ **\du** ” and “ **\du+** ” command must be executed from the SQL Shell.

Let’s learn how the “ **\du** ” and “ **\du+** ” commands work in Postgres:
    
    
    \du;

The “\du” command retrieves the details regarding the list of roles, such as “r **ole/user name** ”, “ **attributes** ”, and “ **member of** ”. The “ **\du+** ” command retrieves all these details along with the “ **description** ”:
    
    
    \du+;

For more detailed information, such as the user’s sysid, superuser, etc., you can use the “ **pg_user** ” table. To get the list of users/roles via the pg_catalog, you need to execute the below-provided command:
    
    
    SELECT * 
    FROM pg_catalog.pg_user;

 **Note:** This command can be executed from any interface, such as psql or pgAdmin:

##  **PostgreSQL List Databases**

Use the “\l”, “\l+” commands or the “pg_database” catalog to get the list of all the available databases in a current server. The “\l” and “\l+” commands must be executed from the SQL Shell; however, the “pg_database” catalog can be used with the help of the SELECT statement from any interface, like pgAdmin or psql.
    
    
    \l;

Here, template0 and template1 are the standard databases, while the remaining are user-defined databases.

 **Note:** Use the “\l+” command to get more details regarding the available databases, such as database size, description, etc.

Let’s learn how to get the list of Postgres databases via the “ **pg_database** ” catalog:
    
    
    SELECT oid, datname
    FROM pg_database;

You can get more details regarding the databases, such as connection limit, tablespace, encoding, etc., by specifying the respective columns’ names in the SELECT statement.

##  **PostgreSQL List Schemas**

In Postgres, the “ **\dn** ”, “ **\dn+** ” commands, and “ **information_schema** ” are used to get the list of available schemas. The “\dn” and “\dn+” commands must be executed from the SQL Shell; however, getting the list of available schemas using “information_schema” can be accomplished from any interface like pgAdmin or psql.

Let’s practice the “\dn” and “dn+” commands via the SQL Shell:
    
    
    \dn;

Use the “\dn+” command for more details regarding schemas, such as access privileges or description:
    
    
    \dn+;

Use the **SELECT** command to fetch the schema’s information from the “ **information_schema** ”:
    
    
    SELECT schema_name, schema_owner
    FROM information_schema.schemata;

This way, you can find the list of available schemas in Postgres.

##  **PostgreSQL List Tables**

Users need to utilize either the “ **pg_catalog.pg_tables** ” or the “ **\dt** ” command to find the list of available tables. You can also use the “ **\d** ” and “ **\dt+** ” commands from the SQL Shell to get the list of available tables. However, the “\dt+” command will show the list of all the tables with more details like table size, access method, etc. While the “\d” command will show the list containing tables, views, sequences, etc.

Let’s implement the “\dt” command via the SQL Shell:
    
    
    \dt;

The below-provided command explains how to use the “ **pg_catalog.pg_tables** ” to get the list of all available relations/tables:
    
    
    SELECT tablename 
    FROM pg_catalog.pg_tables;

To get only user-defined tables, you need to execute the following command:
    
    
    SELECT tablename 
    FROM pg_catalog.pg_tables
    WHERE schemaname!='information_schema' AND schemaname!= 'pg_catalog';

This time, the “pg_catalog.pg_tables” retrieves the user-defined tables only.

##  **Conclusion**

Postgres provides different built-in commands to find the list of users, databases, schemas, or tables. For instance, the “ **\du** ”, “ **\l** ”, “ **\dn** ”, and “ **\dt** ” commands are used to find the list of users, databases, schemas, and tables, respectively. “pg_catalog” and “information_schema” can also be used to find the list of users, databases, schemas, and tables in Postgres. This post has demonstrated how to list users, schemas, databases, and tables in PostgreSQL via different built-in commands, schemas, and catalogs.

---
[View this page online](https://www.commandprompt.com/education/postgresql-list-users-databases-schemas-tables/)

---

# PostgreSQL: Basic psql Commands

> psql is a command-line interface used to perform various database tasks efficiently. For instance, using psql different commands can be executed to access, cre…

Postgres supports numerous commands to perform various database operations. To execute such commands different interfaces are used. One such interface is “SQL Shell”, also known as, “psql”. Using psql, you can execute various commands to accomplish different database operations efficiently, such as accessing, creating, deleting, or updating a database, table, schema, etc.

> Try the latest PgManage (Open Source) and get rid of PgAdmin!

This post presents a comprehensive understanding of basic “psql” commands through practical demonstration.

> [ **Contact us**](<https://commandprompt.com/contact-us/>) **today for all your Postgres and Open Source consulting and support needs.**

##  **Introduction to Basic SQL Shell or psql Commands**

The psql commands assist us in querying the data from the specified database interactively. Here are some of the most frequently used, most effective psql commands:

  * Connect to a Database: “ **psql -d db_name -U user_name** ”.
  * Check Postgres Version: “ **SELECT VERSION();** ”.
  * List All Databases: “ **\l** ”.
  * Access or Switch a Database: “ **\c db_name** ”.
  * List All Tables: “ **\dt** ”.
  * Describe All Tables: “ **\d** ”.
  * Describe a Specific Table: “ **\d tab_name** ”.
  * List All Schemas: “ **\dn** ”.
  * List All Views: “ **\dv** ”.
  * List All Functions: “ **\df** ”.
  * List All Users: “ **\du** ”.
  * Show Commands History: “ **\s** ”
  * Save Query’s Results to a Specific File: “ **\o file_name** ”.
  * Run psql Commands/queries From a Particular File: “ **\i file_name** ”.
  * Execute Previous Command: “ **\g** ”.
  * Show Query Execution Time: “ **\timing** ”.
  * Get Output in HTML Format: “ **\H** ”.
  * Align Columns Output: “ **\a** ”.
  * Get Help: “ **\h** ”.
  * Get All psql Commands: “ **\?** ”.
  * Clear Screen: “ **\\! cls** ”.
  * Quit psql: “ **\q** ”.



Let’s put these commands into practice to get a profound understanding.

###  **Example 1: Connecting to a Database**

Open the CMD and execute the below-provided psql command to establish a connection to a particular database:
    
    
    psql -d postgres -U postgres

The output signifies that a connection with the “postgres” database has been successfully established under the user “postgres”.

###  **Example 2: Checking Postgres Version**

Executing the “SELECT VERSION();” command will retrieve the currently installed Postgres version:
    
    
    SELECT VERSION();

The output shows that currently “PostgreSQL 15.1” is running on our system.

###  **Example 3: Listing All Databases**

Listing available databases is a very common task in Postgres that can be accomplished via the “\l” command:
    
    
    \l

The “\l” successfully retrieves the list of available databases.

###  **Example 4: Accessing/Switching a Database**

Performing any operation on a database object requires accessing that database. To accomplish this task, execute the “\c” command from the “SQL Shell”:
    
    
    \c sample_db;

The connection with the “sample_db” database has been established successfully.

###  **Example 5: Listing All Available Tables**

In Postgres, the tables are used to represent the data elements in a well-organized format. Run the “\dt” command from SQL Shell to fetch the list of available tables/relations:
    
    
    \dt;

The stated command returns all the tables available in the selected database.

###  **Example 6: Describing All Tables**

Postgres users can use the “\d” command to get the list of relations, including sequences, views, etc.
    
    
    \d

The “\d” command successfully retrieves the “schema name”, “table name”, “relation type”, and owner.

###  **Example 7: Describing a Specific Table**

Execute the “\d” command followed by the table name to describe a specific table in Postgres:
    
    
    \d emp_data;

The above-stated command will describe the “emp_data” table:

The stated command retrieves all the details regarding the “emp_data” table, such as column names, column types, columns’ default values, etc.

###  **Example 8: Listing All Schemas**

A Postgres schema is a namespace that keeps the database objects, such as relations, functions, etc. To fetch the list of schemas, use the “\dn” command:
    
    
    \dn;

The given command returns the names of all schemas along with their owners.

###  **Example 9: Listing All Views**

Views are a frequently utilized concept in Postgres that allows us to simplify complex queries. To show the list of views, use the “\dv” command:
    
    
    \dv;

The “\dv” command returns the view name, schema name, relation type, and view’s owner.

###  **Example 10: Listing All Functions**

In Postgres, the functions enhance code reusability, understandability, debugging, etc. To obtain the list of available functions, use the “\df”:
    
    
    \df;

The “\df” command returns the “schema name”, “function name”, “result data types”, and “argument data types”.

###  **Example 11: Listing All Users**

In PostgreSQL, the users can have database privileges and can own the database objects, such as tables, schemas, etc. To get the user’s list, use the below command:
    
    
    \du;

The “\du” command returns the “role name”, “attributes”, and “members details”.

###  **Example 12: Show Command History**

Open the terminal, log into “psql”, and execute the following command to see the query history:
    
    
    \s

The output shows that the “\s” command successfully retrieves the query history.

###  **Example 13: Execute psql Commands From a Particular File**

The SQL Shell supports a “\o” command that allows us to save query results to a specific file. Execute the “\o” command followed by the “file name”, as shown below:
    
    
    \o 'C:/exeFile.txt';

The cursor moves to the next line, which proves that the “\o” command executes successfully. Now the output of the commands will be written to the “exeFile.txt” file until we execute the “\o” command:

Let’s open the desired file to see the result of the “\dt” command:

The output snippet verified the working of the “\o” command.

###  **Example 14: Execute psql Commands From a Particular File**

Postgres allows us to execute psql commands from a particular file using the “\i”. The sample file contains the following command:

Let’s utilize the “\i” command to execute the psql commands from the selected file:
    
    
    \i 'C:/showtables.txt';

The output proves that the “\i” command successfully executes the commands from a specific file.

###  **Example 15: Show Query Execution Time**

In psql, the **“\timing”** command is used to enable or disable query execution time:
    
    
    \timing

Let’s execute any command to see how the “\timing” command works:
    
    
    SELECT * FROM emp_data;

Execute the “\timing” command one more time to disable the query execution time:
    
    
    \timing

The output shows that the query execution has been “off”.

###  **Example 16: Get Output in HTML Format**

The “\H” command is used in psql to get the command’s output in HTML format:
    
    
    \H

Now the output of any particular command will be displayed in HTML format as follows:
    
    
    SELECT * FROM emp_data;

To disable the HTML format, use the “\H” command one more time.

###  **Example 17: Execute Previous Command**

Use the “\g” command to run the previously executed command:
    
    
    \g

The “\g” command retrieves the result based on the previously executed command.

###  **Example 18: Align Columns Output**

Execute the “\a” command to align or unaligned the output format:
    
    
    \a

The output snippet shows that the output format is “unaligned”. Run any Postgres-supported command to understand this concept better:
    
    
    SELECT * FROM emp_data;

The output proves that the result set is unaligned.

##  **Example 19: Get Help**

Use the “\h” command to get help regarding any command or query. For instance, the below command will provide help regarding the “INSERT INTO” command:
    
    
    \h INSERT INTO

The “\h” command retrieves the details regarding the “INSERT” command.

###  **Example 20: Get All psql Commands**

Execute the “\?” command to get all available psql commands:
    
    
    \?

The output displays all available commands in psql.

###  **Example 21: Clear Screen**

Execute the “\\! cls” command from psql to clear the screen:
    
    
    \! cls

Hitting the enter button will clear the screen.

###  **Example 22: Quit psql**

The “\q” command is used to quit or exit the SQL Shell (psql):
    
    
    \q

That’s all! We have discussed various basic yet very important psql commands.

##  **Conclusion**

psql is a command-line interface used to perform various database tasks efficiently. For instance, using psql different commands can be executed to access, create, delete, or update a database, table, schema, etc. Moreover, using psql, you can store the output of commands to a specific file or execute the commands from a particular file. In this write-up, we have discussed the most frequently used psql commands with practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/postgresql-basic-psql-commands/)

---

# PostgreSQL TRUNCATE VS DROP VS DELETE

> In Postgres, the TRUNCATE TABLE command only removes the table’s data and preserves the table’s structure. While the DROP TABLE command drops the table’s data …

Every developer, database user, etc. comes across a situation where he gets confused about “what’s the difference between **DROP, TRUNCATE** , and **DELETE** commands”. If you're experiencing the same issues? Then, nothing to worry about. This post is going to resolve all your ambiguities through practical examples.

##  **Quick Outline**

This write-up will present a comparative analysis of Postgres TRUNCATE, DROP, and DELETE commands using the following content:

  *  **How to Use TRUNCATE Command in PostgreSQL**
  *  **How to Use DELETE Command in PostgreSQL**
  *  **How to DROP a Table in PostgreSQL**
  *  **Postgres TRUNCATE VS DROP VS DELETE**
  *  **Conclusion**



So, let’s begin.

##  **How to Use TRUNCATE Command in PostgreSQL**

The **TRUNCATE TABLE** command is a DDL(acronym of data definition language) operation that removes all the data/records from the targeted table. The TRUNCATE TABLE command only removes the table’s data and preserves the table’s structure.

A foreign key-referenced table can't be truncated by the TRUNCATE TABLE command in Postgres. To achieve this purpose, you must use the **CASCADE** clause/option with the **TRUNCATE TABLE** command.

 **Syntax**

The below snippet shows how to truncate a specific table in Postgres:
    
    
    TRUNCATE TABLE tab_name;

Here the tab_name is a table to be truncated.

 **Example #1: How to Truncate a Table in PostgreSQL**

Suppose we need to truncate a table named “emp_data”, whose content is shown in the below-given screenshot:
    
    
    SELECT * FROM emp_data;

The emp_data has six records. Let’s use the TRUNCATE table command to truncate the targeted table, i.e., emp_data:
    
    
    TRUNCATE TABLE emp_data;

The emp_data table has been truncated successfully. Let’s use the SELECT command to verify the table’s truncation:
    
    
    SELECT * FROM emp_data;

From the output, it is clear that the TRUNCATE TABLE command truncated the table’s data and preserved its structure. For more information about TRUNCATE TABLE, [click here](<https://www.commandprompt.com/education/how-to-use-the-truncate-table-command-in-postgresql/>).

##  **How to Use DELETE Command in PostgreSQL**

The **DELETE** command is a DML(acronym of Data Manipulation Language) command that deletes single or several existing records from the targeted table. The Postgres **WHERE** clause can be used with the DELETE command to specify a condition, and based on that condition, the table’s records will be deleted. Skipping the WHERE clause from the DELETE command will delete all the records from the certain table.

 **Syntax**

The below snippet illustrates how to use the **DELETE** command in Postgres:
    
    
    DELETE FROM tab_name [WHERE condition/criteria];

Tab_name represents the name of the table that needs to be deleted. **WHERE** is an optional clause that determines whether the whole table will be deleted or some specific table records will be deleted?

 **Example: How to Use DELETE Statement in PostgreSQL**

Suppose we want to delete a table named “staff_details” that contains the following records:
    
    
    SELECT * FROM staff_details;

Let’s use the **DELETE** command to delete the focused table, i.e., the staff_details table:
    
    
    DELETE FROM staff_details
    WHERE staff_id = 4;

The output indicates that the targeted record has been deleted from the “staff_details” table. To verify the deletion of the record, you can utilize the below command:
    
    
    SELECT * FROM staff_details;

The specified record, i.e., “staff_id=4”, has been deleted from the staff_details table. You can learn more about the DELETE command from [this article](<https://commandprompt.com/education/how-to-use-delete-query-in-postgresql/>).

##  **How to DROP a Table in PostgreSQL**

The **DROP** command is a DDL(acronym of Data Definition Language) command that drops/deletes the existing objects of a database permanently. Using the **DROP** command, you can drop a database, table, trigger, etc. If we talk about the **DROP TABLE** command, it drops an existing table from a database. It not only drops the table but also deletes the table’s structure permanently.

 **Syntax**

The following snippet demonstrates the usage of the **DROP TABLE** command in Postgres:
    
    
    DROP TABLE tab_name;

The tab_name represents a table that will be dropped.

 **Example: How Does the DROP TABLE Command Work in Postgres?**

Let’s say we have to drop the programming_languages table that consists of the following records:
    
    
    SELECT * FROM programming_languages;

To drop the programming_languages table, we will run the below command:
    
    
    DROP TABLE programming_languages;

The above snippet states that the programming_languages table has been dropped from the respective database. Let’s verify the table’s deletion using the SELECT command:
    
    
    SELECT * FROM programming_languages;

The output proved that the DROP TABLE command successfully dropped the structure and data of the programming_languages table.

##  **Postgres TRUNCATE VS DROP VS DELETE**

The DROP command drops/removes the table from the database completely, i.e., including the table's structure. While the DELETE and TRUNCATE commands remove entries/records from the given table and retain the table structure. The TRUNCATE command always removes all the data of the selected table, while the DELETE command can delete the entire table or some specific table entries depending upon the specified condition. The DELETE command can be customized using the WHERE clause to remove some selective table records. While the TRUNCATE command can't be used with the WHERE clause.

The TRUNCATE command is faster than the DELETE query and has no match when it comes to deleting the entire table's data.

That was all the necessary information regarding the TRUNCATE, DROP, and DELETE statements.

##  **Conclusion**

In Postgres, the **TRUNCATE TABLE** command only removes the table’s data and preserves the table’s structure. The **DELETE** command deletes single, several, or all the existing records from the targeted table. While the **DROP TABLE** command not only drops the table’s data but also deletes the table’s structure permanently. Through relevant examples, this post explained the difference between the TRUNCATE, DROP, and DELETE commands.

---
[View this page online](https://www.commandprompt.com/education/postgresql-truncate-vs-drop-vs-delete/)

---

# What Does PostgreSQL regexp_matches() Function Do?

> regexp_matches() function takes in the string and the regular expression to be matched as an argument along with an optional flag and returns the first matched…

In PostgreSQL, the regexp_matches() function matches a regular expression in a specified main string. This function takes in the string and the regular expression to be matched as an argument along with an optional flag and returns the first matched substring from the main string.

Let’s get into the details of the regexp_matches() function.

##  **What Does PostgreSQL regexp_matches() Function Do?**

The regexp_matches() function basically returns the result of the first matching of the regular expression against the main string. The basic syntax of the regexp_matches() function is given below:
    
    
    regexp_matches(Main_String, Regexp[, flags]);

The regexp_match() function takes in 3 arguments:

● The first parameter is the **main string** in which the search will take place.

● The second argument is a **POSIX regular expression** that needs to be searched in the main string.

● The third argument, which is completely optional, is the flag. The **flag** is responsible for controlling the behavior of the function for example; the **”i”** flag makes a matching case-insensitively. The “ **g** ” flag will return all the matching substrings from the main string.

The function will always return a set of string values. These values correspond to the matches of the expression in the main string. If the match does not exist, the result will be NULL.

Let’s move towards an example to make it more clear.

 **Example**

If we want to match an expression from a string, we will write the query as:
    
    
    SELECT regexp_matches('bats Eaten gate Atone', 'at.');

In the above query:

● The main string is " **bats Eaten gate Atone "** in which the regular expression is going to be matched.

● The expression we want to search for is " **at. "**. You can see the regular expression contains a dot **“.”** , we can use a dot or multiple dots after and before the regular expression. The number of dots and the placement of dots simply specify the number of characters before or after the expression in the returned text.

In case of one dot after the expression "at", the query will search for the first string in the main string and will return the array of the string containing the first “at” and an additional character from the matched string after the “at”.

The output will look like this:

  
Let's add another dot before ”at” and see the results:
    
    
    SELECT regexp_matches('bats Eaten gate Atone', '.at.');

The query will look for the first “at” match in the main string and will result in the string having a character before and after the matched string in the main string. The output is:

  
You can see that the query matched the “at” expression with the string and gets the first match. The dot before and after the expression will join a character before and after the expression from the string.

In the next example, let’s use the flag ”i”. The “i” flag does the matching case insensitively. Consider the below query:
    
    
    SELECT regexp_matches('bats Eaten gate Atone', '.TO.', 'i');

So the query will search for the ”TO” expression being insensitive to the case. The result will be:

  
There is another flag that is usually used i,e, “g” flag, or global flag. This flag returns all the matching strings from the main string. Let's use it in a query:
    
    
    SELECT regexp_matches('bats Eaten   gate Atone', '.at.', 'g');

The output will contain all the strings having the expression “at”.

  
We can also use a combination of two flags as well. Such as sometimes a combination of the **“i”** and **“g”** flags is used.
    
    
    SELECT regexp_matches('bats Eaten   gate Atone', 'AT.', 'ig');

The above query will do case-insensitive matching and will result in all the matching results as output.

  
The regexp_matches() function is more flexible than the regexp_match() function because we can get the first match as well as all the matches, which the regexp_match() does not provide. So this was it about the regexp_matches() function.

##  **Conclusion**

This function matches a specified expression against a specified main string and returns the set to strings/characters that match first. We can get all the match results by using a flag **“g”** with the function. These flags are completely optional but if added will give some specific results for the function. In this article, we have discussed the regexp_matches() function in detail.

---
[View this page online](https://www.commandprompt.com/education/what-does-postgresql-regexp_matches-function-do/)

---

# How to Install and Setup PostgreSQL on Debian 12

> Use the “sudo apt install postgresql postgresql-contrib” command to install PostgreSQL from Debian 12’s default repository.

Debian 12 is the latest stable Linux distribution that introduces numerous features and improvements, including over 11,000 new packages. These notable features encourage Linux users to update their system to Debian 12.

PostgreSQL is a highly stable object-relational database that is backed by 30+ years of active development. It is compatible with several platforms/operating systems like MacOS, Linux, etc. This Multi-platform compatibility allows us to install Postgres on Debian 12 and use its extraordinary features elegantly.

##  **Quick Outline**

This Postgres blog will show you how to download, install, and use PostgreSQL on Debian 12 using the following outlines:

  *  **Prerequisite For Postgres Installation on Debian 12**
  *  **How to Install Postgres on Debian 12 Using its Default Repository?**
  *  **How to Install Postgres on Debian 12 Using PostgreSQL Repository?**
  *  **How to Setup and Use Postgres on Debian 12?**
  *  **How to Uninstall Postgres on Debian 12?**
  *  **Conclusion**



##  **Prerequisite For Postgres Installation on Debian 12**

Before you start installing Postgres on Debian 12, make sure you meet the below-listed requirements:

  1. A Debian 12 (Bookworm) Server.
  2. A User With Sudo/Admin Rights.



##  **How to Install Postgres on Debian 12 Using its Default Repository?**

The default repository of Debian 12 contains all the popular packages, and Postgres is no exception. Debian 12’s default repository is a convenient, reliable, and recommended approach to installing any package or software on Debian 12. So, it is a good practice to install Postgres from the default repository of Debian 12.

Execute the below-given steps to install Postgres on Debian 12 using its default repository:

###  **Step 1: Update System Packages**

Updating the system packages is good practice to begin the installation of any particular software package like Postgres. To do that, execute the following apt command with sudo privileges:
    
    
    sudo apt update

###  **Step 2: Install Postgres**

Once the system packages are updated, users can execute the “apt install postgresql” command with the contributed modules for Postgres to install Postgres on their Debian machine.
    
    
    sudo apt install postgresql postgresql-contrib

###  **Step 3: Verify Postgres Installation**

Execute the below command to verify the Postgres installation status:
    
    
    sudo systemctl status postgresql

From the above snippet, it is clear that Postgres has been successfully installed on Debian 12.

##  **How to Install Postgres on Debian 12 Using PostgreSQL Repository?**

Installing PostgreSQL from the official repository ensures a reliable, secure, and up-to-date database system. For this purpose, go through the following steps:

###  **Step 1: Add Postgres Repository**

The PostgreSQL Global Development Group (PGDG) repository offers Postgres packages for Debian-based systems that are built from the latest Postgres source code. To add/import pgdg on a Debian machine, execute the command:
    
    
    sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

###  **Step 2: Add the Signing Key of the Postgres Repository**

The signing key enables the system to verify the authenticity of packages signed with that key during installations or updates. Use the below command to import/add the PostgreSQL signing key from the specified URL to the system's trusted key list.
    
    
    wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

###  **Step 3: Install PostgreSQL**

Before Postgres installation, first, execute the update command to update the system packages:
    
    
    sudo apt update

Now you are just one command away to install Postgres on your Debian machine. Use the given apt command to install Postgres without any hassles:
    
    
    sudo apt install postgresql -y

##  **How to Setup and Use Postgres on Debian 12?**

Once you have successfully installed Postgres on your Debian 12 machine, you can set it up and avail its extraordinary features like security, data integrity, and many more.

###  **Step 1: Setup Postgres**

Setting up a valid and strong password for your databases is an essential practice that enhances security and prevents unauthorized access or cybercrime. To do that, execute the command:
    
    
    sudo passwd postgres

###  **Step 2: Switch to Postgres**

“postgres” is a default superuser of PostgreSQL. Use the below command to switch from “debianuser” to “postgres”:
    
    
    su -- postgres

###  **Step 3: Access SQL Shell**

psql or SQL Shell is the default terminal-based tool for Postgres. It can be used to perform any database operation using SQL queries or meta-commands. To access SQL Shell, simply type in “psql” and hit the ENTER key:
    
    
    psql

###  **Step 4: Verify Postgres Version**

In the SQL Shell, we can execute any command or query to perform a specific functionality. For instance, the following command shows the currently installed Postgres version on our Debian 12 machine:
    
    
    SELECT VERSION();

###  **Step 5: List Databases**

As a beginner, one of the must-know meta-commands is “\l” which shows the list of available databases:
    
    
    \l

###  **Step 6: Create a New Database**

Apart from the default “postgres” database, we can create a database of our own choice using the following SQL command:
    
    
    CREATE DATABASE cmd_db;

###  **Step 7: Verify Database Creation**

It's a good practice to ensure the creation of a newly created “cmd_db” database. For this purpose, run the command:
    
    
    \l

The presence of “cmd_db” in the list of available databases confirms the creation of the selected database.

###  **Step 8: Switch to New Database**

To use the newly created database, first, we need to access/switch to it. To do this, the below-given meta-command is used in Postgres:
    
    
    \c cmd_db;

###  **Step 9: Create Table**

Once you are connected to the desired database, you can perform any particular database operation like table creation, deletion, data insertion, etc. For instance, the below query creates a new table in the selected database:
    
    
    CREATE TABLE cmd_table(
     id SERIAL PRIMARY KEY,
     nam VARCHAR
     );

###  **Step 10: Verify Table Creation**

To confirm the table’s creation, execute the “\dt” command that will enlist the relation’s details like schema, table name, type, and owner name:
    
    
    \dt;

##  **How to Uninstall Postgres on Debian 12?**

If you don't need Postgres anymore, you can completely remove it from Debian 12 to free up the space. For this purpose, the apt command can be executed with the purge option that will remove Postgres along with all of its associated packages and files.
    
    
    sudo apt purge postgresql postgresql-contrib -y

That’s all about installing and setting up PostgreSQL on Debian 12.

##  **Conclusion**

PostgreSQL can be installed on Debian 12 either from Debian 12’s default repository or the PostgreSQL Repository. Use the “ **sudo apt install postgresql postgresql-contrib** ” command to install Postgres from Debian 12’s default repository or execute the “ **sudo apt install postgresql -y** ” command to install it from the PostgreSQL Repository.

In this Postgres blog, two different methods are discussed comprehensively to install PostgreSQL on Debian 12. In addition to this, different SQL queries and meta-commands are also discussed to perform several database operations. Finally, the uninstallation process of Postgres is also illustrated.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-and-setup-postgresql-on-debian-12/)

---

# How to Describe Database Objects in PostgreSQL From psql

> In Postgres, the meta-commands like “\d”, “\dt”, “\dv”, “\ds”, and “\df” are used to describe relations, tables, views, sequences, and functions, respectively.

PostgreSQL is a very popular choice among SQL users. It offers a variety of features and is compatible with numerous programming languages. Thousands of programmers use Postgres to store all the data of their web or mobile applications securely. Postgres users can create database objects like tables, views, sequences, etc., and use them whenever needed. However, performing a task on any existing database object must be done appropriately; otherwise, it may lead to inconvenience. Therefore, it's a good practice to **describe** the **database object** first, and then perform any particular functionality on them accordingly. Doing so will reduce the chances of human errors or any other inconvenience.

##  **Quick Outline**

This Postgres blog will cover the following sections:

  *  **What are Database Objects?**
  *  **What are Meta Commands in Postgres?**
  *  **How to Describe Database Objects in PostgreSQL Using psql?**
  *  **Bonus Tip 1: How to Describe Postgres Schemas Using psql?**
  *  **Bonus Tip 2: How to Describe Users Using psql?**
  *  **Final Thoughts**



Let’s get started.

##  **What are Database Objects?**

Any entity/object like a table, view, sequence, etc. that is defined in a database and is used to store or reference data is known as a database object. The most popularly used database object is a table that keeps the data in a well-structured manner. Other objects include views, sequences, indexes, tablespaces, functions, etc. In PostgreSQL, the database objects are created using the CREATE command.

##  **What are Meta Commands in PostgreSQL?**

Meta commands can be used to achieve different functionalities, such as describing any particular database object. These commands are executed only in the SQL Shell (psql). Meta commands are short commands that are executed using a backslash “\”. These commands start with a “\” symbol followed by the command verb and then the desired argument.

##  **How to Describe Database Objects in PostgreSQL From psql?**

SQL Shell or psql supports several meta-commands that help us perform different database operations, including describing the database objects. In this write-up, we will execute the different meta commands to describe the following database objects:

  1. Describe All Tables, Sequences, and Views Using \d
  2. Describe Only Tables Using \dt
  3. Describe a Single Table Using \d
  4. Describe Views Using \dv
  5. Describe Sequences Using \ds
  6. Describe Functions Using \df



Let’s implement each of the above-mentioned meta-commands practically.

###  **Example 1: Describe All Tables, Sequences, and Views Using \d**

Relations/Tables are among the most important objects of any database that stores the data in a well-organized manner. Database users often describe the relations before performing any particular functionality on them to avoid any inconvenience. This can be done using the “\d” meta-command.

The “\d” is one of the most popularly utilized commands that retrieve all the relations, including tables, sequences, views, and materialized views. To implement this command, first log into the psql, write “\d”, and hit the “ENTER” key. As a result, you will get all the details regarding all available relations in the selected database, as shown in the following snippet:
    
    
    \d

Executing the above-stated meta-command will retrieve the name of the schema in which the relation is located, the name of the relation, its type, and its owner.

Execute the stated command with the “+” symbol to describe the relations with more details like “persistence”, “access method”, “size”, and “description”:
    
    
    \d+

Do not use a semicolon at the end of the “\d” command; otherwise, you will encounter an “invalid command” error.

###  **Example 2: Describe Only Tables Using \dt**

Do you wanna get a list of all tables only, excluding views and sequences? Don't worry! This can be done by executing the “ **\dt** ” meta-command. This psql command will retrieve/describe all the tables with the following information: schema name, table name, type, and respective owner. The “\dt” command can be executed with or without a “;”. Here is a practical example that demonstrates this command better:
    
    
    \dt

Specify a “+” symbol at the end of the “\dt” command to describe the tables with some additional information like “table size”, “access method”, etc.
    
    
    \dt+

###  **Example 3: Describe a Single Table Using \d**

The “\d” command can be executed with the table name to describe a particular table. For this purpose, the user must use the “\d” command followed by the table name:
    
    
    \d author_info

On successful execution, the stated command will retrieve the following information: the table columns, data types of the columns, nullable attribute, and default value, as shown in the following screenshot:

###  **Example 4: Describe Views Using \dv**

In databases, views are virtual tables that are used to represent the result set of single or multiple tables. SQL Shell supports a very convenient meta-command named “\dv” that is used to describe Postgres views. This command retrieves information about Postgres views including the schema name to which the view belongs, the name of the view, its type, and the owner of the view.
    
    
    \dv

Run the “\dv” command along with the “+” sign to fetch the list of views with additional details:
    
    
    \dv+

###  **Example 5: Describe Sequences Using \ds**

Sequences are database objects that are used to create/generate a series of integers according to the desired specifications. Oftentimes users come across a situation where they want to check the sequence structure before performing any particular operation on any existing sequence. In such cases, users can describe the selected sequence.

To describe PostgreSQL sequences, execute the “ **\ds** ” with the following syntax:
    
    
    \ds

The “\ds” command retrieves all available sequences from the current database, which can be verified from the “Type” column.

Execute the “\ds” command with the “+” symbol to get the sequences’ list with more details like size, description, and persistence:
    
    
    \ds+

###  **Example 6: Describe Functions Using \df**

Functions are reusable code blocks that reduce the developers' efforts, enhance code efficiency, reduce code redundancy, and save a lot of time. Postgres allows users to create new functions according to their needs, which can be accessed and re-used whenever needed. However, it's a good practice to describe the already-created functions before accessing or using them. To do that, the “\df” meta-command can be executed from psql:
    
    
    \df

The stated meta-command will retrieve details about all available functions and stored procedures:

Use the “+” symbol with the “\df” command to get more details about the available functions, such as owner, security, language, etc.,
    
    
    \df+

That’s all about describing a database object in PostgreSQL using psql’s meta-commands.

###  **Bonus Tip 1: How to Describe Postgres Schemas Using psql?**

A schema in Postgres is like a container that allows us to organize the database objects into logical groups. Postgres allows us to create several schemas in a single database. Each schema can have its own set of objects like tables, views, etc.

The need to describe a schema arises when we have to check the schema’s owner, its access privileges, or its description. In such cases, several commands and queries can be executed. Among them, the most convenient one is the “\dn+” meta-command
    
    
    \dn+

###  **Bonus Tip 2: How to Describe Users Using psql?**

In database management systems like Postgres, roles, and users are created to handle access control. A user can be a normal user or a superuser and each user has different attributes and access privileges. Therefore, describing a user before accessing it minimizes the chances of errors and provides a detailed understanding of the users. For this purpose, execute the following meta-command:
    
    
    \du

The above-provided meta-command will retrieve a list of roles along with their attributes:

To learn more about describing users or schemas, navigate to the following dedicated guides: [Show Users in Postgres](<https://www.commandprompt.com/education/how-to-show-users-in-postgresql/>), [List Schemas in Postgres](<https://www.commandprompt.com/education/how-to-list-schemas-in-postgresql/>).

##  **Final Thoughts**

In Postgres, different meta-commands are used to describe database objects using psql. For instance, use the “\d”, “\dt”, “\dv”, “\ds”, and “\df” commands to describe relations, tables, views, sequences, and functions, respectively. All these meta-commands can be executed with the “+” symbol to get more details about any of these objects. All these meta-commands are implemented practically in this guide to give you a profound knowledge of describing database objects in Postgres using psql.

---
[View this page online](https://www.commandprompt.com/education/how-to-describe-database-objects-in-postgresql-from-psql/)

---

# How to Create Database Objects in PostgreSQL Using CREATE Command

> A database object is an entity defined in a database and is used to store or reference data. In Postgres, database objects are created using the CREATE command…

PostgreSQL is a highly stable object-relational database that is backed by 30+ years of active development. Postgres uses different database objects to enhance data usage and management efficiency. The renowned database objects include tables, views, sequences, indexes, stored procedures, and functions. Each database object serves a unique functionality. However, to use any database object, it must be created first in the desired database.

##  **Quick Outline**

This Postgres guide will explain the complete procedure of creating Database objects using the following outlines:

  *  **What is a Database and How to Create it in Postgres?**
  *  **What are Database Objects?**
  *  **How to Create Database Objects in Postgres Using CREATE Command?**
  *  **Bonus Tip 1: CREATE USER**
  *  **Bonus Tip 2: CREATE SCHEMA**
  *  **Bonus Tip 3: Drop Database Objects**
  *  **Conclusion**



##  **What is a Database and How to Create it in Postgres?**

Databases are the systematic collection of structured data/information, which is controlled by a database management system. To create a new database, execute the CREATE statement followed by the DATABASE keyword, as shown in the following syntax:
    
    
    CREATE DATABASE name_of_database
     WITH
     [OWNER = name_of_user]
     [TEMPLATE = template_name]
     [ENCODING = encoding]
     [LC_COLLATE = collate]
     [LC_CTYPE = ctype]
     [TABLESPACE = name_of_tablespace]
     [ALLOW_CONNECTIONS = true | false]
     [CONNECTION LIMIT = maximum_connections]
     [IS_TEMPLATE = true | false ]

The syntax seems a little bit complicated, let’s comprehend it line-by-line.

\- The “ **CREATE DATABASE** name_of_database” creates a new database. Replace the “name_of_database” with any valid and easily rememberable/understandable database name.

\- The database name is followed by the “ **WITH** ” clause that is used to specify the parameters for the database.

\- Specify the user/owner name using the “ **OWNER** ” clause.

\- Specify the template name from which the new database will be created using the **TEMPLATE** keyword.

\- Specify the character set encoding scheme to be used in the new database.

\- Specify the default collation order and character classification for the new database using the **LC_COLLATE** parameter.

\- Specify the character classification for the new database using the “ **LC_CTYPE** ” parameter.

\- Specify the tablespace of your choice using the **TABLESPACE** parameter.

\- Specify a Boolean **TRUE** or **FALSE** to manage the connections. If **FALSE** no one can connect to the database, otherwise, users can connect to the database.

\- Define the connection limit via the **CONNECTION LIMIT** parameter. If you want unlimited connections then use the “-1” value for the “ **CONNECTION LIMIT** ” parameter.

\- Specify a Boolean TRUE or FALSE in the “ **IS_TEMPLATE** ” parameter. Specifying the TRUE value means anyone can clone/duplicate the database while specifying FALSE means only superusers/owners can clone the database.

###  **Example: Create New Database**

In the following code, the “ **CREATE DATABASE** ” command is executed to create a new database named “postgres_db”:
    
    
    CREATE DATABASE postgres_db;

The output confirms the database creation:

##  **What Are Database Objects?**

Any entity that is defined in a database and is utilized to store or reference data is called a database object. Postgres supports several database objects, such as a table, view, sequence, index, etc. The most frequently used object is a table that keeps the data in a well-structured manner. Other objects include views, sequences, indexes, tablespaces, functions, etc.

##  **How to Create Database Objects in Postgres Using CREATE Command?**

In PostgreSQL, the database objects are created using the CREATE command. In this write-up, we will discuss how to use the Postgres “CREATE” command for Table, View, Sequence, INDEX, Function, and Tablespace Creation.

###  **Case 1: Use the CREATE Command For Table Creation**

Tables are among the most frequently utilized database objects that keep the data in the form of rows and columns. In Postgres, the CREATE command can be executed with the “TABLE” keyword to [create a table](<https://www.commandprompt.com/education/different-methods-to-create-a-table-in-postgresql/>) in the desired database. For this purpose, the following syntax is used in Postgres:
    
    
    CREATE TABLE [IF NOT EXISTS] tab_name (
     col1 data_type col_contraint,
     col2 data_type col_contraint,
     col3 data_type col_contraint,
     …
     tab_constraints
     );

Let’s break down this syntax line-by-line to get a better understanding:

\- “CREATE TABLE” is a statement that creates a new table.

\- “[IF NOT EXISTS]” is an optional clause that ensures the table creation only if it is not already created.

\- “tab_name” represents the table name to be created.

\- “col1, col2, col3, …, ” are the column names to be created.

\- “data_type” represents any valid data type, such as int, float, text, etc.

\- “col_contraint” represents column constraints like a PRIMARY KEY, NOT NULL, etc.

\- “tab_constraints” indicates the table rules/constraints, such as PRIMARY KEY, FOREIGN KEY, etc.

###  **Example: Create Table Using CREATE Command**

In this example, a table named “athlete” will be created with four columns: “athlete_id”, “athlete_name”, “athlete_age”, “athlete_weight”:
    
    
    CREATE TABLE IF NOT EXISTS athlete(
     athlete_id INT PRIMARY KEY,
     athlete_name TEXT,
     athlete_age SMALLINT,
     athlete_weight SMALLINT
     );

Here,

\- A column named “athlete_id” of type “INT” is created as a “PRIMARY KEY”.

\- After that, an “athlete_name” column of type “TEXT” is created.

\- Finally, the “athlete_age” and “athlete_weight” columns of type SMALLINT are created.

The “CREATE TABLE” message in the output confirms the successful creation of the selected table, i.e., “athlete”.

###  **Case 2: Use the CREATE Command For View Creation**

A View is a virtual/logical table that is used to simplify a complex query. Views represent the data of single or multiple tables using a SELECT query. Views (except for a materialized view) didn't store the data physically like regular/normal tables.

In PostgreSQL, the “CREATE” command can be executed with the “VIEW” keyword to [create a view](<https://www.commandprompt.com/education/how-to-create-a-view-in-postgresql/>), as demonstrated in the following syntax:
    
    
    CREATE VIEW name_of_view AS select_query;

Here,

\- “CREATE VIEW” is a command that creates a new virtual table.

\- “name_of_view” is a view to be created.

\- “select_query” can be a simple select statement or a complex one with joins.

All in all, the above statement will create a view based on the query specified after the “AS” keyword.

###  **Example: Create View Using CREATE Command**

In this example, we will create a view named “athlete_info” based on the “athlete” table”
    
    
    CREATE VIEW athlete_info
    AS SELECT athlete_id, athlete_name
    FROM athlete;

The SELECT query fetches the “athlete_id”, and “athlete_name” columns of the athlete table. The “CREATE VIEW AS” statement creates a new view based on the fetched column.

This way, a view can be created in Postgres.

###  **Case 3: Use the CREATE Command For Sequence Creation**

A sequence in Postgres is a schema-bound object that generates a series of integers according to the given specifications. A [sequence can be created](<https://www.commandprompt.com/education/how-to-create-a-sequence-in-postgresql/>) in Postgres by executing a CREATE statement followed by a “SEQUENCE” keyword.
    
    
    CREATE SEQUENCE [ IF NOT EXISTS ] name_of_sequence
     [ AS { INT | BIGINT | SMALLINT} ]
     [ INCREMENT [ BY ] increment_val ]
     [ MINVALUE min_val | NO MINVALUE ]
     [ MAXVALUE max_val | NO MAXVALUE ]
     [ START [ WITH ] initial_value ]
     [ CACHE cache ]
     [CYCLE | NO CYCLE]
     [ OWNED BY { table_name.col_name | NONE } ]

Let’s comprehend this syntax line-by-line,

\- “ **CREATE SEQUENCE [IF NOT EXISTS] name_of_sequence** ” creates a new sequence if it doesn’t exist already.

\- “ **[AS { INT | BIGINT | SMALLINT}]** ” specifies the data type of the sequence.

\- “ **[INCREMENT [ BY ] increment_val]** ”, “ **[ MINVALUE min_val | NO MINVALUE ]** ”, **[ MAXVALUE max_val | NO MAXVALUE ]** ”, **[ START [ WITH ] initial_value ]** specifies the increment, minimum, maximum, and initial value of the sequence.

\- **[ CACHE cache ]** is used to determine sequence numbers that are pre-allocated or stored in the memory for faster/quick access.

\- **[CYCLE | NO CYCLE]** determines the restarting behavior of the sequence. If you specify “ **CYCLE** ”, the sequence will restart once it reaches the maximum limit. By default, the “NO CYCLE” behavior is enabled for the sequence.

\- **[ OWNED BY { table_name.col_name | NONE } ]** is used to associate the sequence with a specific table column. This way, when a user drops a table or column it will automatically delete the associated sequence.

###  **Example: Create Sequence Using CREATE Command**

In this example, we will create a sequence named “athlete_sequence” with SMALLINT data type, as shown in the following snippet:
    
    
    CREATE SEQUENCE athlete_sequence
     AS SMALLINT
     INCREMENT 1
     MAXVALUE 15
     START 1;

Here, the initial value of the sequence is 1, the maximum value is 15, and the increment value is 1. The below output confirms the sequence creation:

###  **Case 4: Use the CREATE Command For INDEX Creation**

In databases, when a user fetches a record the query optimizer searches for that record from the entire table and loads it when the perfect match is found. This procedure might take/consume a lot of time. To overcome this problem, [indexes can be created](<https://www.commandprompt.com/education/how-to-create-an-index-in-postgresql/>) that enable us to mark a particular table or table columns that are used frequently in our queries. To create an index, execute the CREATE statement along with the INDEX keyword, as demonstrated in the following syntax:
    
    
    CREATE INDEX <name_of_index>
     ON <table> <USING method>
     (
     col_name [ASC | DESC] [NULLS {FIRST | LAST }],
     …
     );

In the above-stated syntax:

\- Specify the “CREATE INDEX” statement followed by the name of the index to be created.

\- After that, specify the ON clause and then the name of the associated/linked table.

\- Next, specify the USING keyword followed by the index method, such as “btree”, “spgist”, “hash”, etc. If you don’t specify any method, Postgres will use the default method i.e., “btree”.

\- After that, specify a single or multiple columns of the index followed by their sorting order, i.e., ASC or DESC.

\- Finally, you can specify the “NULLS FIRST” or “NULLS LAST” option to sort the column that contains NULL values.

###  **Example: Create INDEX Using CREATE Command**

Execute the SELECT query with the “EXPLAIN” statement to get the query plan:
    
    
    EXPLAIN SELECT *
     FROM athlete
     WHERE athlete_name = 'Null';

The following screenshot demonstrates that the query doesn’t use an index:

Let’s create an INDEX by executing the following query:
    
    
    CREATE INDEX index_athlete_name
    ON athlete(athlete_name);

The following snippet ensures that an index named “index_launch_date” has been successfully created on the “athlete_name” column of the “athlete” table:

Now the database will use this index to pursue the athlete_name column of the athlete table.
    
    
    EXPLAIN SELECT *
     FROM athlete
     WHERE athlete_name = 'Null';

###  **Case 5: Use the CREATE Command For Function Creation**

Functions are one of the most significant database objects that ensure the efficient reusability of the code. To [create a user-defined function](<https://www.commandprompt.com/education/create-function-statement-in-postgresql/>) in PostgreSQL, the **CREATE** command can be executed with the “ **FUNCTION** ” keyword, as illustrated in the following syntax:
    
    
    CREATE [ OR REPLACE ] FUNCTION name_of_function(arg_list)
     RETURNS return_data_type
     LANGUAGE plpgsql
     AS
     $$
     DECLARE
     -- Declare the variable here
     BEGIN
     -- user-defined logic
     END;
     $$

In the given syntax,

\- The “ **CREATE [ OR REPLACE ] FUNCTION** ” statement ensures the creation of a new or updation of an existing function.

\- The “name_of_function” is the function name to be created.

\- “arg_list” represents the arguments to be accepted by the function.

\- Inside the function’s body, use the “ **RETURNS** ” keyword followed by the returned data type.

\- After that, specify the procedural language of the function such as plpgsql.

\- Finally, use the dollar-quoted string constant “ **$$** ” to specify the rest of the code/logic.

###  **Example: Create Function Using CREATE Command**

In the following example, a simple function named “age_counter” is created that counts the athletes whose age is between “start_range” and “end_range” :
    
    
    CREATE OR REPLACE FUNCTION age_counter(start_range INT, end_range INT)
     RETURNS INT
     LANGUAGE plpgsql
     AS
     $$
     DECLARE
     age_count INT;
     BEGIN
     SELECT COUNT(*)
     INTO age_count
     FROM athlete
     WHERE athlete_age between start_range and end_range;
     RETURN age_count;
     END;
     $$

In this example,

\- A function is created as “age_counter” that accepts two arguments “start_range” and “end_range” of type INT.

\- The return type of age_counter() is INT.

\- A variable of type INT is declared as age_count.

\- The COUNT() function is implemented to count/compute the age between the specified range.

\- In the end, the RETURN keyword is used to return the “age_count”.

Execute the following line of code to get the list of all those athletes whose age is greater than 28 but less than 32:
    
    
    SELECT age_counter(28, 32);

The output illustrates that there are five athletes whose age is between 28 and 32 (both inclusive).

###  **Case 6: Use the CREATE Command For Tablespace Creation**

Tablespace is a place/location on the disk where all the database objects are stored/located. To [create a new tablespace](<https://www.commandprompt.com/education/how-to-create-a-tablespace-in-postgresql/>) in Postgres, run the CREATE command with the TABLESPACE keyword, as shown in the following syntax:
    
    
    CREATE TABLESPACE name_of_tablespace
     OWNER name_of_user
     LOCATION directory_location;

Here,

\- The CREATE TABLESPACE statement is followed by the “name_of_tablespace” to be created.

\- Next, the OWNER clause is used to specify the user’s name who owns the tablespace.

\- Finally, the path at which the tablespace will be created is specified using the LOCATION keyword.

###  **Example: Use the CREATE Command to Create a Tablespace**

In the following example, the CREATE TABLESPACE statement is executed to create a new tablespace named “postgres_tablespace”:
    
    
    CREATE TABLESPACE postgres_tablespace
     LOCATION 'C:\New folder';

The output snippet illustrates that a tablespace has been successfully created at the desired location

##  **Bonus Tip 1: CREATE USER**

Every database has several users and each user has different roles and access privileges. These users are different/separate from the OS users. The database users own different database objects, such as tables, indexes, functions, etc. These users help us manage the database objects’ access privileges efficiently. To [create a user](<https://www.commandprompt.com/education/how-to-create-a-user-in-postgresql/>) in Postgres, the CREATE command can be executed with the USER keyword, as illustrated in the following syntax
    
    
    CREATE USER name_of_user;

Replace the “name_of_user” with any name of your choice.

###  **Example: Use the CREATE Command to Create a User**

The following code creates a new database user named “db_user”:
    
    
    CREATE USER db_user;

The output confirms the creation of the desired user:

##  **Bonus Tip 2: CREATE SCHEMA**

A Postgres schema is a named collection of different objects like tables, functions, views, sequences, etc. Postgres allows us to create several schemas in a single database, which helps us manage database objects into logical groups efficiently. To [create a new Postgres schema](<https://www.commandprompt.com/education/how-to-create-schema-in-postgresql/>), execute the CREATE command with the SCHEMA keyword, as we did in the following syntax:
    
    
    CREATE SCHEMA <name_of_schema>;

Specify a valid schema name of your choice in place of “name_of_schema”.

###  **Example: Use CREATE Command to Create a Schema**

In the following example, a new schema named “emp_schema” will be created:
    
    
    CREATE SCHEMA emp_schema;

The output snippet confirms the schema creation:

##  **Bonus Tip 3: Drop Database Objects**

In databases, each database object carries a specific amount of space. In case, an object is no longer needed, you can drop/delete it from the database. Doing so will clean the database, which will eventually help you manage your database efficiently. To drop a database object, specify the DROP command followed by the database object to be dropped, as demonstrated in the following syntax:
    
    
    DROP datababse_object name_of_object;

Here,

\- Replace the “database_object” with any valid object, such as “TABLE”, “VIEW”, “INDEX”, etc.

\- After that, specify the name of the object (view name, table name, index name, etc.) to be dropped in place of “name_of_object”.

 **Example: Drop Database Object Using DROP Command**

In the following example, a tablespace will be dropped using the DROP statement:
    
    
    DROP TABLESPACE postgres_tablespace;

The output confirms that the selected tablespace has been successfully dropped:

That’s all about creating or dropping a database object in PostgreSQL.

##  **Conclusion**

Database objects are entities that are defined in a database and used to store or reference data. In PostgreSQL, the database objects are created using the **CREATE** command. The most frequently used object is a table that stores the data in a well-structured format. The other renowned database objects include tablespaces, views, sequences, indexes, stored procedures, and functions. Each database object serves a unique functionality. This Postgres blog has illustrated the use of each database object with suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-database-objects-in-postgresql-using-create-command/)

---

# How to Use ARRAY_UPPER() Function in PostgreSQL

> The ARRAY_UPPER() function in PostgreSQL returns the upper bound of the array dimension or the highest index of an array.

Postgres allows us to create an array and perform several operations on it, such as adding new elements to it, removing unnecessary elements from it, etc. These operations can be performed using different built-in array functions and operators. One such function is the **ARRAY_UPPER()** which gives the upper bound/ the maximum value of the dimension of the array provided to it.

This guide will comprehensively illustrate the use of the **ARRAY_UPPER()** function in Postgres.

##  **How to Use PostgreSQL ARRAY_UPPER() Function**

The **ARRAY_UPPER()** function takes a couple of parameters and retrieves the upper bound of the dimension of the provided array. The basic query for the **ARRAY_UPPER()** function can be written as:
    
    
    ARRAY_UPPER(array,dim)

● The **ARRAY_UPPER()** function takes in an **array** as a first argument.

● The second argument of this function is the **dimension of the array** along which we wish to find the upper bound.

 **Return Value**

The ARRAY_UPPER() retrieves the upper bound of its dimensions or the highest index of the array in **integer** data type. It returns **NULL** if the dimension specified is greater than the original dimension of the specified array.

Let’s get into the examples to understand how the function actually works.

###  **Example 1: Understanding the ARRAY_UPPER() Function**

Now we will try to understand the workings of the **ARRAY_UPPER()** function by using the following query:
    
    
    SELECT ARRAY_UPPER(ARRAY[10, 9, 8, 7], 1);

We have passed the array and the dimension in the **ARRAY_UPPER()** function. As a result, the query gives the highest/maximum index of the array dimension.

We can observe that the array is a one-dimensional array and the highest index of the specified array is **4**. So the **ARRAY_UPPER()** function has returned **4**.

We can also use the [array_dims()](<https://www.commandprompt.com/education/how-to-use-array_dims-function-in-postgresql/>) function to get the dimensions of an array like this:
    
    
    SELECT ARRAY_DIMS(ARRAY[10, 9, 8, 7])

This function returns the dimensions of the passed array like this:

We can see that the dimension of the array is [1:4] and the highest/ upper bound dimension of the array is 4. This function can be used to verify the simple cases.

###  **Example 2: Using the ARRAY_UPPER() Function With 2-Dimensional Array**

We can also implement the **ARRAY_UPPER()** function on the 2-dimensional array. Same as above, the array and the dimension along which we want to get the upper bound of the array (2 in this case), need to be specified as the function parameters. Consider the following query for this case:
    
    
    SELECT ARRAY_UPPER(array[ [11,52,83],[14,55,76] ], 2);

We can see that the provided array is a 2-dimensional array which can be written as; [1:2][1:3] so the highest index in this query is **3**. The query will return 3 as output.

We can witness that the query gave the same result as per our expectations.

###  **Example 3: Specifying the Wrong Dimension in ARRAY_UPPER() Function**

The dimension of the array must be specified correctly. If the dimension specified is invalid, this would return NULL. Let’s execute the same query with dimension 4.
    
    
    SELECT ARRAY_UPPER(array[ ['Alex','Peter','Kate'],['Williams','Smith','Charles'] ], 4);

We can see that passing the incorrect dimension results in a NULL. we can also verify this by using the[ **IS NULL**](<https://www.commandprompt.com/education/postgresql-is-null-operatorcondition/>) Operator like this:
    
    
    SELECT ARRAY_UPPER(
      array[ ['Alex','Peter','Kate'],['Williams','Smith','Charles'] ]
      , 4) IS NULL;

The **IS NULL** operator retrieves TRUE if the value is NULL otherwise it returns FALSE. So in this case the output is:

The query has yielded **TRUE** which simply ensures that the ARRAY_UPPER() function returns a **NULL**.

 **Note** that the dimension specified needs to be smaller or equal to the original dimension of the provided array. If the dimension specified is greater(as in the above example), the query will return NULL.

###  **Example 4: Using ARRAY_UPPER() Function With Multi-dimensional Array**

We have seen a **NULL** case in the above example but the function only returns NULL if a greater dimension is specified than the original dimension of the array. Let's see this in the below query.
    
    
    SELECT ARRAY_UPPER(
      array[ ['Alex','Peter','Kate'],['Williams','Smith','Charles'] ]
      , 1);

The provided array is 2-dimensional but we have specified 1 as the dimension along which we want to find the upper bound of the array dimension. In this case, the **NULL** value will not be returned by the **ARRAY_UPPER()** function. Instead, the array will be considered as a nested array with 2 elements(the inner arrays). So in the above case, when the array is acting as 1 dimensional, the array becomes the nested array with 2 elements i.e. “['Alex','Peter','Kate']” and “['Williams','Smith','Charles']”. Running the query will give the highest value of the array index. The query yields the following output.

The first array element, “['Alex','Peter','Kate']”, is at index 1, and “['Williams','Smith','Charles']” is at index 2. So the **ARRAY_UPPER()** function has returned 2.

###  **Example 5: Advance Usage of ARRAY_UPPER() Function**

We can also specify the starting and ending indexes of the array. Let’s consider the below query as an example to implement this.
    
    
    SELECT ARRAY_UPPER('[0:3]={97,28,163,6}'::integer[], 1)

In the above query, we have specified the starting and ending indexes i.e. **0** and **3** respectively. This means that the indexing of the above array will start from 0 to 3. We can observe the array in string quotes so we have to do the typecasting into the integer data type. The second parameter illustrates that the array is a one-dimensional array.

Following is the output given by the query.

The highest index in this case is 3. That’s why the **ARRAY_UPPER()** function has returned 3.

###  **Example 6: Using ARRAY_UPPER() Function With Multi-dimensional Array (Advanced)**

The above given was a simple case when we had a one-dimensional array. The situation becomes tough and different in the case of 2 or higher-dimensional arrays. Consider the following case:
    
    
    SELECT ARRAY_UPPER('[2:4][2:3]={{1,1},{1,1},{1,1}}'::integer[], 1);

In the above query, the ending points are given which simply means that the query will assign the indexes according to the specified ending points. As in the above query, we want to get the upper bound of the array dimension along the first dimension. It means that the array will be considered as one-dimensional with the nested arrays which will be the elements of the array. This will automatically skip the second ending points i.e. [2:3]. Now, the indexing according to the [2:4] will take place i.e. 2, 3, 4, and the query will return the result accordingly. The output of this query should be 4, as the highest indexing value is 4.

The output of the above query is:

The result of the query is as per our expectations.

The scenario becomes somewhat different if we declare the dimension as 2 in the above query. Like this:
    
    
    SELECT ARRAY_UPPER('[2:4][2:3]={{1,1},{1,1},{1,1}}'::integer[], 2);

In this case, we specified the dimension as 2. This means that we want to find and get the dimension of the given array **along** the second dimension.

So the [2:3] will be considered the endpoints of the given nested arrays. We can see that the upper bound of the array dimensions in the above case of the second-dimensional array is 3. Let’s see the output of the query.

We can see that the query resulted in 3 as the upper bound of array dimensions. This is how the ARRAY_UPPER() function works.

###  **Conclusion**

The **ARRAY_UPPER()** function in PostgreSQL returns the upper bound of the array dimension or the highest index of an array. The **ARRAY_UPPER()** takes in the array and the dimension of an array along which to find the highest index as arguments and returns the highest index of the array. If the dimension specified in the function is greater than the dimension of the array, the function will give a **NULL** value as outpu **t**. This post has illustrated the basic concept of the **ARRAY_UPPER()** function along with its working and examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-array_upper-function-in-postgresql/)

---

# How do I remove null values with the jsonb_strip_nulls function in PostgreSQL?

> The PostgreSQL stores data and there are a lot of chances that the data being recorded might contain NULL values. The root cause of these NULL values may be so…

The PostgreSQL stores data and there are a lot of chances that the data being recorded might contain NULL values. The root cause of these **NULL** values may be some discrepancies in the system generating the data or maybe due to inefficient/incorrect data entry. The **JSONB** is a widely used data type in Postgres that stores an immense range of textual data in the form of key-value pairs. So the NULL values also appear in **JSONB** data.

We need to get rid of these **NULL** values in order to perform effective operations on the data and also to get useful insights from the data, which is not possible until we have the **NULL** value present in our data. To remove the **NULL** value field from the **JSONB** data, we use the **jsonb_strip_nulls()** function.

The content of this blog is based on the usage of the **jsonb_strip_nulls()** function using examples. So let’s get started.

##  **How to Remove Null Values With the jsonb_strip_nulls Function in PostgreSQL?**

The PostgreSQL **jsonb_strip_nulls()** Function removes the fields/keys that include the NULL values. Any other value/parameter(other than JSONB object) passed, remains unchanged by the function even if it contains NULL values. The basic format/syntax of the PostgreSQL **jsonb_strip_nulls()** Function is given as
    
    
    jsonb_strip_nulls(jsonb_val   JSONB)

The syntax says that:

● We need to provide the **JSONB** value in the **jsonb_strip_nulls()** function.

● The function will return the **JSONB** values, with the fields containing NULL values, removed.

● If the parameter is specified as **NULL** , the function will return **NULL**.

The **jsonb_strip_nulls()** function is the same as the **json_strip_nulls()** function used to remove the NULL field from the **JSON** data fields. Below are the examples that illustrate how the **jsonb_strip_nulls()** function works in PostgreSQL.

###  **Example 1: Understanding the jsonb_strip_nulls() Function**

In the below query, we have provided the JSONB object that contains the marks of different students and the NULL, in case, the student has not attempted the test. Now if we want to remove the field (the students who have not attempted the test), we will use the **jsonb_strip_nulls()** function on the data.
    
    
    SELECT jsonb_strip_nulls(
      '{"stud1_marks": 85,
      "stud2_marks": null,
      "stud3_marks": 92,
      "stud4_marks": 77,
      "stud5_marks": null}');

On execution, the above query will return the data of students who have attempted the test.

We can observe that the fields having **NULL** values are removed from the provided data. This is the function of the **jsonb_strip_nulls()** function. We can also notice that the returned data type of the **jsonb_strip_nulls()** function is **JSONB**.

This was a simple example, let’s consider another example.

###  **Example 2: More About the jsonb_strip_nulls() Function**

As stated above, the **jsonb_strip_nulls()** function only removes the NULL value fields that are present in the JSONB object. NULL values present on other parameters other than the JSONB objects remain unaffected by the **jsonb_strip_nulls()** function. Let’s see an example of this:
    
    
    SELECT jsonb_strip_nulls(
      '[84, null, 53, 
      {"stud1_marks": 85,
      "stud2_marks": null,
       "stud3_marks": 92,
       "stud4_marks": 77,
       "stud5_marks": null}]');

In this query, we have provided a JSONB array to the **jsonb_strip_nulls()** function. The **JSONB** array has elements, also containing a **NULL** value, and a JSONB object as well. The JSONB object contains fields that have NULL values. Let’s execute the query to see what it will return.

It is clear from the above output that the fields having **NULL** values are removed from the JSONB objects while the NULL other than the **JSONB** object remains unaffected.

###  **Example 3: Using the jsonb_strip_nulls() Function On Table’s Data**

We can also implement the **jsonb_strip_nulls()** function on the table’s data. The table’s name is “results” and it is given as

The “marks_record” column, which is the JSONB column containing the JSONB objects. We will now implement the **jsonb_strip_nulls()** function in this column for the “results” table. The query can be written as
    
    
    SELECT jsonb_strip_nulls(marks_record) 
    FROM results;

The **jsonb_strip_nulls()** function will remove all the NULL value fields from the JSONB objects present in the “marks_record” column of the above data.

The query returned the JSONB objects without the NULL value fields. This is how the **jsonb_strip_nulls()** function strips all the NULLs from the JSONB objects.

##  **Conclusion**

The PostgreSQL **jsonb_strip_nulls()** function strips the fields in the **JSONB object** that have NULL values. The JSONB object is to be provided to the **jsonb_strip_nulls()** function and it returns the fields with non-null values. The **jsonb_strip_nulls()** function will not affect any other data such as an array, etc., other than the JSONB object. It will return the same object unaffected. In the above post, we have learned about the **jsonb_strip_nulls()** function with the help of proper implementation.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-remove-null-values-with-the-jsonb_strip_nulls-function-in-postgresql/)

---

# How to convert JSONB to a record using jsonb_to_record in PostgreSQL

> The Postgres jsonb_to_record() function takes a top-level JSONB object, converts it into a table record/row, and returns it.

We can store the JSONB data in a Postgres table. This makes the data more readable, comprehendible, and easy to understand to generate analytics. Many functions are used to perform this particular task such as jsonb_populate_record(), jsonb_populate_recordset(), jsonb_to_record(), and jsonb_to_recordset() functions. All of these functions work in their particular way and have their limitations and restrictions. This blog will be based on the **jsonb_to_record()** function. Let’s see how the **jsonb_to_record()** function converts the JSONB object into table records in PostgreSQL.

##  **How to Convert JSONB to a Record Using jsonb_to_record in PostgreSQL**

The PostgreSQL **jsonb_to_record()** function takes a top-level **JSONB object** as input and gives a single row expanded from that JSONB object, having the corresponding data type defined in the **AS** clause. The basic/fundamental structure of **jsonb_to_record()** function looks like this:
    
    
    jsonb_to_record(jsonb_obj JSONB) AS (col1 data_type, col2 data_type,..... Coln data_type)

In the above syntax:

● The **jsonb_to_record()** function takes the top-level **JSONB object**.

● The **jsonb_to_record()** function gets followed by an **AS** clause.

● After the **AS** clause, we need to specify the list of columns with their data types i.e. the list of column definitions.

● The **JSONB** object is converted into a single row, having **RECORD** data type.

This function is almost the same as the **json_to_record()** function used to convert JSON objects into a record. To illustrate the working of the **jsonb_to_record()** function, we’ll consider some examples given below.

###  **Example 1: Understanding the jsonb_to_record() Function**

The following query demonstrates the working of the **jsonb_to_record()** function.
    
    
    SELECT
      *
     FROM
      jsonb_to_record(
      '{"customer_id": 14,
       "customer_name": "Williams J",
       "items_buy": ["Cookies", "Jam"]}' ) 
     AS cols(customer_id INT, customer_name TEXT, items_buy TEXT[]);

In the above query:

● We have specified a top-level JSONB object i.e _' {"customer_id": 14, "customer_name": "Williams J", "items_buy": ["Cookies", "Jam"]}'_, in the **jsonb_to_record()** function.

● After the **AS** keyword, we have written the column names with their individual data types.

● The **jsonb_to_record()** function will give a single table row created from the provided JSONB object. The name and type of columns will be the same as specified after the **AS** keyword.

The output of this query is given below:

If we observe the above output screenshot, we will be able to understand that the **JSONB** object is transformed into a table record/row. The name and data type of columns are the same as we declared after the **AS** keyword.

###  **Example 2: More About the jsonb_to_record() Function**

In this example, we will notice the impact, when a field in the JSONB object is missing but we have created a column for it. Consider the following query for this case.
    
    
    SELECT
      *
     FROM
      jsonb_to_record(
      '{"customer_id": 14,
      "items_buy": ["Cookies", "Jam"]}' ) 
     AS cols(customer_id INT, customer_name TEXT, items_buy TEXT[]);

The field named “customer_name” is missing from the JSONB object, while the column has been created for it. For such cases, the column is created with the name as specified by the value for that field/key will be NULL like this:

This is how the **jsonb_to_record()** function responds to such a case. Now let’s see the impact if we do not provide the **AS** keyword on the working of the **jsonb_to_record()** function.

###  **Example 3: Executing the jsonb_to_record() Function Without the AS Keyword**

As we have stated the significance and importance of the **AS** keyword earlier i.e. after it, we specify the name and type of the columns, we will see how the function reacts to the absence of **AS** statement. Consider the following query.
    
    
    SELECT
      *
     FROM
      jsonb_to_record(
      '{"customer_id":   14,
       "customer_name": "Williams J",
       "items_buy": ["Cookies", "Jam"]}' );

We have removed the **AS** statement from the query. Running the query will give the following output:

Executing the above query has thrown an error, which says that we have not specified the column definition list. This clearly illustrates that the **AS** statement and the column definition list are important for the **jsonb_to_record()** function to execute and create a record from the provided **JSONB** object.

###  **Example 4: Using User-Defined Data Type With the jsonb_to_record() Function**

In the **AS** statement of the **jsonb_to_record()** function, we can also define a column with a user-defined data type. We will first create a custom data type using the **CREATE TYPE** statement for the same above-considered example. Let’s create a custom data type named “quantity” showing the quantity count for the items.
    
    
    CREATE TYPE quantity 
     AS (item1_qty INT, item2_qty INT)

We have created a custom data type i.e. “quantity”. This data type contains two fields for “item1_qty” and “item2_qty” both of integer type. Execution of the above query will successfully create a new user-defined data type.

We will now use it in the column definition in the **jsonb_to_record()** function. The query can be written as
    
    
    SELECT
      *
     FROM
      jsonb_to_record(
      '{"customer_id": 14,
       "customer_name": "Williams J",
       "items_buy": ["Cookies", "Jam"],
       "quantity":{"item1_qty": 5, "item2_qty": 1}}' ) 
     AS   cols(customer_id INT, customer_name TEXT, items_buy TEXT[],quantity quantity);

In the above query, we have used the created user-defined data type “quantity” for the column definition. The query will return the following output.

We can see that another column is added. The new column “quantity” has the data type “quantity” as defined in the custom data type creation.

This is how the **jsonb_to_record()** function works in PostgreSQL.

###  **Additional Information**

To get multiple rows from the JSONB objects, we can use the **jsonb_to_recordset()** function. This function almost works the same as the **jsonb_to_record()** function the additional thing is that we can get multiple rows using the **jsonb_to_recordset()** function methods. For that, we will provide the **jsonb_to_recordset()** function, with a JSONB array containing multiple JSONB objects so that they can be converted into a set of rows.

###  **Conclusion**

The Postgres **jsonb_to_record()** function takes a top-level **JSONB object** , converts it into a table record/row, and returns it. The **AS** statement is used with the **jsonb_to_record()** function and is necessary for the execution of the function. After the **AS** statement, we specify the list of column names with their data type i.e. column definition list. The **jsonb_to_record()** function returns the **JSONB** object’s data according to those table columns.

---
[View this page online](https://www.commandprompt.com/education/how-to-convert-jsonb-to-a-record-using-jsonb_to_record-in-postgresql/)

---

# PostgreSQL json_populate_record() Function

> The json_populate_record() function in Postgres converts the JSON object into a data row. It populates the table record from the JSON object.

The JSON objects store values in the form of keys and values in the same manner as the tables do. In this regard, they can be transformed into the table data/ table row. This is the function of the **json_populate_record()** function in PostgreSQL. The **json_populate_record()** function is a system function, that takes the **JSON object** and returns the same **JSON object** expanded into a row. The following blog comprises a detailed demonstration of the basic concepts of the **json_populate_record()** function along with practical implementation.

##  **PostgreSQL json_populate_record() function**

The **json_populate_record()** function takes in JSON objects and returns the components of those JSON objects, expanded in a table row. The basic structure of the **json_populate_record()** function is given as:
    
    
    json_populate_record(base_val ANYELEMENT, json_obj JSON) -> ANYELEMENT

In the above syntax:

● The **json_populate_record()** function takes 2 parameters.

● The **base value** can be a value of any data type that illustrates the type of value, in which the JSON object is to be converted.

● The **json_obj** parameter illustrates the **JSON object** that we want to convert.

The **json_populate_record()** function gives the JSON object converted into a customized SQL type value that is specified in the first parameter.

The value of the base is usually declared as NULL. This means that any output column that does not match the JSON object field will return a null value.

The above statements might seem complex but let’s discuss them using examples so that the working of **json_populate_record()** function becomes easy to understand. Let’s move forward with examples.

###  **Example 1: Understanding json_populate_record() Function**

To better understand how the **json_populate_record()** function is implemented follow the steps.

 **Step 1: Create A Custom Type**

We will first have to create a custom data type to do the further implementation. Let’s create the custom data type with the name “registered_students”.
    
    
    CREATE TYPE registered_students 
    AS( stud_id INT,stud_name TEXT, subjects TEXT[])

A user-defined data type is successfully created in the Postgres.

 **Step 2: Use the json_populate_record() Function**

We can now apply the **json_populate_record()** function on this type. We can write the following query for this case.
    
    
    SELECT * FROM
      json_populate_record(
      null::registered_students,
      '{"stud_id": 1,
       "stud_name": "Kate Peter",
       "subjects": ["Physics", "Organic Chemistry"]}');

In this code:

● The base value is considered as NULL. This means that if any JSON object field(provided as a second argument) is missing, the function will return a null value in place of it we will see this case as well.

● In the second argument, we have specified the JSON object that we wish to convert.

The output of this query looks like this:

We can see that the **json_populate_record()** function has converted the specified **JSON** object into the table row.

This is how the **json_populate_record()** function basically works.

###  **Example 2: Base Value in json_populate_record() Function**

The base value is usually declared as NULL. This is because if some field of the JSON object is missing, the function will return NULL in its place. Let’s not specify the “subjects” field in the JSON object. We’ll see how it will be executed.
    
    
    SELECT * FROM
      json_populate_record(
      null::registered_students,
      '{"stud_id": 1,
      "stud_name": "Kate Peter"}');

In this query, you can notice that we haven’t specified the “subjects” field. Upon execution, the query returns the following output.

We can clearly observe that the “subjects” column has returned a NULL value. This is the significance of specifying NULL as the base value.

 **Question** \- Can we specify some other value other than the NULL as the base value? If yes, how will it behave? Let’s see

The answer to this question is **YES!** We can appoint any other value as the base value. In such a case, if any field is missing from the JSON object, the value declared in the base value is returned in its place. Let’s implement this concept using the following query:
    
    
    SELECT * FROM
      json_populate_record(
      (1, 'any_stud_name', Array['Physics', 'Organic Chemistry'])::registered_students,
       
      '{"stud_id":   1,
       "stud_name": "Kate Peter"}');

Here, we have specified some base value fields. These fields must be in the same order and the same data type as declared in the JSON object and the custom data type. We can also notice that the “subjects” field from the specified JSON object is missing. How will the query respond?

In such a case, the missing field from the JSON object takes its value from the base value defined. The same was the scenario in the case of NULL as well. The output of this query is given as:

It is very clear from the above output that the base value is declared so that it can be returned and utilized in case some field in the JSON object is missing as compared to the custom data type defined earlier. Consider a simple example of invalid casting below.

###  **Example 3: In-Valid Casting in json_populate_record() Function**

We need to properly cast the JSON object so that they can be cast into the expected column data type. For example, if we incorrectly declare a “stud_id” as a string, while we have declared it an integer before. The function will throw an error.
    
    
    SELECT * FROM
      json_populate_record(
      null::registered_students,
      '{"stud_id":   "one",
       "stud_name": "Kate Peter",
       "subjects": ["Physics", "Organic   Chemistry"]}');

The query returns:

This illustrates that the proper casting is important for the **json_populate_record()** function to work.

This is how the **json_populate_record()** function works in PostgreSQL.

##  **How to Convert a JSON Object to Multiple Rows?**

To add multiple rows, we can use the Postgres json_populate_recordset() function. We can not provide multiple JSON objects to this function, it results in _“ERROR:_ _cannot call populate_composite on an array”_.

##  **Conclusion**

The **json_populate_record()** function in Postgres converts the JSON object into a data row. This function basically populates the table record from the JSON object. The JSON object is provided to the **json_populate_record()** function along with the base value, it will convert the JSON objects into the table row in accordance with the base values. The above sections demonstrated the **json_populate_record()** function along with different use cases and examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_populate_record-function/)

---

# How jsonb_object_keys() Function Works in PostgreSQL

> The JSONB object is provided to the jsonb_object_keys() function as an argument and it returns a column containing all the keys present in that particular JSON…

The **JSONB** object stores a massive amount of textual data in the form of key-value pairs same as the JSON objects do. We can get all the keys from the given JSONB object using the **jsonb_object_keys()** function in Postgres. The **jsonb_object_keys()** function gives all the keys present in the provided JSONB object. The following articles explain the working of the **jsonb_object_keys()** function in Postgres with examples, so let’s start learning.

##  **How Does the jsonb_object_keys() Function Work in PostgreSQL?**

The **jsonb_object_keys()** function takes the top-level JSONB object as input and returns all the keys that are present on that JSONB object. The basic syntax for the **jsonb_object_keys()** function is given as
    
    
    jsonb_object_keys(jsonb_obj jsonb)

In the above syntax:

● The **jsonb_object_keys()** function takes in a **JSONB** object.

● The **jsonb_object_keys()** function returns the set of all the keys present in that particular JSONB object in the **TEXT** format.

The **jsonb_object_keys()** function offers the same functionality as the **json_object_keys()** function offers for **JSON** data type.

We will have some practical examples to understand the concept clearly.

###  **Example 1: Understanding the jsonb_object_keys() Function**

Consider the following query to see how the **jsonb_object_keys()** function works.
    
    
    SELECT jsonb_object_keys('{"store_name": "Bakery", 
      "street_no": 24,
      "menu_items": ["Cake", "Bread", "patties"]}');

So in this query, we have provided a **JSONB** object to the **jsonb_object_keys()** function having 3 key-value pairs. The **jsonb_object_keys()** function will return all the keys present in the provided JSONB object.

In the output, we can notice that all the keys are returned. The same outcome can be gained by using the * after the **SELECT** statement as well.
    
    
    SELECT * FROM jsonb_object_keys('{"store_name": "Bakery", 
      "street_no": 24,
      "menu_items": ["Cake", "Bread", "patties"]}');

The output of this query is:

  
This is basically how the **jsonb_object_keys()** function works.

###  **Example 2: Using the jsonb_object_keys() Function on Table Data**

The function requires a **JSONB** object to return its keys. We can implement the **jsonb_object_keys()** function on the table’s column containing the **JSONB** objects. Moreover, this can be implemented on the table having a JSON column by first type-casting it into the JSONB data type. Consider the “online_store” table having data about the products in the shopping cart. The table looks like the following.

  
Now we will implement the query to get all the keys from the “products_in_cart” column. We can notice that the objects given in the “products_in_cart” column are JSON objects, so we need to typecast them into JSONB objects to implement the **jsonb_object_keys()** function. The whole query can be written as
    
    
    SELECT jsonb_object_keys(products_in_cart::JSONB) 
    FROM online_store;

We have typecasted the “products_in_cart” column to the JSONB data type and then implemented the **jsonb_object_keys()** function on it. We will get the keys successfully like this.

  
Here we notice that the query has given all the keys present in the column on which the function was implemented. This is how we can get the JSONB keys from the Postgres table containing a JSON/JSONB object column.

##  **Alternative Method to jsonb_each() Function**

If we want to get the key column of the given **JSONB** object, we can also make use of the jsonb_each() or jsonb_each_text() functions. These functions return the key and values from the provided **JSONB** object. So let’s implement the **jsonb_each()** function to get the key column from the same JSONB object as above. The query can be tailored as
    
    
    SELECT key FROM jsonb_each('{"store_name": "Bakery", 
      "street_no": 24,
      "menu_items": ["Cake", "Bread", "patties"]}');

As the **jsonb_each()** function gives the columns for keys and values, in this query, we are just getting the keys by specifying the “key” after **SELECT**. The output looks like this:

  
You can observe that the key column is returned, containing all the keys in the provided **JSONB** object. This is how we can customize the **jsonb_each()** and **jsonb_each_text()** functions to get the keys from the **JSONB** object.

##  **Conclusion**

We can get the keys from the JSONB object, by making use of the **jsonb_object_keys()** function. The **JSONB** object is provided to the **jsonb_object_keys()** function as an argument and the **jsonb_object_keys()** function will give a column containing all the keys present in that particular **JSONB** object. The article explained the working of the **jsonb_object_keys()** function with examples and different use cases.

---
[View this page online](https://www.commandprompt.com/education/how-jsonb_object_keys-function-works-in-postgresql/)

---

# What is the Use of the jsonb_pretty Function in PostgreSQL?

> The jsonb_pretty() function returns the beautified version of the provided JSONB value. This function applies proper formatting to the given value.

A wide variety of JSON/JSONB functions are offered by PostgreSQL. These functions manipulate and modify the provided JSON/JSONB data and some are used to perform operations on them. In this post, the topic of discussion will be the **jsonb_pretty()** function. This function serves a unique purpose i.e. it properly adds the white spaces and indentation to the provided JSONB value so that it looks more readable. Let’s learn more about the **jsonb_pretty()** function and understand how is it used in PostgreSQL.

##  **What is the Use of the jsonb_pretty Function in PostgreSQL?**

The **jsonb_pretty()** function takes the JSONB value as a function parameter and returns a more readable, formatted, and understandable illustration of that JSONB object. The function adds necessary white spaces, new lines, and indentations to the provided data. The fundamental structure of the **jsonb_pretty()** function can be written as
    
    
    jsonb_pretty(jsonb_val JSONB)

● The **jsonb_pretty()** function takes the JSONB value, which is to be formatted.

● The **jsonb_pretty()** function returns a formatted version of that provided value in the **TEXT** type.

We’ll now assess how the **jsonb_pretty()** function adds the formatting to the JSONB values, using the examples.

###  **Example 1: Understanding the jsonb_pretty() Function**

Consider the following simple query to understand how the **jsonb_pretty()** function will format the provided JSONB value (i.e. the JSONB array in this example)
    
    
    SELECT jsonb_pretty('["Alex", "Peter", "Kate", "Oliver"]');

We have provided a JSONB array with some strings/names to the **jsonb_pretty()** function. The function will implement proper formatting on the provided JSONB value like this:

The **jsonb_pretty()** function has added proper indentations, spacings, and new lines to the provided JSONB array. Each new element/value is placed in a new line with proper indentation. The JSONB object has now become more **readable** and **understandable**.

Note that the **”+”** sign shows the insertion of a new line.

This was a simple case now we’ll see how the **jsonb_pretty()** function responds if we provide a nested array.

###  **Example 2: Understanding the jsonb_pretty() Function**

We’ll notice how the **jsonb_pretty()** function responds to the nested array using the following query:
    
    
    SELECT jsonb_pretty('["Alex",   "Peter", ["Kate", "Oliver"]]');

We have provided the nested array to the function. We’ll now observe the clear difference in the formatting in this case.

The nested array has now become more readable and understandable as the **jsonb_pretty()** function has added proper indentation to the nested array. The new lines and white spaces are also properly used.

We will take another example into account to get more clarity.

###  **Example 3: More About the jsonb_pretty() Function**

Below is another example in which we provided a JSONB object having key-value pairs. We will see how the **jsonb_pretty()** function works on it.
    
    
    SELECT jsonb_pretty('{"Alex":10, "Kate":9, "Peter":[8,7]}');

In the above query, we have provided the keys and values to the function. The following is the output for this query.

We can see that the objects are properly indented. Each new element/value is placed in a new line. In the third element, there are two values. So these 2 values are again placed in separate new lines with proper indentation.

The **jsonb_pretty()** function returns the **JSONB** values in a beautified format, which makes them more readable and easy to understand for the user.

##  **Conclusion**

The **jsonb_pretty()** function returns the beautified version of the provided JSONB value. This function applies proper formatting to the given value. The **jsonb_pretty()** function takes in the **JSONB** object, adds proper white spaces, new lines, and indentation to that value, and returns it in the **TEXT** type. This tutorial demonstrated how the **jsonb_pretty()** function works on different JSONB values in PostgreSQL using examples.

---
[View this page online](https://www.commandprompt.com/education/what-is-the-use-of-the-jsonb_pretty-function-in-postgresql/)

---

# Understanding Postgres jsonb_insert() Function With Examples

> The jsonb_insert() function inserts a new JSONB value into an already existing JSONB object at a specific location. It takes in 3 parameters essentially and 1 …

The JSONB objects store a huge amount of textual data in the binary form. Sometimes we need to insert more data values into the existing PostgreSQL **JSONB** objects. This is possible if we use the PostgreSQL **jsonb_insert()** function. This function assists the user in adding more values to the existing **JSONB** objects, by taking that particular JSONB object and the path or location at which we want to insert the new **JSONB** value and the new **JSONB** object, as inputs.

The following article will demonstrate the methods that can insert a new **JSONB** object into the existing **JSONB** object using the **jsonb_insert()** function.

##  **Understanding Postgres jsonb_insert() Function**

The **jsonb_insert()** function takes the JSONB object as input, along with the path at which we wish to insert the new JSONB value and the new JSONB value (that is to be inserted). The basic structure of the **jsonb_insert()** function can be written as:
    
    
    jsonb_insert(
    target_jsonb_object JSONB,
    location_of_insersion TEXT[],
    new_jsonb_val JSONB
    [, insert_after_val BOOLEAN]) ;

In the above syntax:

● The first parameter i.e. _“target_jsonb_object”_ is the given/target JSONB object, in which we want to insert the new **JSONB** value.

● The second parameter i.e. _“location_of_insersion”_ specifies the path or the location at which we want to insert the new **JSONB** value in the _“target_jsonb_object_ ”. This parameter is specified in the **TEXT** array format.

● The third parameter i.e. _“new_jsonb_val_ ” is the value that is to be inserted in the given _“target_jsonb_object_ ”.

● The fourth parameter is totally optional. The _“insert_after_val”_ is a boolean value that illustrates if the _“new_jsonb_val”_ is inserted after the specified _“location_of_insersion”_ or not. The value is **FALSE** by default. This means that if we do not specify the _“insert_after_val”_ parameter, the new **JSONB** value will be added before the specified location. Whereas, if the _“insert_after_val”_ parameter is **TRUE** , the new JSONB value is inserted after the specified location.

● The **jsonb_insert()** function returns a **JSONB** object. That **JSONB** object is basically the new values inserted into the target JSONB object.

###  **Basic Working**

So how does the **jsonb_insert()** function basically work? The **jsonb_insert()** function first looks for the provided new JSONB object(that is to be inserted) in the provided target JSONB object, if the new JSONB value(to be inserted), already exists in the target JSONB object, the new value declared is simply added to that target JSONB object. If it is absent, then a new key-value pair is created in that **JSONB** object.

Let’s move forward into the details of the **jsonb_insert()** function with the help of examples.

###  **Example 1: Understanding the jsonb_insert() Function**

To understand the working of the **jsonb_insert()** function, consider the following query:
    
    
    SELECT jsonb_insert('{"Roll numbers": [1,3,5,7,9]}', '{Roll numbers,0}', '100');

In the above query:

● The first parameter i.e. '{"Roll numbers": [1,3,5,7,9]}' is the target JSONB object in which the value is to be inserted.

● The second parameter here is '{Roll numbers,0}'. This specifies the location. The location is given as a **TEXT** array. This depicts that the new JSONB value is to be placed as “Roll numbers” at and before index “0”.

● The new JSONB value specified is 100.

● We have not specified the “insert_after val” parameter. This means that it will be FALSE by default and the new JSONB value will be inserted before the specified location.

So the function will first find the new **JSONB** value(to be inserted) in the given/target array. In this case, it is already present in the target JSONB object, so it will simply insert the specified value in the array at a specific location. The last boolean parameter is skipped so it will be FALSE by default. This means that the value will be inserted before the provided location i.e. “0” in this case.

The query results in the following output:

We can notice that the new JSON value that is “100” has been inserted into the given **JSONB** object before the index 0.

Let’s observe what will happen if we replace the location in the index with something else. The following query depicts the change.
    
    
    SELECT jsonb_insert('{"Roll numbers": [1,3,5,7,9]}', '{Roll numbers,3}', '100');

We have specified the index “3” now. The query results are the following:

So this is how the **jsonb_insert()** function basically works.

 **Example 2: Understanding the jsonb_insert() Function**

We will now see the case if the new **JSONB** value does not exist in the provided/target **JSONB** values. Consider the below given query:
    
    
    SELECT jsonb_insert('{"Roll numbers": [1,3,5,7,9]}', '{test_scores}', '100');

We have specified a new JSONB object i.e. “test_scores”. In this case, a new value will be created rather than added to the existing one. Following is the output:

We can see that the returned JSONB object contains the previously contained JSONB values and the newly inserted value. Let’s now add some impact of the last “insert_after_val” parameter.

###  **Example 3: Understanding the jsonb_insert() Function’s Last Parameter**

As stated, the last parameter i.e. “insert_after_val” has a boolean value and is totally optional. The default value of this parameter is **FALSE**. The FALSE means that the value will be placed before the specified location as in the above cases. Let’s specify FALSE.
    
    
    SELECT jsonb_insert('{"Roll numbers": [1,3,5,7,9]}', '{Roll numbers,0}', '100', FALSE);

So in this case, the query will add the value before the “0” index of the provided **JSONB** object array like this:

Now if we declare the “insert_after_val” as TRUE. This will insert the new **JSONB** value after the specified location.
    
    
    SELECT jsonb_insert('{"Roll numbers": [1,3,5,7,9]}', '{Roll numbers,0}', '100', TRUE);

Now the value “100” will be added after the index “0” in the provided **JSONB** object “Roll numbers” array i.e. the element at index “0” is 1. So 100 will be placed after it.

The outcome of the query is as we expected. This is the impact of the last boolean parameter.

###  **Example 4: Replacing Existing Key Error in** **the jsonb_insert() Function**

We can insert some value in the existing **JSONB** array using the **jsonb_insert()** function but we can not replace any value. For example in the above-considered example, if we do not specify the index of the element in the array it would depict the whole “Roll numbers” JSONB object, and when we specify its new value it means that we want to replace the value of the already existing “Roll numbers” JSONB object. The following query implements these statements.
    
    
    SELECT jsonb_insert('{"Roll numbers": [1,3,5,7,9]}', '{Roll numbers}', '100');

In this code, we have not specified the index position of the “Roll numbers” **JSONB** object array. So the function will observe that the “Roll numbers” key is already present and has a new declared value. This means that we are trying to replace the key which is not possible with the **jsonb_insert()** function and it throws an error like this:

The error states that we are trying to replace the key which is not possible by making use of this function. To do this use the [**jsonb_set()**](<https://www.commandprompt.com/education/postgresql-jsonb_set-function/>) [function](<https://www.commandprompt.com/education/postgresql-jsonb_set-function/>) instead.

##  **Conclusion**

The **jsonb_insert()** function inserts a new JSONB value into an already existing JSONB object at a specific location. The **jsonb_insert()** function takes in **3 parameters** essentially and **1 parameter** optionally. These 3 parameters include; the target JSONB array in which we want to insert a new value, the path/location of the **JSONB** array where the new value will inserted, and the new JSONB array that we wish to insert. The optional argument is a boolean value that shows if the new **JSONB** value is to be placed in the target **JSONB** object before or after the specified location. The **jsonb_insert()** function has been discussed in detail in this article using proper examples and use cases.

---
[View this page online](https://www.commandprompt.com/education/understanding-postgres-jsonb_insert-function-with-examples/)

---

# How to Use to_ascii() Function in PostgreSQL

> The to_ascii() function in PostgreSQL converts the provided string from any valid encoding to the ASCII encoding.

In PostgreSQL, we can convert a string from any particular encoding to the **ASCII** encoding. This can be performed by using a string function called **to_ascii()**. We just need to provide the string to the function to get its ASCII encoding. A very small range of encodings (from which the string belongs) is supported by the **to_ascii()** function. Any encodings other than supported ones cause an error when they are provided to the **to_ascii()** function.

The content of this article covers the basic workings of the **to_ascii()** function in Postgres.

 **How to Use to_ascii() Function in PostgreSQL**

The **to_ascii()** function converts the string from a specific encoding into ASCII encoding. The syntax for the **to_ascii()** function can be written as:
    
    
    to_ascii(str [, Enc_name])

● To convert the **string** into ASCII we have to pass that string into the to_ascii() function.

● We can also optionally specify the **name of the encoding** , such as “LATIN1”, “LATIN2”, “LATIN9”, and “WIN1250”.

There is another way to do so. The user can also pass the integer values of the particular encoding to do the same. The syntax looks like this:
    
    
    to_ascii(str [, Enc_Int])

We can optionally specify the integer value of the encoding instead of the encoding name.

The below table represents the encodings supported by the Postgres **to_ascii()** function and their integer representation.

Only these encodings are supported by the **to_ascii()** function, any other encoding specified in the **to_ascii()** function causes an error. By default, the encoding is taken as the encoding of the present/current database.

Let’s move towards some examples to better understand the **to_ascii()** function.

 **Example 1: Understanding to_ascii() Function**

Consider the following simple query to see how the **to_ascii()** function works.
    
    
    SELECT to_ascii('Command Prompt','LATIN2');

The above query says that the string “ **Command prompt** ” is from the **LATIN2** encoding and it needs to be converted to ASCII. The output of the query is:

The function returns the above output. The string has been encoded to ASCII.

 **Example 2: Understanding to_ascii() Function Using Integer Representation**

As stated earlier, we can also use the integer representation for the encodings. We’ll implement it in this example.
    
    
    SELECT to_ascii('Command Prompt',16);

This query works fine and returns the following output:

The integer **16** is the representation of **LATIN9** encoding. So, the function has encoded the string from the LATIN9 encoding to ASCII.

 **Example 3: Understanding to_ascii() Function With Specifying Encoding Type**

We can also encode the string without specifying the name or the integer representation of the encoding of the string. In this case, the default string is considered to be in its default encoding. By default, the encoding considered is the encoding of your current database which is by default UTF-8.

We can see the encoding of our database by executing the ”\l” command on psql. Let’s execute the command:
    
    
    \l

In my case, it is the default encoding i.e. **UTF-8.**

The function only supports a small range of encodings that are specified above in the table. Any string encoded in any other encoding results in an error. So, if we execute the following query, we will encounter an “encoding conversion” error:
    
    
    SELECT to_ascii('Command Prompt');

It will definitely throw an error because the default **UTF-8** encoding is used. So the output is:

We can see that the query has thrown an error. Because the **UTF-8** encoding is not supported by the **to_ascii()** function.

 **Example 4: Using to_ascii() Function On Table’s Data**

We can also perform the ASCII encoding on the table’s data. Consider the table named “passed_candidates”.

We’ll write the following query to implement the **to_ascii()** function on the “candidate_name” column of this table.
    
    
    SELECT candidate_id,to_ascii(candidate_name,'LATIN1')
    FROM passed_candidates;

The query will return all the entries of the “candidate_name” column encoded in ASCII like this:

This is how the **to_ascii()** function works.

 **Conclusion**

The **to_ascii()** function in Postgres converts the provided string from any valid encoding to the ASCII encoding. The encoding in which the string originally is can optionally be mentioned in the function by its name or the integer representation of it. Only a small range of encodings are supported by the **to_ascii()** function; any string with any other encoding than these encodings throws an error. In this guide, we have discussed what the **to_ascii()** function does with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-to_ascii-function-in-postgresql/)

---

# PostgreSQL trim_scale() Function

> The trim_scale() function takes in a value of a numeric data type and returns the number after trimming zeros from the decimal part of the given numeric value.

The floating point numbers retain their original decimal places so that it is expressed accurately and precisely. When working with these floating point numbers, we usually encounter cases where we have numerous trailing zeros after the decimal point. The number can be accurately expressed if we remove the trailing zeros. There is a function named **trim_scale()** that is used to trim all the trailing zeros after the decimal point and return the number.

In this article, we will learn to use the **trim_scale()** function in our queries with the help of different examples/use cases.

##  **PostgreSQL trim_scale() Function**

The Postgres **trim_scale()** function trims the trailing zeros after the decimal point. The syntax for the **trim_scale()** function looks like this:

trim_scale(num)

● The **trim_scale()** function takes in a numeric value.

● The returned type of the trim_scale() function is also a **numeric** data type.

The function returns the provided number after removing all the trailing zeros from it.

We’ll move towards some examples for more clarity.

###  **Example 1: Understanding the trim_scale() Function**

We will execute the following query to see how the **trim_scale()** function works with different numbers.
    
    
    SELECT
      trim_scale(24.7300) AS "trim_scale: 24.7300",
      trim_scale(89.0078) AS "trim_scale: 89.0078",
      trim_scale(-11.5060) AS "trim_scale: -11.5060",
      trim_scale(0.00400) AS "trim_scale: 0.00400",
      trim_scale(18470000) AS "trim_scale: 18470000";

The above query evaluates different cases of the trim_scale() function. Let’s first consider the output of the query.

In the above output illustration:

● In the case of the number “ **24.7300** ”, the trim_scale() function has trimmed all the trailing zeros, after the decimal point, from the number.

● For “ **89.0078** ”, the function retrieved the same number because there was no trailing zero in it.

● The trim_scale() function returned “-11.506” when the number “ **-11.5060** ” was provided. We can notice that the last zero has been removed.

● When the number “ **0.00400** ” is provided to the **trim_scale()** function, it returns “0.004”, as the two trailing zeros have been removed from the number.

● Lastly, if the number does not contain a decimal point, the number will remain the same no matter how many trailing zeros it contains, as illustrated in the case of “ **18470000** ”.

So this is the basic function of the **trim_scale()** function in PostgreSQL. We can also implement the **trim_scale()** function on the table data to clean values in the table. Let’s see this particular use case.

###  **Example 2: Using the trim_scale() Function on Table Data**

We’ll implement the **trim_scale()** function on the “circle” table. The table contains the data for the circumference of each circle. The table looks like this:

Now let’s implement the **trim_scale()** function on the circumference column of the above table. We can write the following query for this:
    
    
    SELECT *, trim_scale(circumference) AS "trimmed_circumference"
    FROM circle;

The above-written query returns the following output.

In the above output, we can see that the **trim_scale()** function returns the provided number after removing the extra trailing zeros after the decimal point.

This is how the **trim_scale()** function does.

##  **Conclusion**

The **trim_scale()** function trims the extra trailing zeros from a number and then returns the number. The **trim_scale()** function takes in a value of a numeric data type and returns the number after trimming zeros from the decimal part of the given numeric value. In this article, we have learned how to use the **trim_scale()** function along with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-trim_scale-function/)

---

# How to Use jsonb_build_array() function in PostgreSQL

> In PostgreSQL, the jsonb_build_array() function takes the list of heterogeneous parameters and builds the JSONB array from them.

In PostgreSQL, it is possible to create a JSONB array from a list of variable and heterogeneous parameters. This operation is performed by the **jsonb_build_array()** function. The **jsonb_build_array()** function is a JSON/JSONB function in Postgres, which converts a variable list of parameters into the **JSONB** array.

For the scope of this article, we’ll learn to use the jsonb_build_array() function in different use cases.

##  **How to Use jsonb_build_array() function in PostgreSQL?**

The **jsonb_build_array()** function constructs a JSON array from the provided list of heterogeneous parameters. The basic structure of **jsonb_build_array()** function is given as:
    
    
    jsonb_build_array(parameter_list   VARIADIC)

In the above syntax:

● A variable list of parameters needs to be provided to the **jsonb_build_array()** function.

● The **jsonb_build_array()** function will convert that provided list into the **JSONB** array.

The **jsonb_build_array()** function assesses all the elements in the parameter list and utilizes the[ to_jsonb()](<https://www.commandprompt.com/education/what-does-the-to_jsonb-function-do-in-postgresql/>) function to convert them to place into the array.

The **jsonb_build_array()** function is the same as the [json_build_array() function](<https://www.commandprompt.com/education/how-to-use-json_build_array-function-in-postgresql/>) that is used to build a JSON array.

Below are the examples of the **jsonb_build_array()** function that will make our concept more clear.

###  **Example 1: Understanding** **jsonb_build_array() Function in PostgreSQL**

We will pass the list of elements of different data types to see how the **jsonb_build_array()** function converts them into the JSONB array. Assess the following query.
    
    
    SELECT jsonb_build_array(125, 'string', true, 37.93, null, now());

The above code illustrates that we have provided a heterogeneous list of parameters to the **jsonb_build_array()** function. The query returns the following output:

We can notice that the **jsonb_build_array()** function has returned the array built from the parameter list provided. Moreover, the data type of the returned array is **JSONB**.

###  **Example 2: Using the** **jsonb_build_array() Function With Arrays**

In this section, we’ll see how this **jsonb_build_array()** function works when we pass an array into it. Let’s execute the **jsonb_build_array()** function with a 2-dimensional array using the following query:
    
    
    SELECT jsonb_build_array(ARRAY[[0,9,8],[7,6,5],[4,3,2]]);

We have provided a 2-dimensional array to the **jsonb_build_array()** function. The output of the query is.

The array is converted into the **JSONB** array.

###  **Example 3: Using the** **jsonb_build_array() Function With Composite Types**

For this example, we will use the **ROW** composite type, and see how this function responds to it.
    
    
    SELECT jsonb_build_array(
      125, 'string', true, null,ROW(125, 'string', true, null));

First, let’s see the output of this query and then we’ll see how it worked.

We have provided 5 parameters to the **jsonb_build_array()** function. Each parameter is processed by the **to_jsonb()** function to give the value and that value is then placed in the JSONB array. Like this:
    
    
    SELECT 
      to_jsonb(125),
      to_jsonb('string'),
      to_jsonb(true),
      to_jsonb(ROW(125, 'string', true, null));

The output of this query is:

All these values are returned to the **jsonb_build_array()** function, to place them in the **JSONB** array.

##  **Conclusion**

The **jsonb_build_array()** function takes the list of heterogeneous parameters and builds the JSONB array from them. The list elements are converted using the **to_jsonb()** function and then are placed in the JSONB array by the **jsonb_build_array()** function. This is how this function works.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-jsonb_build_array-function-in-postgresql/)

---

# PostgreSQL quote_ident() Function

> While writing the PostgreSQL queries, we sometimes need to use the string as identifiers. For this purpose, the string needs to be converted into the quantifie…

While writing the PostgreSQL queries, we sometimes need to use the string as identifiers. For this purpose, the string needs to be converted into the quantified identifier or properly quoted in the double quotation mark. In PostgreSQL, the **quote_ident()** function performs this task. The **quote_ident()** function gets a string as an argument and returns the same string properly double-quoted that can be used as a qualified identifier.

Let’s learn more about the **quote_ident()** function in detail in the below section.

##  **What Does PostgreSQL quote_ident() Function Do?**

The PostgreSQL **quote_ident()** function takes in a string and returns the same string with appropriately double-quoted. The syntax for the **quote_ident()** function is given as:
    
    
    quote_ident(str)

The function takes in the string and returns the **string** that is enclosed in double quotes. The **quote_ident()** function will return **NULL** if the specified string is NULL.

Let’s understand the concept with examples.

###  **Example 1: Understanding quote_ident() Function**

Consider the following query to understand the basic working of the quote_ident() function.
    
    
    SELECT 
      quote_ident('Command   Prompt') AS "Command Prompt",
      quote_ident('Command-Prompt') AS "Command-Prompt",
      quote_ident('CommandPrompt') AS "CommandPrompt";

In the above query, we have provided the strings to the **quote_ident()** function. As a result, it will return the strings in the double quotes like this:

The **quote_ident()** function has returned the same strings but with the double quotes.

The double quotes are placed where they are required. If the string provided to the **quote_ident()** function is already an identifier, it is not enquoted in double quotes. Let’s understand this via an example.

###  **Example 2: Using quote_ident() Function With Identifiers**

The **quote_ident()** function does not always add double quotes on the string, usually, it does. But when the string provided to the **quote_ident()** function is already a qualified identifier, it will not encode it in double quotation marks. This can be illustrated by the following query:
    
    
    SELECT 
      quote_ident('command_prompt') AS "command_prompt",
      quote_ident('command') AS "command",
      quote_ident('prompt') AS "prompt";

As we have provided qualified identifiers in the **quote_ident()** function, the function will not insert the double quotes on the string.

The above output verifies the fact that if we provide the qualified identifier to the function, it will not add the double quotes to it.

###  **Example 3: Using quote_ident() Function on String Already Having Double Quotes**

If there is a case that the string on which the **qoute_ident()** function is applied already has a double quote, the double quote will be applied to that double quote string. Here is a demonstration:
    
    
    SELECT 
      quote_ident('Command "Prompt"') AS "doubling double quotes";

The output of this query will be the following:

This is how the **qoute_ident()** function doubles the double quote if it is already present in the string.

###  **Example 4: Using quote_ident() Function On Table Data**

Now we will observe the working of the **qoute_ident()** function on the table data. For that, consider the table named “registration”. The table looks like this:

Now we will apply the **qoute_ident()** function on the “city” column of this table. The query for this can be written as:
    
    
    SELECT studentid, studentname, QUOTE_IDENT(city)
     FROM registration;

The query will encode all the entries of the “city” column in double quotes like this:

We can clearly see that the **qoute_ident()** function worked on the city table and returned the table with double-quoted entries of the column “city”.

This was all about the **qoute_ident()** function and its working.

##  **Conclusion**

The **qoute_ident()** function adds double quotes to the string to make it able to be used as a quantified identifier. The string is provided to the function as an argument and the **qoute_ident()** function returns the same string enquoted with double quotes. If the string provided to the function is already a quantified identifier, then no quotes will be added. In this Postgres blog, we have discussed the qoute_ident() function with various use cases.

---
[View this page online](https://www.commandprompt.com/education/postgresql-quote_ident-function/)

---

# PostgreSQL min_scale() Function

> The min_scale() function in Postgres returns the minimum precision or minimum number of decimal places that are necessary to accurately/completely express the …

PostgreSQL provides a mathematical function that gives us the minimum number of decimal places required in order to express/represent a specific number accurately and precisely. This function is named as the **min_scale()** function. The following section of this blog will explain the use and working of the min_scale() function through proper examples and use cases.

##  **How to Use min_scale() Function in PostgreSQL?**

The **min_scale()** function in PostgreSQL returns the minimum precision or the minimum number of decimal places the specified number possesses to represent itself accurately. The basic syntax of the **min_scale()** function is:
    
    
    min_scale(num)

● The number is provided to the function as an argument.

● This number should be of **Numeric data type**.

● The function will always return an **integer data type** value, representing the minimum number of decimal places used to accurately express the number.

If the number provided is an **integer** , the output will be **0**. If that number has a **fractional part,** the output will be the number of digits after the point without the trailing zeros.

The below examples will more clearly illustrate the working and usage of the **min_scale()** function.

 **Example 1: Understanding the min_scale() Function**

Consider the following query to see how the **min_scale()** function works.
    
    
    SELECT
      min_scale(0) AS "min precision:0",
      min_scale(5.0) AS "min precision:5.0",
      min_scale(20.48) AS "min precision:20.48",
      min_scale(-11.5006) AS "min precision:-11.5006",
      min_scale(17.799*2) AS "min precision";

The query will return the minimum precision/ minimum number of decimal places that are necessary to express the accurate number. The output for the above query is:

We can see that the integer values are returned for the respective values. The simple rule is that:

● The **min_scale()** function simply gives the minimum number of decimal places after the decimal points except the trailing zeros.

● If the number is a floating point number(lines 12-15), it will follow the same rule.

● If the given numeric value is an integer(0 in the above query), the **min_scale()** function will give 0 as there is no decimal place after the decimal point.

The outputs in the above image follow the same rule.

###  **Example 2: Using the min_scale() Function on Table’s Data**

Consider the following “circles” table.

We can find the minimum precision of the “circumference“ column by implementing the min_scale() function on it. The query for this is written as:
    
    
    SELECT *, min_scale(circumference) AS "min precision in   circumf"
     FROM circles;

This query will return the number of decimal places that are necessary to express the respective circumference completely and accurately like this:

To demonstrate the above table, consider the circumference on the first row. After counting, we will be able to observe that the **6.28318530717959** has **14** decimal places after the decimal point (and no trailing zero) so the **min_scale()** function has returned 14.

Let’s say, the number was 6.283185307179590000, the **min_scale()** function would still have returned 14 because no matter how many trailing zeros are there, they won’t count. This is how the **min_scale()** function works in PostgreSQL.

###  **Conclusion**

The **min_scale()** function in Postgres returns the minimum precision or minimum number of decimal places that are necessary to accurately/completely express the number. The **min_scale()** function gets the numeric value as input and gives an integer. We have assessed the basic workings of the **min_scale()** function along with their implementation in examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-min_scale-function/)

---

# PostgreSQL parse_ident() Function

> parse_ident() function splits the qualified identifier/argument into an array. It gets two parameters; the 1st is the argument that is to be split, and the 2nd…

PostgreSQL offers many string functions. Some of these functions offer the functionality to get some information related to the provided string while some of the functions are used to manipulate the string. The **parse_ident()** function is a string function that splits the qualified identifier into an array. In this article, we’ll learn about the **parse_ident()** function with the help of proper examples. Let’s learn together.

##  **How Does PostgreSQL parse_ident() Function Work?**

The **parse_ident()** function takes in an argument/qualified identifier and splits it into an array. The basic syntax of parse_ident() function can be written as:
    
    
    parse_ident (qualified_arg, StrictMode)

In the above syntax:

● The **parse_ident()** function basically takes in two arguments/parameters.

● The 1st parameter is the qualified argument that will be split into the array.

● The 2nd parameter is an optional parameter that is used to enable or disable the strict mode. The strict mode is **enabled by default** i.e. if we do not specify this parameter in the function.

● If the **strict mode is enabled** , it will cause an error in case there is a special character present in the qualified identifier.

● If the **strict mode is disabled** i.e. by specifying it as **FALSE** , it will just ignore the special characters.

The function will return an **array**. In case, the user provides an invalid argument to the function, this will cause an error. The return value will be **NULL** if we provide the NULL values as an identifier/argument.

We will understand the **parse_ident()** function with the help of examples to make it more clear.

###  **Example 1: Understanding the parse_ident() Function**

We will consider the following query to observe the working of the **parse_ident()** function.
    
    
    SELECT parse_ident('John.Smith.Lily');

In the above query, we have provided the “John.Smith.Lily” as a qualified identifier/argument. The function will simply return and split the argument in an array like this:

We can see that the argument has been split in an array.

Here in the above query, no information about the strict mode has been provided. This means that the strict mode is enabled because the default value for it is “enabled”. We will now see how the function responds to the special character when the strict mode is enabled.

###  **Example 2: Understanding the Strict Mode in parse_ident() Function**

Consider the following query to see the response of the function with the special characters. Let's add some special characters at the end of identifier arguments in the above-considered query.
    
    
    SELECT parse_ident('John.Smith.Lily%%%');

Here we have inserted the % special character at the end of the identifier with the enabled strict mode. Upon execution, the query will throw an error like this:

The error says that we have provided an invalid string. In the next example, we will try to implement the **parse_ident()** function on the same qualified identifier/argument containing the special character at the end but with the disabled strict mode.

###  **Example 3: Understanding the Disabled Strict Mode in parse_ident() Function**

To disable the strict mode, we will specify it as **FALSE**. The query will become:
    
    
    SELECT parse_ident('John.Smith.Lily%%%', FALSE);

The output of the query is:

We can observe that the output of the above query is totally different from the previous case. In that case, the query returned an error because the strict mode was enabled. But in the case of **disabled strict mode** , the function has ignored the special characters and executed the query without an error.

This is how the **parse_ident()** function splits the argument into an array.

##  **Conclusion**

The PostgreSQL **parse_ident()** function splits the qualified identifier/argument into an array. It gets two parameters; the 1st is the **argument** that is to be split, and the 2nd is the **strict mode** which is **optional**. But by default, it is enabled. Enabling the strict mode adds extra strictness towards the special characters in the argument. It will show an error if the strict mode is enabled and a special character is added to the identifier. While if it is disabled, the function will ignore the special character and return the result accordingly. This blog covered the concepts of the **parse_ident()** function with examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-parse_ident-function/)

---

# PostgreSQL json_each() Function

> The json_each() function converts the top-level JSON object into the expanded key-value pairs. It accepts a JSON object as an input and converts and returns th…

Postgres tables store data in the form of rows and columns, the same way the JSON data type can store data in the form of key-value pairs. The **JSON** data types store the JavaScript Object Notation data in PostgreSQL. The key-value pair is a pair of the identifier and its value or values. Postgres offers many functions that can be used to manipulate or interrogate some information about these JSON data types. In this article, we’ll investigate the basic workings of the **json_each()** function, so let’s get started!

##  **PostgreSQL json_each() Function**

We know that a JSON data type stores data in the form of key-value pairs. We can get the top-level JSON objects into a set of expanded key-value pairs. The **json_ each()** function can be utilized for this specific purpose. The structure of the **json_each()** function can be written as:
    
    
    json_each ( obj JSON ) → set_of RECORD( key TEXT, value JSON )

In the above syntax:

● The **Json_each()** function takes in the JSON object as an argument.

● The **Json_each()** function returns the set of expanded key-value pairs for the specified JSON object.

● The data type of the “key” is **TEXT** and for “value” it is **JSON** data type.

● The two separate columns for “key” and “value” are returned as an output containing all the expanded key-value pairs in the respective top-level JSON object.

Let’s write some queries for the **json_each()** function to understand the concept in a better way.

###  **Example 1: Understanding the json_each() Function**

Let’s assume the following query to understand the concept. The following query contains the data of the record of a student.
    
    
    SELECT json_each(
      '{"st_name": "Smith", 
      "id": 56,
      "Courses": ["English", "Physics", "Chemistry"]}');

We have provided the top-level JSON object to the **json_each()** function. The function will now return the data in key-value pairs like this:

We can observe that the query has given the expanded JSON key-value pairs in return.

We can also get the two different columns for the key and the value.

###  **Example 2: Using the json_each() Function to Get Different Columns For Key And Value**

In this section, let’s write the query to get the two separate columns for the key and values of the above-considered example. The query can be written as:
    
    
    SELECT * FROM json_each(
      '{"st_name": "Smith", 
      "id": 56,
      "Courses": ["English", "Physics", "Chemistry"]}');

The output of this query is illustrated below:

The above image illustrates that we were successful in getting two separate columns for the key and values. We can also observe that the data type of the key is **TEXT** and the value is **JSON**.

If we want to get the data type of both the columns as **TEXT** , we need to use the json_each_text() function instead.

###  **Example 3: Using the json_each() Function On Table Data**

We can use the **json_each()** function with the table data as well. We can implement it on the table having a JSON column that contains the **JSON** objects. To see how to create a table containing a column of JSON data type you can follow the link: [Working With PostgreSQL JSON Data](<https://www.commandprompt.com/education/working-with-postgresql-json-data/>).

Here I am considering the table “online_store” which looks like this:

The column “products_in_cart” is of JSON data type and contains the JSON objects. Let’s implement the **json_each()** function to get the keys and values in the table.
    
    
    SELECT json_each(products_in_cart) 
     FROM online_store;

Using the above query, we will be able to get the JSON objects from the “product_in_cart” column.

In this way, we can get the key and values from any table using the **json_each()** function. You can also notice that the **RECORD** is the data type of the column that is given by the query.

To get the keys and values separately, we’ll write the following query:
    
    
    SELECT * FROM online_store, json_each(products_in_cart);

The query will return the keys and values in two different columns like this:

We can also note that the return type of the “key” column is **TEXT** and the “value” column is **JSON**. so this is how we work with the **json_each()** function on any Table.

##  **Conclusion**

The **json_each()** function converts the top-level JSON object into the expanded key-value pairs. The JSON object is provided to the **json_each()** function as an input as it will convert and return the expanded key-value pairs. We understood the basic concept and working of the **json_each()** function with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_each-function/)

---

# PostgreSQL json_object_keys() Function

> The JSON object is provided to the json_object_keys() function as an argument and it returns a column containing all the keys present in that particular JSON o…

A **JSON** object is comprised of key-value pairs that can be stored in Postgres. We can get the keys and values from the JSON objects using different Postgres JSON functions. A function called the **json_object_keys()** function is used to fetch the keys from the provided JSON objects. This tutorial will be about the **json_object_keys()** function and how we can get all the keys using this function.

##  **PostgreSQL json_object_keys() Function**

The **json_object_keys()** function takes the JSON object and returns the keys present in it. The basic structure of the **json_object_keys()** function looks like this:
    
    
    json_object_keys(obj JSON)

In the above syntax:

● The **json_object_keys()** function takes in a JSON object of **JSON** data type.

● The **json_object_keys()** function returns the set of all the keys present in that particular JSON object in the **TEXT** format.

Let’s implement the function query to see how it works.

###  **Example 1: Understanding the json_object_keys() Function**

We will now execute the **json_object_keys()** function on the _ '{"st_name": "Peter", "S_id": 84, "Subjects": ["German", "Calculus"]}'_ JSON object. The query can be written as
    
    
    SELECT json_object_keys('{"st_name": "Peter", 
      "S_id": 84,
      "Subjects": ["German", "Calculus"]}');

On execution of this query, we will see that the **json_object_keys()** function will return the column of all the keys present in the provided JSON object. The output of this query looks like this:

The above output shows that the query has returned all the keys present in the given JSON object.

The following query also returns the exact same output/result.
    
    
    SELECT * FROM json_object_keys('{"st_name": "Peter", 
      "S_id": 84,
      "Subjects": ["German", "Calculus"]}');

The * says that the query will return all the columns that are the outcome of the function but the function only returns the column for the keys. So it returns that column.

We can also get the keys from the JSON object present in a table.

###  **Example 2: Using the json_object_keys() Function On Table Column**

If a table has a column containing the JSON object, we can get the keys present in it. Consider the table “online_store” containing the JSON column “products_in cart”. The table looks like this:

To get the keys from this column, we can write the following query.
    
    
    SELECT json_object_keys(products_in_cart) 
     FROM online_store;

The above query will return the column containing keys present in the JSON “products_in_cart” column.

The output gave us the keys present in the **JSON** column. This is how we can get the JSON keys from the Postgres table containing a JSON object column.

##  **Additional Information/Alternative Method to json_object_keys() Function**

If we want to get the key column of the given **JSON** object, we can also make use of the json_each() or json_each_text() functions. These functions return the key and values from the provided **JSON** object separately. So to get only the key column from the JSON object using the json_each() function, specify the key column in the SELECT query as follows:
    
    
    SELECT key FROM json_each('{"st_name": "Peter", 
      "S_id": 84,
      "Subjects": ["German", "Calculus"]}');

The output looks like this:

You can observe that the key column is returned, containing all the keys in the provided **JSON** object. This is how we can customize the **json_each()** and **json_each_text()** functions to get the keys from the JSON object.

##  **Conclusion**

To get all the keys from any JSON object, we use the **json_object_keys()** function. The JSON object is provided to the **json_object_keys()** function as an argument and the **json_object_keys()** function will give a column containing all the keys present in that particular JSON object. This article demonstrates the working of the **json_object_keys()** function with examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_object_keys-function/)

---

# PostgreSQL quote_literal() Function

> The PostgreSQL quote_literal() function takes in a string and returns the same string enclosed with the single quotations.

The **quote_literal()** function is a string function used in PostgreSQL. This function works somewhat similar to the **quote_ident()** function. The quote_literal() function takes in a string and returns the same string enclosed in single quotes. In this post, we’ll see what the **quote_literal()** function does and how is it used in Postgres.

##  **What Does the PostgreSQL quote_literal() Function Do?**

The PostgreSQL **quote_literal()** function gets a string as a parameter/argument and returns that string enclosed in single quotes. The syntax for the **quote_literal()** function can be written as follows:
    
    
    quote_literal(str);

● The **quote_literal()** function takes the string and returns the string enclosed in single quotes.

● A **NULL** is returned if the argument given to the **quote_literal()** function is NULL. However, quote_nullable() is a better option in this case.

We will now understand the functioning and use cases of the **quote_literal()** function with the help of examples.

###  **Example1: Understanding quote_literal() Function**

We will execute the following query having the **quote_literal()** function to see how this function works.
    
    
    SELECT  
      quote_literal('Command Prompt'),
      quote_literal(null);

By executing this query we will get the same string enclosed in single quotes like this:

Note that the **quote_literal()** function has returned **NULL** when we pass NULL as an argument.

This is how the **quote_literal()** function works.

###  **Example 2: Using quote_literal() Function with Embedded Single Quotes**

Let’s see how the query functions if there are embedded single quotes in the string. Consider the following query:
    
    
    SELECT quote_literal(E'let\'s learn PostgreSQL') ;

The **quote_literal()** will behave in the same manner as it usually does. The output for this query is:

The whole string is enclosed in single quotes.

 **Example 3: Using quote_literal() Function With Non-String Data types**

The **quote_literal()** function can also take non-string data type as argument. For example, we can pass a boolean to see does it works with other data types or not. Consider the following query for that:
    
    
    SELECT quote_literal(false) ;

By executing this query, we will get the following output:

This means that the **quote_literal()** function works fine with other non-string data types. Let’s observe another query, to see if it works in a similar way, with the integer, or not.
    
    
    SELECT quote_literal(87394);

This query returns the following output.

We can see that the **quote_literal()** function also works fine with the non-string data types, unlike the **quote_ident()** function.

Let’s implement the **quote_literal()** function on the table data.

###  **Example 3: Using quote_literal() Function on Table’s Data**

Let’s apply the **quote_literal()** function on the table column “studentname” from the “registration” table.

The table looks like this:

We will write the following query to execute the **quote_literal()** function on the “studentname” column :
    
    
    SELECT studentid, QUOTE_LITERAL(studentname), city
     FROM registration;

The above query will enclose every entry of the “studentname” with single quotes like this:

This is how we can use the **quote_literal()** function in PostgreSQL.

##  **Conclusion**

The PostgreSQL **quote_literal()** function takes in a string and returns the same string enclosed with the single quotations. This function can also take other non-string arguments and still work fine. This post taught us the workings of the **quote_literal()** function and its use cases in detail.

---
[View this page online](https://www.commandprompt.com/education/postgresql-quote_literal-function/)

---

# PostgreSQL json_strip_nulls() Function

> In PostgreSQL, the json_strip_nulls() function removes/eliminates the fields in the JSON object that have NULL values.

The JSON objects store data in key and value pairs. There is a great possibility that the data being recorded can have **NULL** values. The **NULL** values give incomplete information and are usually of no use to us. So we need to get rid of such data. The **json_strip_nulls()** function can be used to perform this operation. The **json_strip_nulls()** function removes the fields having NULL values from the provided JSON object.

##  **How to Use the json_strip_nulls() Function in PostgreSQL?**

The **json_strip_nulls()** Function stripes/removes the fields/keys that contain the NULL values. Any other parameter(other than JSON object) passed, remains unaffected by the function even if it contains NULL values. The basic structure of the PostgreSQL **json_strip_nulls()** Function is given as
    
    
    json_strip_nulls(json_val JSON)

The syntax says that:

● We need to pass JSON value in the **json_strip_nulls()** function.

● The function will return the **JSON** values, with the fields containing NULL values, removed.

● If the parameter is specified as **NULL** , the function will return **NULL**.

Below are the examples that illustrate how the **json_strip_nulls()** function works in PostgreSQL.

###  **Example 1: Understanding the json_strip_nulls() Function**

The following JSON object contains the radius for the circles. We will implement the **json_strip_nulls()** function to remove the **NULL** value from the JSON object. The query can be written as
    
    
    SELECT json_strip_nulls('{"circle1_rad":   34,
      "circle2_rad": null,
      "circle3_rad": 22,
      "circle4_rad": 97}');

The query will give the following output:

We can observe that the “circle2_rad” had the **NULL** value, so after executing the query, it has been removed by the **json_strip_nulls()** function. This was the simple working of the **json_strip_nulls()** function.

###  **Example 2: Understanding the json_strip_nulls() Function**

Consider the below-given query to see how the function responds to it:
    
    
    SELECT json_strip_nulls(
      '[45, null, 33, 
      {"circle1_rad": 34, "circle2_rad": null, "circle3_rad": 22}]');

In this query, we have provided an array to the **json_strip_nulls()** function. The array contains a JSON object as well i.e. _{ "circle1_rad": 34, "circle2_rad": null, "circle3_rad": 22}_, containing the keys and values. Let’s see how the **json_strip_nulls()** function worked on it.

If we carefully observe the output, we will be able to discover that the JSON object field containing the NULL value(i.e. circle2_rad) has been removed while the **NULL** value in the array remains unaffected. This means that the **json_strip_nulls()** function only works for the JSON objects. This is how the **json_strip_nulls()** function basically works.

The **json_strip_nulls()** function can be used on the table data. We will learn to execute it on table data in the following example.

###  **Example 3: Using the json_strip_nulls() Function With Table’s Data**

Consider the database table for an online store that stores the customers and their shopping cart information. The table is named “online_store” which looks like this:

Now, we’ll apply the **json_strip_nulls()** function on the “online_store” table to remove all the JSON fields having the value NULL. The query can be written as
    
    
    SELECT json_strip_nulls(products_in_cart) 
     FROM online_store;

The query will remove all the JSON fields having a NULL value from the “products_in_cart” column of the “online_store” table. The output of the query is:

You can notice that the “qty” field of the second row had a NULL value so it is removed from the particular JSON object. The “item” and ”qty” fields of the last row, both had NULL value, so they both are striped from the respective JSON object.

This is how the **json_strip_nulls()** function strips all the NULLs from the given JSON objects.

##  **Conclusion**

The PostgreSQL **json_strip_nulls()** function removes the fields in the JSON object that have NULL values. The JSON object is to be provided to the **json_strip_nulls()** function and it returns the fields with non-null values. Any other data can be provided to this function as well such as an array, etc., other than the JSON object, but the **json_strip_nulls()** function will not function on it. It will return the same object unaffected. In this detailed guide, we have learned about the **json_strip_nulls()** function with the help of suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_strip_nulls-function/)

---

# How to Use jsonb_build_object() Function in PostgreSQL

> In PostgreSQL, the jsonb_build_object() function takes a heterogeneous list of parameters and converts them into JSON objects.

In PostgreSQL, JSON data type plays a significant role in storing the data in key and value pairs. The JSONB is the extended data type that came from the JSON, which assists JSON in analyzing and storing the huge amount of JSON data in binary. There are many functions that are used to manipulate and interpret the JSON/JSONB data in Postgres.

For the scope of this article, we’ll cover one of the JSON/JSONB functions offered by Postgres that is, the **jsonb_build_object()** function. Let’s learn about this function together.

##  **How to Use jsonb_build_object() Function in PostgreSQL?**

The **jsonb_build_object()** function converts a heterogeneous list of parameters into the JSON object. The fundamental structure of the **jsonb_build_object()** function looks like the same as given below:
    
    
    jsonb_build_object(parameter_list   VARIADIC)

The syntax of **jsonb_build_object()** function says that:

● The function takes a list of heterogeneous parameters.

● The **jsonb_build_object()** function will give a **JSONB** object in return.

● The keys and values in the JSON object will be the alternative parameters provided in the function.

The **jsonb_build_object()** function assesses each provided parameter, the key arguments are forced to become TEXT. Whereas, on the values arguments, the [to_jsonb()](<https://www.commandprompt.com/education/what-does-the-to_jsonb-function-do-in-postgresql/>) function is applied and the result is returned on the key-value pairs as a **JSONB** object.

 **Additional Note** : The **to_jsonb()** just takes an SQL value and converts it into the JSONB format. For a detailed demonstration of the **to_jsonb()** function, we can head over to the dedicated article for the [to_jsonb() function](<https://www.commandprompt.com/education/what-does-the-to_jsonb-function-do-in-postgresql/>).

###  **Important Points**

Beyond the syntax of the **jsonb_build_object()** function, there are some important points for the implementation of this function, that is:

● The parameters passed in the **jsonb_build_object()** function should be even in number.

● The function forms alternative key-value pairs i.e. the first parameter will be the key and its very next element will be the value for it. The next element will again be a key and following it, its value will be given, and so on.

The **jsonb_build_object()** function is almost the same as the [**json_build_object()**](<https://commandprompt.com/education/how-does-the-json_build_object-function-work-in-postgresql/>)[ function](<https://commandprompt.com/education/how-does-the-json_build_object-function-work-in-postgresql/>) in PostgreSQL, which performs the same function for the JSON data.

Let’s take the help of some examples, to better understand the working of the **jsonb_build_object()** function.

###  **Example 1: Basic Working of the jsonb_build_object() Function**

As stated before, the keys and values are alternatives to each other in the provided parameter list. The key values are simply converted to **TEXT** with no other change while the “value” in the returned JSONB object(by the **jsonb_build_object()** function) comes after implementing the **to_jsonb()** function on it. We will assess a simple example to understand it better.
    
    
    SELECT jsonb_build_object( 37, now());

By executing this query, we will get:

We can note that the first value i.e. key is simply converted into **TEXT** format and the second parameter i.e. value comes after implementing the **to_jsonb()** function on it. We can also verify it by running the query for the **to_jsonb()** function on the ”value” parameter’s value i.e.
    
    
    SELECT to_jsonb(now());

Hence, the working of the **jsonb_build_object()** function is verified by the above illustration. We can have more examples for the **jsonb_build_object()** function.

###  **Example 2: Understanding the jsonb_build_object() Function**

We will provide different parameters for how the **jsonb_build_object()** function works on it. We will examine the following query:
    
    
    SELECT jsonb_build_object(185, 'ValString', false, now());

In the above query:

● As we have stated earlier, the keys and values are alternative parameters in the provided list. So, the ‘185’ will be key, and the “ValString” will be assessed as its value. Similarly, the “false” will be the key, and now() will be assessed as its value.

● The keys will simply be converted into the **TEXT**.

● The Values will be returned to the **JSON** object after applying the **to_jsonb()** function on it.

Let’s execute the above query to see what the output of the query is.

We can notice that the key parameters are simply converted into the TEXT. While the value parameters are obtained by the **to_jsonb()** function implemented on them. They are then returned as the JSONB objects by the **jsonb_build_object()** function. We will execute the query for the **to_jsonb()** function to see how it responds to these values.
    
    
    SELECT to_jsonb('ValString'::text),to_jsonb(now());

Upon executing this query we got:

If we carefully observe, we will be able to infer that the “values”, in the JSONB object, got their values after the **to_jsonb()** function is implemented on them.

###  **Example 3: Arguments List Must be Even**

The parameters provided to the **jsonb_build_object()** function need to be even in number to make the key and value pairs. If we provide an odd number of parameters, the **jsonb_build_object()** function will throw an error like this:
    
    
    SELECT jsonb_build_object(185, 'ValString', false, now(),null);

We have provided 5 parameters in the above **jsonb_build_object()** function. The query will throw an error.

So, for the execution of the **jsonb_build_object()** function, it is necessary to provide an even number of parameters.

###  **Example 4: Understanding the jsonb_build_object() Function With Arrays**

We can also declare arrays in the **jsonb_build_object()** function. Let’s implement the function by providing a 2-dimensional array to it.
    
    
    SELECT jsonb_build_object(100, ARRAY[[0,5],[4,7]]);

The execution of the above query gives:

Again the same concept is followed. The key parameters are returned as TEXT while the array returns the value after implementing the to_jsonb() function on it.

The arrays in the **jsonb_build_object()** function usually work fine. However, the array can be declared as the value parameter, not for the key. The key parameter does not have to be some array, JSON object, or any composite type. If we do so, an error will be thrown by the Postgres.
    
    
    SELECT jsonb_build_object(ARRAY[[2,7],[4,9]], ARRAY[[0,5],[4,7]]);

In this query, we have specified an array as a key parameter now let’s observe what will it return.

The error is thrown in this case saying that the key parameter can not be an array.

###  **Conclusion**

The **jsonb_build_object()** function takes a heterogeneous list of parameters and converts them into JSON objects. The key and value parameters are alternatively present in the list. The JSON object is formed and returned in such a way that the key parameters are simply placed in the JSON object as **TEXT** but the value is returned after the **to_jsonb()** function is applied to them. In this blog, we have observed different use cases/examples for the **jsonb_build_object()** function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-jsonb_build_object-function-in-postgresql/)

---

# PostgreSQL quote_nullable() Function

> The quote_nullable() function in PostgreSQL is used to enclose the string within single quotations. The string is provided to the function as an argument and i…

PostgreSQL offers many string functions including the parse_ident(), quote_ident, quote_literal(), etc. There is another convenient function called the **quote_nullable()** that is commonly used to handle **NULL** situations. The **quote_nullable()** function works the same as the **quote_literal()** function. The difference lies just in the case when **NULL** is provided as a string.

Let’s understand the concept of the **quote_nullable()** function with examples.

##  **What Does the quote_nullable() Function Do in PostgreSQL?**

The **quote_nullable()** function takes a string as an argument/parameter and returns the same string enclosed in the single quotations. The basic syntax of the **quote_nullable()** function is as follows:
    
    
    quote_nullable(str)

● The return data type of the **quote_nullable()** function is a **string**.

● If the **NULL** input is provided to the **quote_nullable()** function, it will return the string NULL. This is the difference between the **quote_nullable()** function and the **quote_literal()** function(we will see this later with the help of an example).

Below are some of the examples and use cases of the **quote_nullable()** function which will help us understand the concept of this function.

###  **Example 1: Understanding the quote_nullable() Function**

Consider the following query to understand how the **quote_nullable()** function works.
    
    
    SELECT  
      quote_nullable('Command Prompt'),
      quote_nullable(null);

● The first statement will return the same string enclosed in single quotes.

● The second statement where **NULL** is passed will return the string NULL.

The output of this query will be the following:

This is the basic functioning of the **quote_nullable()** function. We’ll move towards some advanced examples now.

###  **Example 2: Using quote_nullable() Function With Embedded Single Quotes**

The function can encounter the case where the string can have embedded quotes. The function behaves in the same way as it normally does. Consider the below given query:
    
    
    SELECT quote_nullable(E'let\'s learn PostgreSQL') ;

The above query will return the embedded string enclosed in the single quotations like this:

###  **Example 3: Using quote_nullable() Function With Non-String Data Types**

The **quote_nullable()** function also works with **non-string data types**. It works normally with the non-string data types. Let’s input an integer in the **quote_nullable()** function using the following query:
    
    
    SELECT quote_nullable(4735) ;

The query will return the integer enclosed in the single quotation like this:

Similarly, other data types such as boolean, etc. work fine with the **quote_nullable()** function as well.

###  **Example 4: Using quote_nullable() Function With Table’s Data**

We will now implement the **quote_nullable()** function on the table’s data. Consider the “test_scores” table. The table looks like this:

Let’s implement the **quote_nullable()** function on the “candidate_gender” column of the above table. The query for this can be written as:
    
    
    SELECT candidate_name, QUOTE_NULLABLE(candidate_gender)
    FROM test_scores;

The query will return the Postgres table containing all the entries of the column “candidate_gender” enclosed in single quotes. The output of the query is:

This is how the **quote_nullable()** function works.

Till now we have seen the working of the **quote_nullable()** function which seemed to be the same as that of the **quote_literal()** function. So what’s the difference between the two functions? Let’s learn about it in the next section.

##  **PostgreSQL quote_nullable() Function VS quote_literal() Function**

The basic working of the **quote_nullable()** function and the **quote_literal()** function are the same. The difference between both functions comes when we have to encounter the case of NULL as an input. By using the following query we will demonstrate the difference between both the **quote_nullable()** function and the **quote_literal()** function.
    
    
    SELECT  
      quote_literal(Null),
      quote_nullable(Null);

The query returns the following output:

In the above output, we can see that when the NULL is provided to the **quote_literal()** function, it returns the **NULL**. But when NULL is provided to the **quote_nullable()** function it gives us the **string NULL**. this is the whole difference between both functions.

 **Verification**

The fact stated above can be verified by using the [**IS NULL**](<https://www.commandprompt.com/education/postgresql-is-null-operatorcondition/>)[ statement](<https://www.commandprompt.com/education/postgresql-is-null-operatorcondition/>). The “ **IS NULL** ” keyword is used to find if a column contains a NULL or not. The IS NULL returns TRUE if the column entry is NULL and it returns FALSE if the column entry is not NULL. This function of the **IS NULL** statement can be used to verify the return value of the **quote_literal()** and the **quote_nullable()** functions.
    
    
    SELECT 
      quote_literal(Null) IS NULL AS quote_literal,
      quote_nullable(Null) IS NULL AS quote_nullable;

This query returns the following output:

The **quote_literal()** function returns NULL so the **IS NULL** statement has given **TRUE** while in the case of the **quote_nullable()** function, the string NULL is returned which means that the output is not NULL so the **IS NUL** L statement has returned **FALSE**. Which verifies the working of both functions.

##  **Conclusion**

The **quote_nullable()** function in PostgreSQL is used to enclose the string within single quotations. The string is provided to the function as an argument and it returns the single quote enclosed string. The **quote_nullable()** function basically works the same as the **quote_literal()** function but the difference comes when we encounter the NULL case. This article demonstrated the working of the **quote_nullable()** function its use cases and the difference between the Postgres **quote_nullable()** function and the **quote_literal()** function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-quote_nullable-function/)

---

# PostgreSQL to_hex() Function

> Postgres offers the to_hex() function to convert a number/numeric value into its hexadecimal representation. It takes an integer as an argument and returns a s…

The **to_hex()** function in PostgreSQL converts a specified number into the hexadecimal representation of that number. The hexadecimal is a number system having a base value of **16**. There are a lot of scenarios where the hexadecimal numbers are used. So we need to see how we can convert a number into its hexadecimal representation in PostgreSQL.

In this article, we’ll learn to convert the numbers into hexadecimal numbers.

##  **PostgreSQL to_hex() Function**

The to_hex() function takes in the number and returns its hexadecimal representation. The syntax for the **to_hex()** function can be written as:
    
    
    to_hex(num);

We need to provide an integer to the **to_hex()** function to get the **string** that will basically be the hexadecimal representation of that number.

The working of the **to_hex()** function can be presented by using the following examples.

###  **Example 1: Understanding the to_hex() Function**

We will execute the following query to better understand how the **to_hex()** function works.
    
    
    SELECT
      to_hex(0) AS "hex:0",
      to_hex(9) AS "hex:9",
      to_hex(1178) AS "hex:1178",
      to_hex(-129) AS "hex:-129",
      to_hex(15) AS "hex:15";

The query will return the hexadecimal representation of all of the integers provided to the **to_hex()** function. The output looks like this:

  
We can clearly see that the output is in the hexadecimal representation of each integer. We can also note that the returned data type of the **to_hex()** function is **TEXT**.

We can also implement the **to_hex()** function on the table data.

###  **Example 2: Using the to_hex() Function On Table’s Data**

We can get the hexadecimal representation of all the entries of a column by using the **to_hex()** function. Let’s consider the following table named “num”.

  
Now to get the hexadecimal representation of all these numbers in the column named “x”, we will have to write the following query.
    
    
    SELECT x, to_hex(x) AS "hexadecimal representation"
     FROM num;

The query returns the same output as expected i.e.

  
So this is how the **to_hex()** function works.

##  **Conclusion**

Postgres offers the **to_hex()** function to convert a number/numeric value into its hexadecimal representation. The parameter of the **integer** data type is given to the **to_hex()** function and in return it gives us the value in the **string** data type. This blog demonstrated the use of the **to_hex()** function with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-to_hex-function/)

---

# PostgreSQL json_object() Function

> The PostgreSQL json_object() function builds a JSON object from the provided TEXT array or arrays. It takes a text array or two text arrays.

PostgreSQL offers many JSON functions like **json_each()** , **json_each_text()** , **json_object()** , **json_populate_record()** , etc. These functions are used to manipulate the data of JSON data type in some way. The primary/major focus of this particular post will be on the **json_object()** function. We will see how the **json_object()** function can be utilized in the Postgres queries.

##  **How to Use json_object() Function in PostgreSQL?**

The **json_object()** function is used to construct a JSON object using a text array or two arrays. The array/ arrays are provided to the **json_object()** function as arguments. Now there are two cases in terms of the arguments provided to the **json_object()** function. Let’s discuss them.

###  **Case 1: Providing A Text Array to the json_object() Function**

In the case of a single array provided to the **json_object()** function. The syntax of the **json_object()** function can be illustrated as:
    
    
    json_object(key_val_array TEXT[])

In the above syntax:

● A single key-value array is provided to the **json_object()** function.

● The key_value array must have a data type of **TEXT**.

● The **json_object()** function converts this key-value text array into a **JSON** object. This means that the returned data type of this function is **JSON**.

In this case, the keys and values of the JSON object will be from the **TEXT** array provided to the **json_object()** function.

We can provide:

● One-dimensional **TEXT** array to the **json_object()** function. The count of elements in the provided array, in this case, must be even. The keys and values are declared as alternative entries to each other.

● Two-dimensional **TEXT** array to the **json_object()** function. Each inner array will be present in the key-value pairs.

Let’s go over the examples of these cases one by one.

###  **Example 1: Using json_object() Function With Single One-Dimensional Text Array**

To cover an example for this case, we will provide the **json_object()** function with a one-dimensional array. Consider the following query for this:
    
    
    SELECT json_object('{Stud_name, Peter, stud_id, 82, grad_batch, 2023}');

We have provided a single one-dimensional array to the **json_object()** function i.e. **{Stud_name, Peter, stud_id, 82, grad_batch, 2023}**. The function **json_object()** will return a JSON object in a way that the keys and values are alternative elements. This means that the “stud_name” will be the key and its value will be “Peter”. Similarly “stud_id” will be the key and “82” will be its paired value and so on. We can see the output for this:

We can observe that the **json_object()** function has given the **JSON** object for the provided text array. The keys and values are alternative elements of the provided array.

This is how the **json_object()** function works.

If the data type of the provided array is not TEXT, the function will throw an error. So in this case we can typecast the array into a TEXT. For example, if we provide {'Stud_name', 'Peter', 'stud_id', 82, 'grad_batch', 2023} array to the json_object() function, we can see that this array is not a TEXT array(as it is not quoted by quotes), the function won’t execute. So we will have to typecast it into a **TEXT** array. The following query is written to do so.
    
    
    SELECT json_object(
      ARRAY['Stud_name', 'Peter', 'stud_id', 82, 'grad_batch', 2023]::TEXT[]);

Now this query will work fine.

This proves that the **json_object()** function will only work when the array provided to it is a **TEXT** array.

Now, let’s see the impact of the two-dimensional single array on the function result.

###  **Example 2: Using json_object() Function with Single Two-Dimensional Text Array**

The function can also take a two-dimensional **TEXT** array as input. In this particular case, the inner array of the two-dimensional array will be acting as key-value pairs. We will consider the following query as an example to demonstrate this:
    
    
    SELECT json_object('{{radius_1, 26}, {radius_2, 14}, {radius_3,6}}');

In this query, we have provided a two-dimensional array to the **json_object()** function. Now the inner arrays i.e {radius_1, 26} , {radius_2, 14}, {radius_3,6} are considered as key-value pairs. This means that for the first inner array, “radius_3” is the key, and “26” is the paired value and the same with all. The outcome of the above query is illustrated below.

The output clearly verifies that in the case of a 2-dimensional text array provided to the **json_object()** function, the elements of the inner array act like key-value pairs.

 **NOTE:** Note that the elements of inner arrays have to be 2. Otherwise, the **json_object()** function will not work on that array and will not return anything.

That was all about providing a single text array to the **json_object()** function. We will next see what happens if we provide 2 arrays to the **json_object()** function.

###  **Case 2: Providing Two Text Arrays to the json_object() Function**

We can provide **2** one dimensional text arrays to the **json_object()** function. In this case, the first array will act like the keys array and the second array will act like a values array. Each key from the first array pairs with the corresponding value at the same place in the second text array. The syntax looks like this:
    
    
    json_object(keys_arr TEXT[], val_arr TEXT[])

In this syntax:

● The function **json_object()** is provided with 2 arrays.

● The first array will always be the **keys array**.

● The second array will always be a **values array**.

● Both the arrays have to be **TEXT** arrays.

● The **json_object()** function will return the JSON object built from these two arrays.

● The return type of the **json_object()** function is **JSON**.

 **NOTE:** here one thing is most important for the function to execute properly, that is the the element of both the arrays should be equal.

Consider the given examples for proper clarity of the concept.

 **Example 1: Using json_object() Function with Two Text Arrays**

The following query is written as an example to understand how the query performs when we provide 2 text arrays to the **json_object()** function.
    
    
    SELECT json_object('{Williams, Tim, Kate}', '{7,9,   6}' );

In such a case, the first array i.e. provided **{Williams, Tim, Kate }** will act as the keys array, and the second array i.e. **{7,9, 6}** acts as the array of values. So each element of the key array pairs with the corresponding given value in the values array. The above query returns the following output.

The output validates the concept we discussed. In this way, the json_object() function builds the JSON object from the provided **TEXT** arrays.

##  **Additional Information: Alternative to json_object() Function**

We can get the keys and values separated from the JSON object, which is returned by the **json_object()** , by using the json_each() or json_each_text() functions. The query can be written as:
    
    
    SELECT * FROM json_each(json_object('{Williams, Tim, Kate}', '{7,9,   6}' )) ;

The query returns the following results.

We can clearly observe that all the keys and values are separated. In case we use the **json_each_text()** function only the difference will be in the returned data type of the values that will be **TEXT**.

##  **Conclusion**

The PostgreSQL **json_object()** function builds a JSON object from the provided **TEXT** array or arrays. The **json_object()** function takes a text array or two text arrays. In the case of a single text one-dimensional array, the alternative elements act as keys and values, the elements need to be even in number. In the case of a single-text two-dimensional array, the inner arrays will be the keys and value pairs. For the two arrays, the first array will be the keys array and the second will be the values array. Each element of the key array pairs with the corresponding element in the value array.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_object-function/)

---

# PostgreSQL json_each_text() Function

> The PostgreSQL json_each_text() function converts the JSON object into its small decomposed key-value pairs.

The JSON data type stores data in JSON objects. The JSON objects are top-level JSON objects comprising key-value pairs. In PostgreSQL, we can separately get the key and values for a JSON object using the two JSON functions; The **json_each()** function and the **json_each_text()** function. This blog primarily focuses on the **json_each_text()** function. So let’s learn about it.

##  **PostgreSQL json_each_text() Function**

The **json_each_text()** function works the same as the json_each() function does. It converts the JSON object into wide pairs/sets of keys and values. The difference between the **json_each() function** and the **json_each_text()** function comes in the return data type. The **json_each() function** gives the key in TEXT and the value in JSON format. while the **json_each_text()** function returns both the key and value in **TEXT** format.

The basic syntax for the j **son_each_text()** function can be written as:
    
    
    json_each_text(obj JSON) -> set_of RECORD(key TEXT, value TEXT)

In the above syntax:

● The **Json_each_text()** function takes in the JSON object as a parameter.

● The **Json_each_text()** function returns the set of expanded key-value pairs for that JSON object.

● The keys/values are collectively stored as RECORD.

● The returned Type of the “key” and “value” is the **TEXT**.

● The two separate columns for “key” and “value” can be returned as an output containing all the expanded key-value pairs in the respective top-level JSON object.

Let’s see how the PostgreSQL **json_each_text()** function can be implemented, using examples.

###  **Example 1: Understanding the json_each_text() Function**

Let’s consider the following query as an example of the json_each_text() function.
    
    
    SELECT json_each_text(
      '{"s_name": "Alex", 
      "s_id": 47,
      "Courses_taken": ["applied Physics", "French", "Algebra"]}');

We have passed the JSON object into the **json_each_text()** function. The function will be the key and values for the provided JSON object like this:

We can note that the function has given us the key-value pairs of the provided JSON object in an expanded form.

We can also get the keys and values in two different columns of a Postgres table.

 **Example 2: Using the json_each_text() Function**

We can get the keys and values of a **JSON** object in two separate columns using the **json_each_text()** function. The same above example is considered here as well, to write the query for this scenario. The query looks like this:
    
    
    SELECT * FROM json_each_text(
      '{"s_name": "Alex", 
      "s_id": 47,
      "Courses_taken": ["applied Physics", "French", "Algebra"]}');

The query will return the keys and values in two separate columns of data like this:

We can notice that the data type of both columns is **TEXT**. This is the point where the **json_each_text()** function is different from the **json_each()** function in Postgres.

In this way, the keys and values can be separated into 2 columns of a table. We can also custom-name these columns. For that, the query can be written like this:
    
    
    SELECT * FROM json_each_text(
      '{"s_name": "Alex", 
      "s_id": 47,
      "Courses_taken": ["applied Physics", "French", "Algebra"]}')
      AS col_names(new_key, new_val );

We are customizing the new names for the key and value columns. The new titles are **“new_key”** for the “key” column and **“new_val”** for the “value” column. The output looks like this:

We can observe the new names instead of the old ones in the output.

###  **Example 3: Using the json_each_text() Function on Table’s Data**

We can use the **json_each_text()** function on a table “online_store” having a JSON object column. The table looks like this:

Now we will implement the **json_each_text()** function on the JSON column. We can write the following query:
    
    
    SELECT json_each(products_in_cart)
    FROM online_store;

The query returns the keys and values as RECORDs for the table column.

Now if we want to separate columns for keys and values, we will execute the following query:
    
    
    SELECT * FROM online_store, json_each_text(products_in_cart);

This query will give the keys and values in separate columns.

We can observe that the **json_each_text()** function has returned the values in the **TEXT** data type. This is how we can use the **json_each_text()** function with table data.

##  **Conclusion**

The PostgreSQL **json_each_text(** ) function converts the JSON object into its small decomposed key-value pairs. The data type of keys and values is **TEXT** , this is the point where the **json_each_text()** function is different from the **json_each()** function. This tutorial comprised the details about the **json_each_text()** function and demonstrated how it is different from the **json_each()** function along with the proper examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_each_text-function/)

---

# PostgreSQL json_to_record() Function

> The Postgres json_to_record() function takes a top-level JSON object as input, converts it into a table record/row, and returns it.

The data stored in JSON objects can be stored in a Postgres table. This will make the data more readable, comprehendible, and easy to understand to generate analytics. We can use many functions to do this such as json_populate_record(), json_populate_recordset(), json_to_record(), and json_to_recordset() function. All these functions work in their own way and have their own limitations. The content of this blog is the **json_to_record()** function. Let’s see how the **json_to_record()** function works in PostgreSQL.

##  **PostgreSQL json_to_record() Function**

The **json_to_record()** function takes a top-level JSON object as input and returns a row expanded from that JSON object, having the respective data type, the same as defined in the **AS** clause. The basic syntax of **json_to_record()** function looks like this:
    
    
    json_to_record(json_obj JSON) AS (col1 data_type, col2 data_type,..... Coln data_type)

In the above syntax:

● The **json_to_record()** function takes the top-level JSON object.

● The **json_to_record()** function is followed by an **AS** clause.

● After the **AS** clause, we need to specify the column names with their corresponding data types.

● The JSON object gets converted into a row, having **RECORD** data type.

To illustrate the working of the **json_to_record()** function, we’ll consider some examples given below.

###  **Example 1: Understanding the json_to_record() Function**

The following query demonstrates the working of the **json_to_record()** function.
    
    
    SELECT
      *
     FROM
      json_to_record(
      '{"student_id": 1, "student_name": "Tom", "subjects": ["Chemistry", "Calculus"]}' ) 
     AS   cols(student_id INT, student_name TEXT, subjects TEXT[]);

In the above query:

● We have specified a top-level JSON object i.e _{ "student_id": 1, "student_name": "Tom", "subjects": ["Chemistry", "Calculus"]}_, in the **json_to_record()** function.

● After the **AS** keyword, we have written the names of the columns with their respective data types.

● The **json_to_record()** function will return a single table row created from the corresponding JSON object. The name and type of the table columns will be the same as specified after the **AS** keyword.

The output of this query is given below:

If we observe the above output, we will be able to comprehend that the JSON object is converted into a table record/row. The name and type of table columns are the same as declared after **AS**.

###  **Example 2: Understanding the json_to_record() Function**

In this section, we will notice the impact when a field in the JSON object is missing but we have created a column for it. Consider the following code.
    
    
    SELECT
      *
     FROM
      json_to_record(
      '{ "student_name": "Tom", "subjects": ["Chemistry", "Calculus"]}')
      AS cols(student_id INT, student_name TEXT, subjects TEXT[]);

In the above code, the “student_id” field in the provided JSON object is missing, whereas, we have created a column for it. In this case, the NULL value will be displayed by the table like this:

This is how the **json_to_record()** function responds to such a case. Now let’s see what will happen if we do not provide the **AS** keyword to the **json_to_record()** function.

###  **Example 3: Implementing the json_to_record() Function Without AS Keyword**

As we have stated the significance of the **AS** keyword earlier i.e. after it, we specify the name and type of the columns, we will see how the function responds when the **AS** statement is not present. Consider the following query.
    
    
    SELECT
      *
     FROM
      json_to_record(
      '{ "student_name": "Tom", "subjects": ["Chemistry", "Calculus"]}');

We have eliminated the **AS** statement from the query. So the output of this query is:

Executing the above query returned an error, which says that we have not specified the column definition list. This clearly illustrates that the **AS** statement and the column definition list are important for the **json_to_record()** function to execute.

###  **Example 4: Using User-Defined Data Type With the json_to_record() Function**

In the **AS** statement of the **json_to_record()** function, the user can also define a column with a custom/user-defined data type. Let’s first create a custom data type using the **CREATE TYPE**.
    
    
    CREATE TYPE major   
     AS (major_name TEXT, current_semester TEXT)

We have created a custom data type i.e. “major”. This data type contains two fields for “major_name” and the “current_semester”. Execution of the above query will successfully create a new user-defined data type.

We will now use it in the column definition in the **json_to_record()** function. The query can be written as
    
    
    SELECT
      *
     FROM
      json_to_record(
      '{"student_id":   1,
       "student_name": "Tom",
       "subjects": ["Chemistry", "Calculus"],
       "major":{"major_name": "Chemical Engineering", "current_semester": "3rd"}}')
      AS cols(student_id INT, student_name TEXT, subjects TEXT[], major major);

In the above query, we have used the user-defined data type “major” for the column definition. The query will return the following output.

We can see that another column is added. The new column “major” has the data type “major” as defined in the custom data type creation.

This is how the **json_to_record()** function works in PostgreSQL.

##  **How to Get Multiple Rows From JSON Objects in Postgres?**

To get multiple rows from the JSON objects, we can use the **json_to_recordset()** function. This function almost works the same as the **json_to_record()** function. The additional thing is we can get multiple rows using the **json_to_recordset()** function method. For that, we will provide the **json_to_recordset()** function with a JSON array containing multiple JSON objects so that they can be converted into a set of rows.

##  **Conclusion**

The Postgres **json_to_record()** function takes a top-level JSON object as input, converts it into a table record/row, and returns it. The **AS** statement complements the **json_to_record()** function and is necessary for the execution of the function. After the **AS** statement, we specify the list of column names with their respective data type. The **json_to_record()** function returns the JSON object’s data according to those table columns.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_to_record-function/)

---

# PostgreSQL json_to_recordset() Function

> In PostgreSQL, the user can convert the data stored in JSON objects (as key-value pairs) to a set of table rows. This operation can be performed by making use …

In PostgreSQL, the user can convert the data stored in JSON objects (as key-value pairs) to a set of table rows. This operation can be performed by making use of the **json_to_recordset()** function. The **json_to_recordset()** function takes a JSON array, which can contain one or more JSON objects. The **json_to_recordset()** function converts those JSON objects into the set of table records/rows. Let’s start learning the **json_to_recordset()** function with examples.

##  **PostgreSQL json_to_recordset() Function**

The PostgreSQL **json_to_recordset()** function takes the **JSON** array. The JSON array might possess one or more JSON objects. These JSON objects are converted into the set of data rows by the **json_to_recordset()** function. The basic syntax for the **json_to_recordset()** function is given below:
    
    
    json_to_recordset(json_arrayJSON) AS (col1 data_type, col2 data_type,..... Coln data_type)

In the above syntax:

● The **json_to_recordset()** function takes in the JSON array.

● The **json_to_recordset()** function is followed by an **AS** clause.

● After the **AS** clause, we have to specify the column definition list i.e. column names with their data types.

● The JSON objects present in the JSON array are converted into a set of rows, having **RECORD** data type.

We will understand the workings of the **json_to_recordset()** function using the example.

###  **Example 1: Understanding the json_to_recordset() Function**

To understand the concept behind the **json_to_recordset()** function, the following query can be used.
    
    
    SELECT
      *
     FROM
      json_to_recordset(
      '[{"student_id": 1, "student_name": "Tom", "subjects": ["Chemistry", "Calculus"]},
     {"student_id": 2, "student_name": "Smith", "subjects": ["Data Structures", "Calculus"]}]')
      AS cols(student_id INT, student_name TEXT, subjects TEXT[])

In the above code:

● We have specified 2 JSON objects in the JSON array. Both these objects will be converted to the rows of the table by using the **json_to_recordset()** function.

● After the **AS** keyword, we have written the names of the columns with their respective data types.

● The **json_to_recordset()** function will return the table rows created from the corresponding JSON objects present in the JSON array. The name and type of the columns will be the same as specified after the **AS** keyword.

The output is given as

We can clearly notice that the **json_to_recordset()** function has returned 2 rows, as we specified 2 JSON objects in the JSON array.

 **NOTE:** Note that the **json_to_recordset()** function primarily takes a JSON array. Otherwise, specifying the JSON object causes an error. We can specify the JSON objects inside the JSON array.

Another important point is that the **json_to_recordset()** function can also return 1 row. This happens when we pass a single JSON object in the JSON array. But, to get the single row **json_to_record()** function is preferred. However, the **json_to_recordset()** function can do it as well.

###  **Example 2: Understanding the json_to_recordset() Function**

In this example, we will detect the impact when a field in the JSON object is missing but we have created a column for it. Consider the following code.
    
    
    SELECT
      *
     FROM
      json_to_recordset(
      '[{"student_id": 1, "subjects": ["Chemistry", "Calculus"]},
       { "student_name": "Smith", "subjects": ["Data Structures", "Calculus"]}]')
      AS cols(student_id INT, student_name TEXT, subjects TEXT[])

In the above code, the “studen_name” in the first JSON object and the “student_id” field in the second JSON object are skipped, whereas, we have created a column for it. In this case, the NULL value will be shown by the table like this:

This is how the **json_to_recordset()** function responds to such a case. Now let’s see what will happen if we do not provide the **AS** keyword to the **json_to_recordset()** function.

###  **Example 3: Executing the json_to_recordset() Function Without AS Keyword**

The significance of the **AS** statement in the **json_to_recordset()** function is already stated. We basically provide the list of column definitions after the **AS** statement. Let’s notice the impact of skipping it.
    
    
    SELECT
      *
     FROM
      json_to_recordset(
      '[{"student_id": 1, "student_name": "Tom", "subjects": ["Chemistry", "Calculus"]},
      {"student_id": 2, "student_name": "Smith", "subjects": ["Data Structures", "Calculus"]}]');

The output of this query is given below:

Running the above query yielded an error, which says that we have not specified the column definition list. This clearly depicts that the **AS** statement and the column definition list are necessary for the **json_to_recordset()** function to execute.

###  **Example 4: Using User-Defined Data Type With the json_to_recordset() Function**

The user can also use a custom data type to define any column. The user-defined/custom data type can be created using the **CREATE TYPE** statement.
    
    
    CREATE TYPE major   
     AS (major_name TEXT, current_semester TEXT)

This query will successfully create a “major” data type for the user now this can be used to define the data type of a column like this:
    
    
    SELECT
      *
     FROM
      json_to_recordset(
      '[{"student_id":   12,
       "student_name": "Will",
       "subjects": ["Organic Chemistry", "Inorganic Chemistry"],
       "major":{"major_name": "Chemical   Engineering", "current_semester": "3rd"}},
       
       {"student_id": 45,
       "student_name": "Oliver",
       "subjects": ["Data Structures", "Calculus"],
       "major":{"major_name": "Software   Engineering", "current_semester": "4th"}}]')
      AS cols(student_id INT, student_name TEXT, subjects TEXT[] , major major);

In the above query, we have used the user-defined data type “major” for the column definition. The query will return the following output.

We can see that another column is added. The new column “major” has the data type “major” as defined in the custom data type creation.

This is how the **json_to_recordset()** function works in PostgreSQL.

##  **PostgreSQL json_to_record() Vs json_to_recordset() Function**

The PostgreSQL **json_to_record()** function takes the **JSON object** and converts it into **a single data row**. Whereas, the PostgreSQL **json_to_recordset()** function takes the **JSON array** as input and returns the **set of rows** expanded from the JSON objects provided in the JSON array.

##  **Conclusion**

The Postgres **json_to_recordset()** function takes a top-level **JSON array** as input and converts it into a set of table rows. The JSON array can contain multiple JSON objects that are expanded into rows. The **AS** statement and the **json_to_recordset()** function, serve together for the execution of the function. After the **AS** statement, we specify the list of column names with their data type. The **json_to_recordset()** function returns the JSON object’s data according to those table columns.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_to_recordset-function/)

---

# Understanding PostgreSQL jsonb_typeof() and json_typeof()

> The PostgreSQL json_typeof() function and the jsonb_typeof() function are used to get the data types of the JSON and JSONB values, respectively, in the string …

There are several JSON functions that PostgreSQL offers that are applicable to the JSON and JSONB data types. The [JSONB](<https://www.commandprompt.com/education/jsonb-data-type-in-postgresql/>) data type is the binary form/version of the [JSON](<https://www.commandprompt.com/education/working-with-postgresql-json-data/>) data type. This came to assist the JSON in analyzing and processing huge amounts of textual data. Some of the JSON functions, among them, are used to manipulate and perform operations on the JSON and JSONB data and some are used to get some information from the given Postgres **JSON** or **JSONB** data.

This tutorial will make us:

● Understand the PostgreSQL **json_typeof()** function.

● Understand the PostgreSQL **jsonb_typeof()** function.

We will go over them one by one.

##  **Understanding PostgreSQL json_typeof() Function**

The **json_typeof()** function takes a JSON value and returns its type as a string. The basic syntax of **json_typeof()** function is given as:
    
    
    json_typeof(json_val JSON)

In the above syntax:

● The **json_typeof()** function takes a **JSON** value as input.

● **json_typeof()** function gives the data type of the provided JSON value as a **string/text**.

● If the function is provided NULL, the NULL value will be returned.

We can understand the workings of the **json_typeof()** function using some examples.

###  **Example 1: Understanding the json_typeof() function in PostgreSQL**

To learn, how the **json_typeof()** function works, we can execute the following query:
    
    
    SELECT
      json_typeof('"Command Prompt"') AS "type of Command Prompt",
      json_typeof('true') AS "type of true",
      json_typeof('[0,7,5,3]') AS "type of [0,7,5,3]",
      json_typeof('973.8383') AS "type of 973.8383",
      json_typeof('{"value":6}') AS "type of Command Prompt {""value"":6}",
      json_typeof('false') AS "type of false",
      json_typeof('null') AS "type of null";

In the above query, we have specified different types of JSON values in the **json_typeof()** function. The function will return the data types of all the JSON values like this:

It is clear in the above output that the **json_typeof()** function has returned the data type of the provided JSON values in the **TEXT** data type.

###  **Example 2: Understanding the json_typeof() function With NULL**

When NULL is provided in the quotes, the **NULL** is returned as a string. This can also be confirmed by the[ IS NULL](<https://www.commandprompt.com/education/postgresql-is-null-operatorcondition/>) statement. The “IS NULL” statement returns true if the expression gives NULL. The following can be the query written in this regard.
    
    
    SELECT json_typeof('null') IS NULL AS "json type of null";

The output of this query is:

The IS NULL statement returned false because passing the **‘null’** to the **json_typeof()** function will give the string **NULL**.

However, if we simply provide the NULL to the **json_typeof()** function, we will get the NULL value, not the string NULL, like this.
    
    
    SELECT json_typeof(NULL)"json type of NULL";

The output of this will be:

Now if we apply the **IS NULL** statement on it, this will return true because the value for this case is **NULL**.
    
    
    SELECT json_typeof(NULL) IS NULL AS "json type of null";

Executing this query will give:

The query returned “true”, which means that the **json_typeof()** function when applied on NULL gives null.

###  **Example 3: Understanding the json_typeof() function in PostgreSQL**

The numeric JSON values that are to be provided to the **json_typeof()** function should be enclosed in the single quotes to get its data type using the **json_typeof()** function. The second thing we can do to the numeric type JSON values is cast the provided value to the TEXT first and then to the JSON data type. The same is the case with boolean values as illustrated in the below query.
    
    
    SELECT 
      json_typeof(46858::text::json) AS "json type of 46858",
      json_typeof(8494.453::text::json) AS "json type of 973.8383",
      json_typeof(false::text::json) AS "json type of true" ;

In the above query:

We have provided an Integer and floating point number to the **json_typeof()** function and typecased them into **TEXT** and then **JSON**. The query is valid and returns the following result.

This is how the **json_typeof()** function works with different JSON values.

##  **Understanding PostgreSQL jsonb_typeof() Function**

The **jsonb_typeof()** function works the same as the **json_typeof()** function does. It takes a **JSONB** value and returns its type as a string. The basic syntax of **jsonb_typeof()** function is given as:
    
    
    jsonb_typeof(jsonb_val JSONB)

In the above syntax:

● The **jsonb_typeof()** function takes a **JSONB value** as input.

● **jsonb_typeof()** function gives the data type of the provided JSONB value as a **string/text**.

● If the function is provided NULL, the NULL value will be returned.

We can understand the workings of the **jsonb_typeof()** function using some examples.

###  **Example 1: Understanding the jsonb_typeof() Function in PostgreSQL**

To learn, how the **jsonb_typeof()** function works, we can execute the following query:
    
    
    SELECT
      jsonb_typeof('"Command Prompt"') AS " jsonbType of Command Prompt",
      jsonb_typeof('true') AS "jsonbType of true",
      jsonb_typeof('[0,7,5,3]') AS "jsonbType of [0,7,5,3]",
      jsonb_typeof('973.8383') AS "jsonbType of 973.8383",
      jsonb_typeof('{"value":6}') AS "jsonbType of Command Prompt {""value"":6}",
      jsonb_typeof('false') AS "jsonbType of false",
      jsonb_typeof('null') AS "jsonbType of null";

In the above query, we have specified different types of **JSONB** values in the **jsonb_typeof()** function. The function will return the data types of all the JSONB values like this:

It is clear from the above output that the **jsonb_typeof()** function has returned the data type of the provided JSONB values in the **TEXT** data type.

###  **Example 2: Understanding the jsonb_typeof() function With NULL**

When NULL is provided in the quotes, the **NULL** is returned as a string. This can also be proved using the[ IS NULL](<https://www.commandprompt.com/education/postgresql-is-null-operatorcondition/>) statement. The “IS NULL” statement returns true if the expression gives NULL. The following can be the query written in this regard.
    
    
    SELECT jsonb_typeof('null') IS NULL AS "jsonb type of null";

The output of this query is:

The IS NULL statement returned false because giving the **‘null’** to the **jsonb_typeof()** function will give the string NULL.

However, if we simply provide the NULL to the **jsonb_typeof()** function, we will get the NULL value, not the string NULL, like this.
    
    
    SELECT jsonb_typeof(NULL) AS "jsonb type of NULL";

The output of this will be:

Now if we apply the **IS NULL** statement on it, this will return true because the value for this case is **NULL**.
    
    
    SELECT jsonb_typeof(NULL) IS NULL AS "jsonb type of null";

Executing this query will give:

The query returned “true”, which means that the **jsonb_typeof()** function when applied on NULL gives null.

###  **Example 3: Understanding the jsonb_typeof() Function in PostgreSQL**

The numeric JSONB values that are to be provided to the **jsonb_typeof()** function should be enclosed in the single quotes to get its data type using the **jsonb_typeof()** function. The second thing we can do to the numeric type JSONB values is cast the provided value to the TEXT first and then to the JSONB data type. The same can be done to boolean values as well. The below query illustrates the concept.
    
    
    SELECT 
      jsonb_typeof(46858::text::jsonb) AS "jsonb type of 46858",
      jsonb_typeof(8494.453::text::jsonb) AS "jsonb type of 973.8383",
      jsonb_typeof(true::text::jsonb) AS "jsonb type of true" ;

In the above query:

We have provided an Integer and floating point number to the **jsonb_typeof()** function and typecast them into **TEXT** and then **JSONB**. The query is valid and returns the following result.

This is how the **jsonb_typeof()** function works with different JSONB values.

##  **Conclusion**

The PostgreSQL **json_typeof()** function and the **jsonb_typeof()** function are used to get the data types of the JSON and JSONB values, respectively, in the string format. The JSON and JSONB values are provided to the **json_typeof()** function and the **jsonb_typeof()** function respectively. The sections above demonstrated the working of the **json_typeof()** function and the **jsonb_typeof()** function with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/understanding-postgresql-jsonb_typeof-and-json_typeof/)

---

# How to Use ASCII() Function in Postgres

> In PostgreSQL, the ASCII() function is used to find the ASCII code for the given characters. This character can be a special character as well.

PostgreSQL provides a wide range of string functions that are utilized to retrieve some information regarding a specific string. **ASCII()** function is one of those functions. This function gives the **ASCII code** of a character. The character whose ASCII code is to be found is passed into the function as a parameter.

This article will contain a detailed demonstration of the working of the **ASCII()** function in PostgreSQL.

##  **How to Use the ASCII() Function in PostgreSQL?**

As discussed in the introduction, the **ASCII()** function returns the ASCII code for the character that is passed into it. The syntax of the ASCII() function is given as:
    
    
    ASCII(Character);

In the above syntax:

● The **character** whose ASCII number is to be found is passed into the ASCII() function.

● The function will return an **integer** as the ASCII code of the provided character.

There are some important points regarding the ASCII() function:

● We can also find the ASCII code of the special characters using this **ASCII()** function.

● The ASCII code of upper and lower case letters is different.

● We can also provide a string to the **ASCII()** function. In this case, the function will return the ASCII code for only the first character of that string.

We will later understand all these cases with the help of examples. First, let’s see how the ASCII() function is used in Postgres.

###  **Example 1: Using ASCII() Function**

Let’s find the ASCII code for the letter “S” using the ASCII() function. The query for this can be written as:
    
    
    SELECT ASCII('S') AS ASCII_code_capital_S;

The output of this query gives the ASCII code for the “ **S** ”, which is “ **83** ”:

###  **Example 2: Using ASCII() Function with Special Characters**

We can also find the ASCII code for the special characters in Postgres by utilizing the ASCII() function like this:
    
    
    SELECT 
    ASCII('&') AS ASCII_code;

The query will give the ASCII code for the “&” operator as:

The ASCII code of the “ **&** ” is **38**.

###  **Example 3: Using ASCII() Function With Upper and Lower Case Letters**

We will write the following query to notice the ASCII code for the upper and lower case letters:
    
    
    SELECT 
      ASCII('S') AS ASCII_code_capital_S,
      ASCII('s') AS ASCII_code_small_s;

The output of this query will be the ASCII code for the capital and small “s”. We will note that the code will be different for both. The output is:

Note that the ASCII code for the upper case “ **S** ” is **83** and for the lower case, it is **115**. So the code is different when changing the case of the character.

Let’s implement the **ASCII()** function on a string.

###  **Example 4: Using ASCII() Function With String**

We can also provide a string of more than one character in the **ASCII()** function. But the function will give the ASCII code of only the first character/letter of that provided string. Let’s write up the following query to observe the output:
    
    
    SELECT 
      ASCII('S') AS ASCII_code_S,
      ASCII('Smith') AS ASCII_code_Smith;

The above query will give the ASCII code for the letter “S” and the string “Smith” as:

We can see that the ASCII code for the string “Smith” is the same as that of the letter “S”. So this point is verified that the **ASCII()** function gives the ASCII code for the first character/letter of the provided string.

This is how the **ASCII()** function works to find the ASCII code of the given character/string in PostgreSQL.

###  **Conclusion**

The **ASCII()** function is used to find the ASCII code for the given characters. This character can be a special character as well. If we pass a string into the **ASCII()** function, the function will give us the ASCII code of only the first character of that string, not the whole string. The **ASCII** code is case sensitive, which means that the lower and upper case of the same letter have different **ASCII** codes. In this post, we have discovered the workings of the ASCII() function along with its use cases.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-ascii-function-in-postgres/)

---

# PostgreSQL degrees() Function

> The degrees() function takes in the angle in radians with double precision data type, and converts and returns the angle value in degrees also having double pr…

There is a huge list of mathematical functions offered by PostgreSQL. These mathematical functions assist the user in performing the mathematical computations. The **degrees()** function is used to convert the angle in **radian value into degrees**. The SI unit for the measurement of angles is **radian**. In this post, we’ll learn how the **degrees()** function works.

##  **PostgreSQL degrees() Function**

The **degrees()** function takes in a **double precision** as an angle in radians and also returns a **double precision** but as degrees. The **degrees()** function simply converts the angle in radians into degrees.

The syntax of this function looks like this:
    
    
    degrees(angle_in_radian_dp)

The argument provided to the **degrees()** function is the angle in radians and the data type will be double precision. The function returns the angle in degrees.

We will go through some examples to get the concepts more clearly.

###  **Example 1: Understanding degrees() Function**

Consider the following query to understand the degrees() function:
    
    
    SELECT
      degrees(0) AS "degrees:0",
      degrees(1.0) AS "degrees:1.0",
      degrees(9.45) AS "degrees:9.45",
      degrees(-11.56) AS "degrees:-11.56",
      degrees(17.79*2) AS "expression degrees";

The function will convert all the radian values, provided to it, into the degrees like this:

  
We can see that the **degrees()** function has converted all the radian values into degrees. Other than that we can notice the following things in the above case:

● The function also supports the **negative values** (-11.56).

● We can also specify any **expression** (17.79*2) in the **degrees()** function. The function will first solve the expression and then convert the value into degrees.

This is the basic working of the **degrees()** function.

###  **Example 2: Using degrees() Function to Get Full Circle**

The full circle in radians is equal to “ **6.283185307179586** ” radians. Now if we pass the stated radian value to the **degrees()** function, it will return the full circle in degrees.
    
    
    SELECT
      degrees(6.283185307179586) AS "Full Circle";

The output for this query is:

  
We can observe that the radian value 6.283185307179586 has given the full circle i.e. 360 degrees.

###  **Example 3: Using degrees() Function With Other Functions**

We can also use the **degrees()** function with other functions. The PI() function returns the mathematical constant value of pi. So let’s use it in a query.
    
    
    SELECT
    degrees(PI()) AS "Half Circle";

The **PI()** function will provide the mathematical constant value of **π** i.e. 3.141592653589793. The **degrees()** function will then convert the radian value of **π** into degrees like this.

  
We can see that the degrees() function has returned 180 degrees which is the half circle. We can also get the full circle by passing the 2*PI() argument in the **degrees()** function like this:
    
    
    SELECT
    degrees(PI()*2) AS "Full Circle";

This will give the full circle as **2π** is equal to the full circle.

###  **  
Using Radian() Function**

There are many other functions with which we can use the **degrees()** function for example **radian()** is another function that converts the degrees into radians. Let’s observe what happens if we use the **radians()** function in the degrees function. Consider the below query for this:
    
    
    SELECT
      degrees(radians(4*90)) AS "Full Circle";

● The query will first solve the expression i.e. 4*90 that gives 360.

● The 360 is in degrees that is given as input to the radians() function.

● The **radians()** function will convert the 360 degrees into radians.

● That radian value is then provided to the **degrees()** function to get the final output.

If we carefully understand the query, we will get to know that the **degrees()** and **radians()** functions **counterbalance** each other's effect. So we will get the 360 degrees as output. To verify this let’s see what the query has returned.

  
The query returned the same output as we expected.

###  **Example 4: Using degrees() Function on Table’s Data**

We can implement the **degrees()** function on the table data. For this particular function, consider the table named “circle”.

  
We will write the following query if we wish to convert every angle given in the column “angle_in_rad” into degrees:
    
    
    SELECT angle_in_rad, degrees(angle_in_rad) AS "angle in degrees"
     FROM circle;

On executing this query, we will get the degree conversion of each angle_in_rad entry like this:

  
This is how we can implement the **degrees()** function on table data to get the radian values in degrees.

##  **Conclusion**

The mathematical **degrees()** function in PostgreSQL converts the radian values of angles into degrees. The function takes in the angle in radians with double precision data type, and it converts and returns the angle value in degrees also having double precision data type. We have implemented different use cases for the **degrees()** function in detail, to understand the concept clearly.

---
[View this page online](https://www.commandprompt.com/education/postgresql-degrees-function/)

---

# PL/pgSQL Errors and Messages

> Postgres offers several methods to display/show these errors to users and notify them through messages so that the program can be executed normally as expected…

One of the significant features of Postgres is “ **error handling** ”. Postgres offers several methods to display/show these errors to users and notify them through messages so that the program can be executed normally as expected and without any interruption.

In this article, we will learn about some of the built-in errors in PostgreSQL and how these errors are raised using the **RAISE** statement.

##  **PL/pgSQL Errors and Messages**

The errors and messages need to be raised in PostgreSQL in order to report them to the user. Reporting the errors to the user is important as it helps in understanding the reason behind the error so that it can be fixed.

###  **Report Messages**

To raise a message, we make use of the **RAISE** keyword. The basic syntax for raising a message is:
    
    
    RAISE level format;

Let's have a look at the syntax of the above query and try to understand what is what. You can see that the **RAISE** statement is followed by the level option. Level basically depicts and shows the seriousness of the particular error. PostgreSQL offers several levels that are listed below:

● DEBUG

● INFO

● NOTICE

● LOG

● EXCEPTION

● WARNING

Note that if there is no level specified then by default, the RAISE statement considers it as an **EXCEPTION** level. In this case, it would stop the current transaction.

Next is the **format**. The format is basically a string/text that determines the message to be shown. The format contains a **% placeholder** , that will be replaced by the provided argument. It is a crucial point that the placeholders and number of arguments should be equal. Otherwise, this situation will throw an error.

Let’s see an example of how the **RAISE** statement works.

###  **Example 1: Understanding Reporting Messages**

In the example below, the **RAISE** statement reports multiple error messages at the same instance:
    
    
    DO $$ 
    BEGIN 
    RAISE LOG 'Log   message is raised at: %', now() ;
    RAISE DEBUG 'Debug message is raised at: %', now();
    RAISE INFO 'Information message is raised at: %', now();
    RAISE NOTICE 'Notice message is raised at: %', now();
    RAISE WARNING 'Warning message is raised at: %', now();
    END $$;

The **now()** function is used to get the current time and then that time is substituted by the **% placeholder**. The output for the above-written query is given as:

Here one thing to be noticed is that not every message is reported back to the client/user. Only messages of type INFO, NOTICE, and WARNING are reported back. These settings are however administered by **_client_min_messages_** and **_log_min_messages_** options.

###  **Raising Errors**

The syntax for raising an error is the same as for reporting messages. However, the level for raising errors is the **EXCEPTION** level. But if it is not written, the **RAISE** statement still considers it **EXCEPTION** by default. Besides level, you can also specify more information with the **RAISE** statement. You can do this by writing the following query:
    
    
    USING option = expression

The option here can be of any type given below:

 **MESSAGE:** Sets the text of the error message.

 **HINT:** Provides us with hints(helps to discover the actual cause of error).

 **DETAIL:** This gives us detailed/precise facts about the error.

 **ERRCODE** : Identifies the error code.

###  **Example 2: Raising Errors in PL/pgSQL**

Let’s have a look at an example to cover this concept:
    
    
    do $$ 
     declare
      Username varchar(255) := 'alexpeter';
     begin 
      --   check Username is available or not
      -- …
    raise exception 'Username % not Available :(', Username
     using hint = 'Please   select some other username';
     end $$;

In the above example, the user checks for the username if it is already in use or not. The output in this case is:

###  **Example 3: Raising SQLSTATE Error**

Now let's consider another example, for that, we will write the query for SQLSTATE.
    
    
    DO $$ 
     BEGIN 
      --...
      RAISE SQLSTATE '4510B';
     END $$;

The output for the code is:

We can see that the **SQLSTATE** error has been raised by the above query.

###  **Example 4: Raising Errors in PL/pgSQL**

Consider the following provided query to assess the more about raising error in PL/pgSQL:
    
    
    DO $$ 
     BEGIN 
      --...
      RAISE invalid_regular_expression;
     END $$;

In this case, the error raised is “invalid_regular_expression”.

In this way, we can raise the errors to make the users aware of the errors raised.

##  **Conclusion**

PostgreSQL has some built-in errors. We must display these errors/issues to the user and report them via messages so that the program is executed normally without any interruption. In this article, we have learned about some of the built-in errors in PostgreSQL and how these errors are raised with practical examples.

---
[View this page online](https://www.commandprompt.com/education/plpgsql-errors-and-messages/)

---

# PostgreSQL json_populate_recordset() Function

> The json_populate_recordset() function converts the JSON array into a set of data rows. The JSON array can contain multiple JSON objects, which can be converte…

The data stored in JSON objects can be converted into multiple table rows by using the **json_populate_recordset()** function. The **json_populate_recordset()** function converts the JSON array containing multiple JSON objects into a set of table rows. The detailed working of the **json_populate_recordset()** function is provided in the following sections.

##  **PostgreSQL json_populate_recordset() Function**

The **json_populate_recordset()** function converts the provided JSON array into the set of table rows. The basic syntax of the **json_populate_recordset()** function is given below:
    
    
    json_populate_recordset ( base_val ANYELEMENT, json_array JSON ) → set_of ANYELEMENT

In the above syntax:

● The **json_populate_recordset()** takes **2** parameters.

● The base value illustrates the type of value in which the **JSON** array values are converted.

● The **JSON** array is specified which needs to be converted.

The PostgreSQL **json_populate_recordset()** function returns the set of data rows that were transformed from the JSON array provided.

The value of the base is usually declared as **NULL**. This means that any output column that does not match the JSON array/object field will return a null value.

The above concepts might seem complicated at times but we’ll examine them using examples so that the working of the **json_populate_recordset()** function becomes effortless to comprehend. Let’s move forward with examples.

###  **Example 1: Understanding json_populate_recordset() Function**

To implement the **json_populate_recordset()** function in any example, we will follow the below-given steps.

 **Step 1: Create A User-Defined\Custom Data Type**

We can create a custom data type using the CREATE TYPE keyword. The query for the creation of a custom data type “team” looks like this:
    
    
    CREATE TYPE team 
     AS (member_id INT,member_name TEXT, Projects TEXT[])

This query will successfully create a custom data type named “team” in the Postgres.

 **Step 2: Implement the json_populate_recordset() Function**

Now we’ll use the **json_populate_recordset()** function on this newly created custom data type. The query can be written as:
    
    
    SELECT * FROM
      json_populate_recordset(
      NULL::team, 
      '[{"mem_id": 1,
       "mem_name": "Williams Tim",
       "projects": ["game app", "clothing website"]}]');

In this code:

● The base value is specified as NULL. This means that if any JSON object field(provided in the JSON array i.e. the second argument) is missing, the function will return a null value in place of it.

● In the second argument, we have specified the JSON object that we wish to convert. In this case, the function got only one **JSON** object in the JSON array, so only one row will be returned like this:

We can also get multiple rows from the data of JSON objects using the **json_populate_recordset()** function.

###  **Example 2: Specifying Multiple JSON Objects in json_populate_recordset() Function**

If we specify multiple **JSON** objects in the **json_populate_recordset()** function, we will get multiple rows. Let’s execute the following query:
    
    
    SELECT * FROM
      json_populate_recordset(
      NULL::team, 
      '[{"mem_id": 1,
      "mem_name": "Williams Tim",
      "projects": ["game app", "clothing website"]},  
      {"mem_id": 2,
      "mem_name": "Tim Wills",
      "projects": ["ludo app", "food app"]}]');

In this case, we have specified two JSON objects. So the function will return two data rows like this:

Hence, from the above image, it is clear that if we provide multiple JSON objects in the JSON array, we will be able to get multiple rows.

Now we’ll see how the base value impacts the outcome of the **json_populate_recordset()** function.

###  **Example 3: Base Value in json_populate_record() Function**

The base value is usually declared as NULL. This is because if some field of the JSON object is missing, the function will return NULL in its place. Let’s not specify the “projects” field in the JSON object. We’ll see how will it be executed.
    
    
    SELECT * FROM
      json_populate_recordset(
      NULL::team, 
    '[{"mem_id": 1,
       "mem_name": "Williams Tim"},   
       {"mem_id": 2,
       "mem_name": "Tim Wills"}]');

In this query, you can notice that we haven’t specified the “projects” field. Upon execution, the query returns the following output.

We can clearly observe that the “projects” column has returned NULL values. This is the significance of specifying NULL as the base value.

We can write any other value, of our choice, as the base value. In such a case, if any field is absent from the JSON object, the value declared in the base value is returned in its place. Let’s comprehend this concept using the following query:
    
    
    SELECT * FROM
       json_populate_recordset(
      (1, 'any_member_name', Array['dummy project', 'project abc']):: team, 
     '[{"mem_id": 1,
       "mem_name": "Williams Tim"},  
       {"mem_id": 2,
       "projects": ["ludo app", "food app"]}]');

Here, we have specified some base value fields. These fields must be in the same order and the same data type as declared in the JSON object and the custom data type. We can also notice that the “projects” field from the first specified JSON object is missing and in the second field the member’s name is missing. How will the query respond?

In such a case, the missing fields from the JSON object take their value from the defined base value. The same was the scenario in the case of NULL as well. The output of this query is given as:

It is very clear from the above output, that the base value is declared so that it can be returned and utilized in case some field in the JSON object is missing as compared to the custom data type defined earlier.

##  **json_populate_recordset() Vs json_populate_record() Function in PostgreSQL**

The main difference between the **json_populate_recordset()** and the **json_populate_record()** function is that the **json_populate_record()** function takes the JSON object as input and returns only one row. While the **json_populate_recordset()** function takes the JSON array containing one or multiple JSON objects and returns the set of rows from them.

##  **Conclusion**

The **json_populate_recordset()** function converts the JSON array into a set of data rows. The JSON array can contain multiple JSON objects, which can be converted into arrays by using the **json_populate_recordset()** function. This blog demonstrated the working of the **json_populate_recordset()** function with proper examples and also sketched the difference in working of the **json_populate_recordset()** and **json_populate_record()** function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_populate_recordset-function/)

---

# How Does the pi() Function Work in PostgreSQL?

> Use the pi() function in PostgreSQL to get the mathematical constant value of π. pi() can be used in mathematical expressions to use the value of π.

The **pi()** function is one of the mathematical functions that is frequently used in PostgreSQL. This function returns the mathematical constant value of the **π** “pi”. The π is widely used in mathematical calculations and we can also use the mathematical value of **π** in Postgres by using this **pi()** function. In this blog, we will use the **pi()** function and understand how it works.

 **How Does the pi() Function Work in PostgreSQL?**

The **pi()** function gives the mathematical constant value of **π**. The syntax of this function is:
    
    
    SELECT PI();

The return type of this function is the **DOUBLE PRECISION** data type. Let’s execute the **pi()** function to see what it returns:

We can observe that the **pi()** function has returned the mathematical constant value of **π** and the data type returned by this function is **DOUBLE PRECISION**.

We can use it in expressions as well. Let’s see how.

 **Example 1: pi()** **Function in PostgreSQL**

We can use the **pi()** function in expressions for example we can execute the following expression to get the desired output:
    
    
    SELECT PI()* 2;

In the above expression, we have multiplied the constant value of **π** by 2. This will give the following output:

This is how we can use the **pi()** function in any expression.

 **Example 2: Applying Functions on pi()** **Function in PostgreSQL**

We can apply some other function to the **pi()** function. Like, in the below query, we will be applying the [ROUND() function](<https://www.commandprompt.com/education/postgresql-round-function-with-examples/>) to the **pi()** function.
    
    
    SELECT ROUND(PI());

The query will return the rounded value of the **π** as an output.

Similarly, we can apply the [CEILING()](<https://www.commandprompt.com/education/how-does-the-ceiling-function-work-in-postgresql/>) and [FLOOR()](<https://commandprompt.com/education/how-to-use-floor-function-in-postgresql/>) functions on the **pi()** function like this:
    
    
    SELECT 
    CEILING(PI()),
    FLOOR(PI());

The above query gives the ceiling and the floor value of the **π** in output.

In this simple way, we can apply functions on the **pi()** function.

 **Example 3: Using PI() Function to Calculate the Circumference of Circle**

Another significant use case of the **pi()** function is calculating the circumference of circles. Let’s create the following table in which we will be calculating the circumference of the circle using the generated columns. The query can be written as:
    
    
    CREATE TABLE circles (
    circle_id SERIAL PRIMARY KEY,
    Radius INT NOT NULL, 
    circumference DECIMAL
    GENERATED ALWAYS AS (2* PI()* Radius) STORED
    );

The query will successfully create the table. Now if we want to insert some values into the table, we will write the following query.
    
    
    INSERT INTO circles(Radius)
    VALUES(1),(3),(5),(7),(9);

The values will be inserted in the “circles” table. The values will also be automatically inserted in the ”circumference” column because it is a generated column and the value of each row is computed by the expression provided i.e. “2* PI()* radius”. Now we will run the **SELECT** statement to get the table.
    
    
    SELECT * FROM circles;

The output of this query is:

In this way, we can use the **pi()** function in a Postgres table to calculate the circumference of circles. There can be more use cases to apply the function in any table.

This was all about the basic functioning of the **pi()** function in Postgres.

 **Conclusion**

Use the **pi()** function in PostgreSQL to get the mathematical constant value of **π**. We can use this function in different mathematical expressions where we need to use the value of **π**. In this article, we understood the workings of the **pi()** function with different examples and use cases.

---
[View this page online](https://www.commandprompt.com/education/how-does-the-pi-function-work-in-postgresql/)

---

# PL/pgSQL Block Structure

> PL/pgSQL supports block structure. The block has two sections; a declaration and a body. Sub-block structure is also supported by PL/pgSQL.

PL/pgSQL is the procedural language for the PostgreSQL database that supports the concept of block structuring. A " **block** " in Postgres refers to a data storage building block where information can be stored. In simple terms, it is just like a container that can keep a certain amount of data. It has a crucial/vital role in storing and manipulating Postgres database data.

In this post, we’ll understand the structure of the PL/pgSQL language. We will also learn to write the PL/pgSQL block. Let’s get started.

##  **PL/pgSQL Block Structure**

PL/pgSQL is a block-structured language. Therefore, the PL/pgSQL functions are organized into block structures. But what does a block look like?

Following is a basic syntax of a complete block in PL/pgSQL:
    
    
    [ <<label>> ]
       [ DECLARE
      Write declarations here]
     BEGIN
      Write your statements/code/queries here.
     END [ label ];

Let’s have a look at the main components of a block:

Every block is divided into two main sections: **Declaration** and **body**. The declaration section is completely optional to write. Whereas it is compulsory to write the body in the block structure. The variables are declared in the declaration section which are used within the body and the body is where you write your code. Each statement in both sections is terminated by semicolons.

One thing is to be noted here, the block ends where there is a semicolon after the END statement. Also, a block may contain an optional label at the beginning and end. The label has to be the same in both places.

 **Example**

Below is a very simple example illustrating the basic syntax of **PL/pgSQL** Block Structure:
    
    
    DO $$
       <<first_block>>
     DECLARE
      stud_count integer := 0;
     BEGIN
      --   Get the number of Students in a class
      SELECT count(*)
      INTO stud_count
      FROM test_scores;
      --   display a message
      RAISE NOTICE 'The number of Students is %', stud_count;
     END first_block   $$;

In the above example, the block starts from the **_< <first_block>>_** label and ends at the semicolon after the END statement. In the declare section, the variable, **_stud_count_** is declared as zero.

The body section starts from the BEGIN statement, where the whole code is placed. Here in the body, we have used **SELECT INTO** with **count()** function to get the number of students from the table _Students_ and assign the value to the variable i.e. student_count.

The **RAISE NOTICE** is used to show the message. Here the essential point to mention is that **_do_** is not part of the block. It is just there to execute/run an anonymous block of code.

The output of this query is the number of students present in the table “test_score”. The output looks like this:

We can see that the query has not shown the initially declared value of the _stud_count_ rather it entered the block to print the count value from the table.

##  **PL/pgSQL Sub-block Structure**

PL/pgSQL also supports a sub-block structure. We can place another block inside a block. The block placed/nested inside a block is called a sub-block. The block that possesses/contains the subblocks is called the outer block. So, the basic concept is **the outer block is divided into smaller but more logical sub-blocks**.

Below is the basic syntax showing a sub-block and an outer block:
    
    
    [ <<label>> ]
      [ DECLARE
      Write declarations here]
     BEGIN
      Write your statements/ queries here.
      --
      -- Create a subblock
      --
      [ DECLARE
      Write declarations here ]
      BEGIN
      Write your statements/queries here
      END;
     END [ label ];

A sub-block is created, this will also contain both sections i.e. declaration and the body similar to the outer block. We’ll implement the sub-block structure of PL/pgSQL in the following example.

 **Example: Understanding the Sub-Block Structure of PL/pgSQL**

Let’s understand the sub-block structure of the PL/pgSQL using the following query, which keeps the student count. The query is given below:
    
    
    DO $$ 
       <<outer_block>>
     DECLARE
      stud_count int := 0;
     BEGIN 
      stud_count := stud_count + 10;
      RAISE NOTICE 'The current count of   students is %', stud_count;
     -- the inner block/sub-block starts from   here
     DECLARE 
      stud_count int := 100;
      BEGIN 
      stud_count := stud_count + 20;
      RAISE NOTICE 'The current count of students in the subblock is %', stud_count;
      RAISE NOTICE 'The current count of students in the outer block is %', outer_block.stud_count;
      END;
    -- the inner block/sub-block ends here
    RAISE NOTICE 'The current count of students in the outer block is %', stud_count;
    END outer_block $$;

In the above code;

● There is an inner/ sub-block in the “outer_block” that starts from the inner **DECLARE** statement and ends at the inner **END** statement.

● We have declared the variable “stud_count” as 0 in the outer block. After the **BEGIN** keyword, we have added the integer 10 in the “stud_count” and raised it as a **NOTICE**.

● The inner block gives the “stud_count” variable the value of 100.

● We have raised a **NOTICE** of “stud_count” + 20 in the inner block, we will get 120 in return. Here the value of “stud_count” is 100.

● Now if we want to access the outer-block value of the “stud_count”. We will have to access it by the dot operator i.e. “outer_block.stud_count”. This gives us the current value from the outer block.

● After the **END** keyword, the inner block is ended. After that, everything lies in the outer block.

● The last **RAISE NOTICE** statement returns the current value of “stud_count” in the outer block.

The above description can easily be understood by following the below output.

This is how the sub-block structure works in PL/pgSQL.

##  **Conclusion**

PL/pgSQL supports block structure. The blocks start from the **DECLARE** statement till the **END** statement. Remember that the _do_ statement is not included in the block. The block has two sections; a declaration and a body. Sub-block structure is also supported by PL/pgSQL, which means that we can create a sub-block in an outer block. In this article, we have learned about the structure of PL/pgSQL structure and how it is implemented using examples.

---
[View this page online](https://www.commandprompt.com/education/plpgsql-block-structure/)

---

# The Risks of Not Having a Multi-Region PostgreSQL Cluster

> Introduction:In today&#x27;s fast-paced digital landscape, data is at the heart of every organization&#x27;s success. The PostgreSQL database system is a robust and popu…

**Don’t worry, mitigating the risk is easier than you may think.**

## Introduction:

In today's fast-paced digital landscape, data is at the heart of every organization's success. The PostgreSQL database system is a robust and popular choice for managing critical data, but ensuring database availability, scalability, and resilience is crucial. One strategy that can significantly mitigate risks associated with database availability is adopting a multi-region architecture. SaaS applications in particular are often implemented as single-region applications, and can benefit greatly from a multi-region approach. In this blog post, we'll delve deep into the risks of not having a multi-region strategy for your PostgreSQL database system and explore why it's a game-changer in today's data-centric world.

###  **The Single-Region Dilemma**

In the world of cloud-based databases, it's not uncommon for businesses to initially adopt a single-region setup. This means that they host their entire database infrastructure within a single geographic region provided by their chosen cloud service provider (CSP). While this approach might seem straightforward and cost-effective, it comes with significant risks and limitations that businesses must carefully consider.

pgEdge Cloud is fully-distributed PostgreSQL, deployable across multiple cloud regions or data centers, with ultra high-availability, disaster recovery capabilities, data residency, compliance adherence, and business continuity. These benefits collectively help mitigate single-region deployment risks by reducing dependency on a single region and enhancing overall system resilience and flexibility.

###  **Risks and Limitations of Single-Region Database Setup**

 **Limited Availability:** The primary drawback of a single-region setup is its limited availability. If the chosen region experiences downtime due to technical issues, maintenance, or unforeseen disasters (natural or otherwise), the entire database becomes inaccessible. This can result in a complete halt to business operations, leading to revenue loss and frustrated customers. Simply saying “we are down because our cloud provider is down” no longer is acceptable to your customers (or investors) when the outage is just one region.

 **Data Loss:** In the event of a catastrophic failure in a single-region setup, data loss is a real concern. While cloud providers implement robust backup and disaster recovery solutions, these may not always be sufficient to prevent data loss. For example, if a severe hardware failure occurs and the data center experiences data corruption, recovery may be challenging, leading to potentially irreplaceable data loss.

 **Latency Issues:** Depending on the location of the single region, users located far from that region may experience latency issues when accessing the database. Slow response times can result in a poor user experience and may deter potential customers.

## Key takeaways with pgEdge

 **Disaster Tolerance:** In the event of a catastrophic failure, such as a natural disaster or data center outage, having a copy of your database in another region provides a robust disaster recovery solution. You can quickly failover to the secondary region to minimize downtime and data loss. Using streamlined monitoring management with pgEdge toolset, and multi-master replication features, you don't need to worry about failover at all, period!

 **Load Balancing:** Multi-region setups allow for intelligent load balancing. You can route traffic to the nearest and healthiest region, optimizing performance and ensuring that each region operates at peak efficiency. Load balancing is simplified by pgEdge's out-of-box integration with [pgCat](<https://github.com/postgresml/pgcat>) \- the next generation of PostgreSQL connection pooler, which supports sharding, load balancing, and mirroring.

 **Support for Multi-Master (Active-Active) Architecture:** Organizations adopting pgEdge have the option of going fully distributed, thanks to pgEdge’s built-in support for multi-master replication and delta conflict avoidance, allowing for multiple nodes to take both read and write traffic at each regional node. Alternatively the additional regional node(s) can be configured to only accept read traffic, or can simply be passive standby nodes ready for when disaster strikes.

 **Cloud Diversification Strategy:** To mitigate the “cloud concentration risk” associated with single-cloud deployment, pgEdge Cloud adopts a multi-cloud approach, optionally distributing database instances across multiple cloud service providers. It includes iEven if one CSP encounters a disruption, a pgEdgenode in another cloud can seamlessly take over, maintaining database uptime.

 **Operational Resilience:** By diversifying database hosting across CSPs, operational resilience is enhanced, safeguarding critical database services from disruptions caused by issues with a single CSP.

 **Risk Assessment:** Our thorough risk assessment at the outset takes into account the reliance on a CSP’s offerings w.r.t multi-region availability for database hosting, and ensures the implementation of PostgreSQL database administration best practices.

In summary, the risk associated with single-region deployment can have significant consequences for critical PostgreSQL database applications. To address concerns related to downtime, compliance, high-availability, and scalability, it's evident that diversifying data hosting across multiple cloud providers or adopting a multi-cloud and multi-region strategy is a prudent approach to safeguard your data and applications against potential disruptions.

Learn more about [pgEdge Cloud](<https://www.pgedge.com/products/pgedge-cloud>) or watch a live demo and presentation of “[How to Make Your SaaS Resilient with Multi-region](<https://pages.pgedge.com/saas-multi-region-webinar>)”.

By : **Hari Kiran**

[ **Originally published**](<https://www.pgedge.com/blog/the-risks-of-not-having-a-multi-region-postgresql-cluster>) **.**

---
[View this page online](https://www.commandprompt.com/education/the-risks-of-not-having-a-multi-region-postgresql-cluster/)

---

# PostgreSQL Full-Text Search

> In PostgreSQL, the full-text search returns all the possible results for the searched terms and their variants as well which was a drawback of the simple searc…

By default, PostgreSQL supports exact searches. For Example, if we search for “mobile phone”, PostgreSQL will look for the exact same field named “mobile phone” in the database tables and will show the result accordingly.

What if a user wants to buy a shirt and a watch and he searches for “shirts and watches”? Or what if the user searches for a term with misspell? PostgreSQL generally searches for the same results as the sentence/phrase given by the user. But the major flaw in this approach is that not necessarily there would be products existing with the same name. Consequently, this will affect the system so much and will result in a reduction of sales causing a big loss for the company.

##  **Simple Text Search**

There are many operators that are used to perform basic string matching. The most commonly used are **LIKE/ILIKE** (SQL wildcard matches), where **LIKE** is case sensitive and **ILIKE** is case insensitive. Two other commonly used methods are **SIMILAR TO** (SQL Regex) and **~** (POSIX Regex).

But these approaches do have some limitations which made them less ideal for use. These approaches lack linguistic support i.e. they are unable to identify synonyms of the words used, and sentence structure, and ignore the frequently occurring words. They do not possess the ability to rank the search results. These queries are also slow in nature because of the limited indexing support.

Considering the limitations of simple text search, below are some of the major requirements that need to be fulfilled for an advanced text search:

● Search should be **case insensitive**.

● **User-entered search terms** will be **transformed into the query** and the result should return to the user.

● Words in the query should **correspond variants** i.e. if a user searches for ‘shirts’ all the results having the word ‘shirt’ should also appear in the search results.

Let’s have a look at how a simple text search works:

###  **Step 1: Create a Table and Insert Values**

Let's create a database table named “search” and insert some values in it, we will write the following query:
    
    
    CREATE TABLE search(documents TEXT);
     INSERT INTO search(documents)
      VALUES ('He eats the   cake'),
      ('What is the date?'),
      ('this wil reduce the heat'),
      ('that one t-shirt is my favourite'),
       ('I am eating the food '),
       ('He cooks the meat'),
      ('I need to buy new watch'),
      ('we all need to treat others with respect'),
      ('who else eats pie?'),
      ('I will not wait for so long'),
      ('I will eat the whole box of chocolates'),
       ('this shirt is not mine');
     SELECT * FROM search;

The above query will output the following table:

###  **Step 2: Perform a Simple Search**

Now if we perform searches with [ILIKE](<https://www.commandprompt.com/education/what-does-ilike-operator-do-in-postgresql/>), which does case-insensitive matching, It would find all the data(also called documents) that includes that specific term the user has searched for. It will also return the results that contain the term in the form of a sub-string. Let's apply this thing to the above example:
    
    
    SELECT documents, documents ILIKE '%eat%' AS matches FROM search;

The output will be:

We can clearly see that ILIKE statement has found all the data that includes the term “eat”. It will also return the results that contain “eat” as a sub-string like heat, meat, treat, etc. But we know that these searches are totally irrelevant to the search results. They are just spamming the search results.

Now to fix it up, we will write another query in order to remove spam results. Following will be the query:
    
    
    SELECT documents, documents ILIKE '% eat %' AS matches FROM search;

The output of the above query is:

Now observe that the above query has narrowed and specified the search results so much that even the term ‘eat’ is not identified by the search(in row number 1). We can fix it by specifying all the synonyms for terms with the ILIKE statements separated by **OR operators** i.e.
    
    
    SELECT documents, (documents ILIKE '%eat%' OR documents ILIKE '%eats%') AS matches FROM search;

We can clearly see that this is not a good approach to be used. This will become very complex if we start to write the same thing for each and every term. Also, **hard coding is never a good approach!**

We have seen so many limitations of simple text search, which are to be seriously considered. In the place where ordinary search fails, the full-text search appears to help.

##  **PostgreSQL Full-Text Search**

We have seen major limitations of simple text search but we don't need to worry because full-text search is a great savior. To perform full-text search on a document you need to pass that document from different stages. Let's go over them one by one.

###  **Step 1: Get the Document Ready**

PostgreSQL does not directly apply the full-text search directly to the document, that is stored in **text** data type. Instead, the document needs to be converted into a more search-optimized data type called **tsvector**. For this specific work, the **to_tsvector** function is used. The basic syntax of this function is

>  ** _to_tsvector([ config regconfig, ] document text) → tsvector_**

The **_to_tsvector_** does some processing measures on the txt of the documents. The _to_tsvector_ first breaks the document into words. These words are then mapped to one or multiple dictionaries. **_Dictionaries_** are just a mapping of words that have been normalized. These normalized forms are referred to as ** _lexemes_**. Doing this will convert words into their base words for example; happiest maps to happy and hoping maps to hope. So how it works is, if the word matches with the dictionary entry, its lexemes are added to the _tsvector_. The to_tsvector() function returns a tsvector list aligned with their positions in the document with other words like prepositions etc.

Let’s have a glance at how the to_tsvector works. We can write the query as
    
    
    SELECT to_tsvector('We are eating the best mangoes together');

The query will output the main _tsvectors_ in the string provided to the function along with their positions in the string with respect to the preposition used like “we”, “are” and “the”. The following is the result of the previously mentioned query:

This is how the _to_tsvector_ works.

Another function used is the “ **to_tsquery() function** ”. This function converts the keywords into normalized words/tokens. The below query demonstrates the working of the _to_tsquery_ function:
    
    
    SELECT to_tsquery('eating & best & mangoes & together');

The output of this query will be all the normalized words in the above-given string. The output is:

We will see how these two functions can be used together to perform the full-text search.

###  **Step 2: Perform the Full-Text Search Function**

To perform the full-text search, the _to_tsvector_ , and the _to_tsquery_ functions are used together along with the matching operator i.e. **@@**. This matching operator returns a boolean value after the execution of the word search (tsquery) against the tsvector document.

We will consider the same above-considered example to perform a full-text search on it. Let’s use the _to_tsquery_ and _to_tsvector_ functions to perform the full-text search. Consider the following query for this purpose.
    
    
    SELECT * FROM search WHERE to_tsvector(documents) @@ to_tsquery('eat');

Let’s see what the query returns. The query upon execution gives the following output:

We can see that the query has returned the documents having the term eat and where the term eat is meant as eat, not used as the prefix or suffix.

This is the way we can conduct a full-text search. We can also add some other conditions for the search results by using operators such as AND and OR operators to perform the custom search.

For example, if we want to search for the term “eat” where the term “chocolate” also comes we will write the query as
    
    
    SELECT * FROM search WHERE to_tsvector(documents) @@ to_tsquery('eat & chocolate');

The “&” is the **AND operator**. So the output of the query will only be that document where the terms eat and chocolate come together.

Similarly, we can add the **“|”** i.e. **OR operator** , **“!”** i.e. **NOT EQUAL operator** and the **“ ”** i.e. **double quotation operator** that returns the exactly same term you searched for. We can also combine all these operators to specify a custom query as per our wish.

This is the way we can conduct a full-text search effectively.

###  **Conclusion**

The pattern matching operators are provided by PostgreSQL to perform the search. But this search is a **simple search** that is done using the **LIKE** , and **ILIKE** operators. Using a simple search for the searching purpose is not a good approach so we need to perform the searching operation using the full-text search. This search returns all the possible results for the searched terms and their variants as well which was a drawback of the simple search approach. In this article, we have learned how the simple search approach works and what drawbacks this approach has while performing a search. Also, we have learned how can we use the full-text search approach for effective searching with proper implementation.

---
[View this page online](https://www.commandprompt.com/education/postgresql-full-text-search/)

---

# SELECT if String Contains a Substring Match in PostgreSQL

> SELECT if String Contains a Substring Match in PostgreSQL can be accomplished using different methods, such as LIKE and ILIKE, position(), substring(), etc.

PostgreSQL offers many data types. Strings are the most significant and most commonly used data types. Sometimes we need to search for some terms/substrings in the strings. PostgreSQL provides many approaches to find if a string contains a substring. This article comprises methods with which we can find whether a string contains a substring or not. Let’s move towards exploring these methods.

##  **SELECT if String Contains a Substring Match in PostgreSQL**

There are several ways to select if the string contains a matching sub-string. These methods are:

● Using LIKE/ILIKE Operator

● Using position() Function

● Using substring() Function

● Using Similar to regular expression

● Using POSIX regular operators

Let’s go over all these ways one by one.

###  **Method 1: Using LIKE/ILIKE Operator**

The LIKE and ILIKE operators are simple search operators. These operators are basically used to search a substring in a string or set of strings. Let's consider a table named “simplesearch” on which we will perform our matching:

The table contains different strings. We will search for some substrings in these strings. Let's see how the LIKE operator can be utilized for this purpose.

Let’s suppose we want to find a substring i.e. “ate” We will write the query for the LIKE operator as follows:
    
    
    SELECT * FROM simplesearch WHERE document LIKE '%ate%';

The table simplesearch contains a column “document” where we have to search the substring. There are two wild cards that are used in this method:

● The percentage sign “ **%** ” - matches the set of characters

● The underscore sign “ **_** ” - matches a character.

The matching is done using the wildcards and the values are returned accordingly.

So the LIKE operator searches for the substring “ate” in the document list and returns those strings in which it is present.

The output for the above query is:

In a similar way, the ILIKE operator works. The only difference is ILIKE operator does case-insensitive matching. Now if we search for the substring “AtE”, we will get the same result because the operator being used is the ILIKE operator which does not care about the case. The query can be written as
    
    
    SELECT * FROM simplesearch WHERE document ILIKE '%AtE%';

The query will return the following output:

This is how we can find out if the string contains the specified substring and also get those strings containing the substring.

###  **Method 2: Using Position() Function**

The position() function is also a good alternative to find if the string contains a substring or not. The basic syntax of this function is given as
    
    
    SELECT POSITION(Sub_string IN String);

The function returns the number that shows the location of the substring in the string, 0 if the substring is not present, and NULL if any of the arguments is NULL.

Let’s query the position() function for our case:
    
    
    SELECT * FROM simplesearch WHERE position('ate' in document) > 0;

The above query will select if the strings in the simplesearch table contain a substring “ate”. Following is the output returned by the query:

In this particular way, we can get the strings containing our specified substring.

###  **Method 3: Using Similar to Regular Expression**

The similar expression works the same as the LIKE operator. The only difference in both these is that the “similar to” expression interprets the pattern using SQL standards. This is also a good way to get the strings containing specified substrings. We can write the query as:
    
    
    SELECT * FROM simplesearch WHERE document SIMILAR TO '%ate%'

We have specified the substring and we are selecting the document(the rows that contain the strings) that are similar to the substring. The output is given as

This is a simple and effective way to do this particular task.

###  **Method 4: Using Substring() Function**

The substring() function can also be used to get the string if the specified sub-string is contained in the string. The substring() function returns the strings that contain our specified substring or are similar to that substring. Following will be a query for our case:
    
    
    SELECT * FROM simplesearch 
    WHERE document ~~ substring(document SIMILAR '%ate%' ESCAPE '#')

The substring() function will return all the strings that contain the “ate” substring or are similar to the “ate” substring. The returned result of the substring function is matched with the document, column that contains all the strings, using the **~~ operator** , and if they both match, the string is selected from the table and returned.

The output for the above query is:

So this is how we can select the string if it contains the specified substring.

###  **Method 5: Using POSIX Expression**

The POSIX expression such as Regexp_match() can be used for this purpose. The regexp_match() expression takes in the string and the substring as arguments and returns the matched substring.

We can write the following query for the POSIX expression:
    
    
    SELECT regexp_match('The United   States of America', '..ate.')

This will result in the text that shows whether the string contains the substring or not. The output is given as:

So this is how we can use all the above functions to select if the string contains a substring Match in PostgreSQL.

###  **Conclusion**

We can select if the string contains our specified substring in Postgres by using the five methods that we have discussed above. The first way is by using simple search operators such as the **LIKE and ILIKE** operators. The second way is by using the **position()** function, thirdly it's the **substring()** function that we can use for this purpose. Another expression named “ **similar to** ” can be used and lastly, it's the POSIX expression such as **regexp_match()** that can be used to select the string if it contains a substring match.

---
[View this page online](https://www.commandprompt.com/education/select-if-string-contains-a-substring-match-in-postgresql/)

---

# UNION Vs INTERSECT Vs EXCEPT: What's the Difference

> In Postgres, the UNION, INTERSECT, and EXCEPT are the set operators that are applied on at least two tables to get a specific combined result.

There are some set operators that are offered by PostgreSQL. The most common set operators offered by PostgreSQL are **UNION** , **INTERSECT** , and **EXCEPT**. These operators are widely used when we want to combine the resultant output of two or more tables. In this post, we will be understanding these operators and discussing the difference between UNION, INTERSECT, and the EXCEPT operator. So let’s get started.

##  **UNION vs. INTERSECT vs. EXCEPT: What 's the Difference?**

Before moving on to the functioning and the differences between these operators, let’s have a quick glimpse at the rules for these set operations:

● The number of columns for the result set must be equal for all the queries.

● The data types must be the same or at least they should be compatible with each other.

Another point to note is that we can always sort the result according to our wish by using the ORDER BY clause.

Now let’s see how these set operators work.

###  **UNION Set Operator**

 **The** [UNION operator](<https://www.commandprompt.com/education/postgresql-union-all-operator-with-examples/>) **combines the resulting output set of two or multiple SELECT queries.** The resultant/output set of two SELECT queries is merged and returned. Note that in UNION, there is no duplication of records. Let's see the workings of the UNION set operator.

Consider the two tables. The first table is named “test_scores” and contains the record of candidate and their scores who appeared in an entrance test. The table is given as:

Another table contains the list of candidates who passed the entrance test and were successful in getting admission. The table is named “passed_candidates”. The table is as follows:

Now if we apply the UNION operator on both tables the query will be:
    
    
    SELECT candidate_name
     FROM test_scores
     UNION
     SELECT candidate_name
     FROM passed_candidates;

The query will give the table containing the combined result sets from both tables. In easy words, the query will give a table containing all the entries from both tables. Since in my case, all the entries of the second table are present in the first table it will return no extra entry than the first table. The output is:

We can see that all the entries of the second table are present in the first table all the union operator results in all the entries but no entry is duplicated. The duplication of entries happens in UNION ALL. It works the same as the UNION operator the only difference is it returns all the merged entries that may be duplicated.

So this is how the UNION operator works; we will now see how INTERSECT is different.

###  **INTERSECT Set Operator**

 **The** [INTERSECT set operator](<https://www.commandprompt.com/education/postgresql-intersect-operator-with-examples/>) **gives a combined table containing the common entries from at least two specified tables.** In our considered case, if we apply the INTERSECT operator between the two tables, it will give the entries that are common in both tables i.e. the candidates who have passed the entrance test. The query for the INTERSECT operator looks like this:
    
    
    SELECT candidate_name
     FROM test_scores
     INTERSECT
     SELECT candidate_name
     FROM passed_candidates;

In the above query, the INTERSECT operator will return the table having the entries common in both the specified tables like this:

We can see that the table only contains those entries that were common in both tables.

Let’s see how the EXCEPT operator is different from both these set operators.

###  **EXCEPT Set Operator**

The [EXCEPT set operator](<https://www.commandprompt.com/education/how-to-use-except-operator-in-postgresql/>) compares the resultant set of both the SELECT statements and returns all those data entries that are present in the resultant set of the first SELECT query but are absent in the second SELECT statement. Let’s query the EXCEPT operator:
    
    
    SELECT candidate_name
     FROM test_scores
     EXCEPT
     SELECT candidate_name
     FROM passed_candidates;

The above query will return all those entries that are present in the first table i.e.”test_scores” but are absent in the second table i.e. ”passed_candidates”. The query returns the following output:

The above output advocated the working of EXCEPT operator. The query has returned all those values that were present in the “test_scores” but not in “passed_candidates” i.e. the query has returned all those names of candidates who did not clear the entrance test.

###  **Conclusion**

The UNION, INTERSECT, and EXCEPT are the set operators that are applied on at least two tables to get a specific combined result. The UNION operator combines the result of two or multiple SELECT statements. The INTERSECT set operator gives a combined table containing the common entries from at least two specified tables and the EXCEPT set operator compares the resultant sets of both the SELECT statements and returns the entries that are present in the resultant set of the first SELECT query but absent in the second SELECT query. The content of this article demonstrated all these set operators and their differences using practical examples.

---
[View this page online](https://www.commandprompt.com/education/union-vs-intersect-vs-except-whats-the-difference/)

---

# What Does the UPDATE ... FROM Statement Do in PostgreSQL

> In PostgreSQL, the UPDATE FROM statement is used to update the data/row of any table according to the data of another table.

PostgreSQL provides us with many statements using which we can write our queries to get the desired kind of data from the database tables. Using these statements, we can manipulate and also extract the database data. For example, we can fetch data using the SELECT query while the UPDATE query is used to manipulate the existing data into the newly provided data.

The content of this post covers the concepts of the UPDATE FROM statement. The **UPDATE FROM** statement is used to update table data according to some other table data. Let’s learn about this command in detail.

##  **What Does the UPDATE ... FROM Statement Do in PostgreSQL?**

The **UPDATE FROM** statement is used to update the data/row of any table according to the data of another table. For example, if we want the test scores of candidates to reflect on the attendance list as well, we can get the data from the “test_scores” table and update the “attendance_list” table.

The “attendance_list” table is given as follows:

The “test_scores” table looks like this:

Now if we want to add the scores of each candidate on the attendance list as well we can make use of the **UPDATE FROM** statement. The basic syntax for an UPDATE FROM statement can be written as:
    
    
    UPDATE tab_name
     SET
      col_name1 = val1,
      col_name2 = val2,
      ...
     FROM second_table[, ...]
     WHERE cond
       [RETURNING expr];

In the above syntax:

● We first need to specify the name of the table which needs to be updated after the **UPDATE** statement.

● We need to set the values of the columns that will be updated.

● After the **FROM** statement, we will specify the name of the second table, the table according to which we want to update the values.

● We can write the condition after the **WHERE** clause that needs to be fulfilled for the updation to happen.

● At last, you can write the returning clause to get the resulting data of the query.

For the scenario we discussed above, the query can be written as:
    
    
    UPDATE attendance_list a
     SET st_name = st_name || ' got ' || b.candidate_score
     FROM test_scores b
     WHERE a.st_name = b.candidate_name
     RETURNING st_id,st_name;

In this query:

● We have specified that the “ **attendance_list** ” has to be updated.

● The “st_name” column from “attendance_list” is set in a way that the student name will be concatenated with the “candidate_score” from the “ **test_scores** ” table.

● The concatenation is done by the “ **||** ” **operator** and the ‘ **got** ’ string.

● This is going to happen when the “st_name” from the attendance_list table is equal to the “candidate_name” from the test_scores table. This means that the score of each candidate is appended with its own name. This is the whole condition specified after the **WHERE** clause.

Now let’s see what this query returns.

In the above output, we can clearly see that the table “attendance_list” has been updated the same as the query was defined. The scores of each candidate are appended with the name using the ‘ got ’ string.

This is how we can update a table's data according to another table.

###  **Conclusion**

We can Update an existing table according to another table present in the database by making use of the UPDATE FROM clause. We need to specify the target table where the updation will take place after the UPDATE clause and the table according to which the update takes place is specified after FROM. This article demonstrated the working of the **UPDATE FROM** statement in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/what-does-the-update-from-statement-do-in-postgresql/)

---

# How to Comment Characters in psql

> Commenting on the special character in psql may be a problem sometimes. To avoid errors we can use different methods, such as \echo, \warn, “\\” separator, etc…

In order to bring the proper clarity and to make the code readable, comments are added to the code. Comments are added by the developer or the programmer of the code to make it understandable for everyone. We also usually use comments in the psql so that the queries and commands are more understandable.

We can simply comment in the psql by using “--” for one line code and “\\* and */” for multiliner code. But what if we wish to add/insert some special characters to the code? How can they be commented so that they are correctly interpreted by the SQL Shell? Let’s get started with the article to find the answer to all these queries.

##  **How to Comment Characters in SQL Shell (psql)?**

Comments are ignored by the psql for the query execution. These comments are only written by the programmer to make the queries understandable. If we want to write a single-line comment, it will be written as follows:
    
    
    -- This is a Command Prompt --single line comment--

For the multi-line comment, we write them as:
    
    
    /* This is Command prompt &&
      This is an example of multiple lines comments */

We can see that in both the above syntaxes, special characters are part of the comment. This thing works perfectly in the pgAdmin or any other GUI-based platform that works on PostgreSQL.

But these might cause some problems in CLIs like psql. Let’s see how commenting in this way can be an issue in psql.

Let’s consider the following query:
    
    
    SELECT * FROM test_scores; -- select the table

In the above code block, we have written a query to select the table name “test_scores”. We have also added a single-line comment with it. This query will work fine i.e. ignore the comment for the query execution. The output looks like this:

The comments work well for queries like these but if we write the queries or meta-commands with a slash, the queries return an error. Consider the following example to understand this concept better:
    
    
    \dt -- display tables

It gives an error in the output that:

This does not only happen in the case of the “dt” command. In the case of any meta-command, starting with a slash would similarly result in an error.

This issue can be resolved in the following ways:

###  **Method 1: Running the Comment Before the Query**

To resolve the above issue, we can run the comment before the query rather than running it or writing it above the query. Since the comments are only meant to show what is happening in the code and to add some clarity. We can implement this method like this:
    
    
    postgres=# -- display tables!
    postgres=# \dt

Now the query will execute perfectly fine.

So in this way, we can handle this case.

###  **Method 2: Using \ECHO**

The “\echo” command is used to print the statement specified after it on the psql. We can use this meta-command to make comments in the psql. This method can be implemented like this:
    
    
    \dt \echo display_all_the_tables!

This method will also work fine. The query will also run as it is meant to be and the comment is also added without causing any problem in it.

In this way, we have printed the comment using the \echo command.

###  **Method 3: Using \WARN**

Another way to comment characters in psql is using the \warn command. This approach is almost similar to the one given above. The \warn meta-command warns or prints some error. This method can be implemented like this:
    
    
    \dt \warn display_the_table!

This query will return the following output on the psql:

The warning is printed after the execution of the command as a comment.

###  **Method 4: Using \\\ and - -**

In this method, we first write out the query then we add a separator i.e. “\\\”, and then we will write the comment using - -. The query and the comment are separated by the separator. The comment in this case is not printed as an output of executing the query. Let’s implement this method.

This is how this method is implemented.

###  **Method 5: Using COMMENT Command**

The last and one of the effective methods used to comment in psql is by utilizing the COMMENT command. This command is used to comment on specific database objects we can use this command to comment on the table like this:
    
    
    COMMENT on table test_scores is 'Amazing Results!';

Executing this command will give the following output:

Now to see the comment we will execute the command to display the table in its detailed form. The query is “ **\d+** ”. This query will show us the comment i.e.

We can see that the comment has been added to the table as a description.

So these all are the methods we can use for commenting the special characters in psql that may be brought into use as per our needs.

###  **Conclusion**

Commenting on the special character in psql may be a problem sometimes. To avoid errors we can use different methods. The first one is by “running the comment before the query” to avoid the error. To add comments we can also use **\echo** and **\warn** commands, these commands print the comment. The third method is to separate the query/command and the comment using the **“\\\”** separator. Lastly, we can comment on some specific database objects using the COMMENT command. This article has covered all the methods in detail with practical implementation.

---
[View this page online](https://www.commandprompt.com/education/how-to-comment-characters-in-psql/)

---

# How to Fix “window function nth_value requires an OVER clause” in Postgres

> In PostgreSQL, the error “window function nth_value requires an OVER clause” occurs when the OVER clause is not specified in the query.

PostgreSQL provides a list of window functions that are operated on the set of rows. One of the most significant window functions that is usually used is the **NTH_VALUE() function**. This function is widely used to get a particular value at a specific location/position. The most important application of this function is getting the specified positioned data from ordered data and partitioned data.

For example, we can get the 3rd value from the candidate marks data ordered in descending order. If the data is partitioned by the genders i.e. Male and female, by getting the 3rd value we will get the data for the candidate securing the 3rd position in both the gender categories.

While working with the **NTH_VALUE()** function we usually encounter the **“window function nth_value requires an OVER clause”**. In the following topic, the reason for this error is discussed, and the way we can fix it is provided.

##  **How to Resolve the “window function nth_value requires an OVER clause” Error in PostgreSQL?**

This error arises when we are using the NTH_VALUE() function **without querying an OVER statement**. For most of the window functions and here specifically for the NTH_VALUE() function, the **OVER clause is necessary for the proper execution**.

Let’s have a look at the query we are trying to run to find the 3rd value from the table named “test_scores”:
    
    
    SELECT *, NTH_VALUE (candidate_score,3) 
    FROM test_scores;

The above query results in an error:

Now here we can see that we have not specified any OVER clause. This error can be resolved by adding an OVER clause. Let’s try to fix the issue using the OVER clause.
    
    
    SELECT *, NTH_VALUE (candidate_score,3) 
     OVER (
     ORDER BY candidate_score DESC 
     RANGE BETWEEN UNBOUNDED PRECEDING AND 
     UNBOUNDED FOLLOWING
     ) AS third_position
     FROM test_scores;

We have added an OVER clause in which we are ordering the candidate scores in descending order. Now we will see if the NTH_VALUE() function is working fine or not. The output of the above query is:

We can see that the NTH_VALUE() function is running fine now. So this is how we resolve this error.

###  **Conclusion**

The error **“window function nth_value requires an OVER clause”** occurs when the **OVER** clause is not specified in the query. The NTH_VALUE() function and some other window functions require the OVER clause for their proper execution. In this article, we have fixed the “window function nth_value requires an OVER clause” for the NTH_VALUE() function by adding the OVER statement in the query.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-window-function-nth_value-requires-an-over-clause-in-postgres/)

---

# How to Drop a Custom/User-Defined Type in PostgreSQL

> In PostgreSQL, an already existing user-defined data type that is no longer in our use can be dropped by using the DROP TYPE IF EXISTS statement.

Data types are mandatory to define the column types while creating a Postgres table. PostgreSQL offers many built-in data types. However, we can also create custom data types to use them where needed. We can also discard the user-defined data types that already exist and are no longer in use. In this article, we will learn how to drop a user-defined data type in PostgreSQL. So let’s get started.

##  **How to Drop a Custom/User-Defined Type in PostgreSQL?**

We can drop the custom data type by simply using the **DROP** [DDL command](<https://www.commandprompt.com/education/postgresql-data-definition-language-ddl/>) of PostgreSQL. The basic syntax to drop any user-defined data type is:
    
    
    DROP TYPE IF EXISTS user_def_type_name;

We simply need to write the name of the user-defined data type that we want to delete/drop. The command used is **DROP TYPE IF EXIST** , this command simply drops the type if it exists otherwise it won’t return an error, unlike the simple DROP TYPE command. Let’s learn about dropping a type with the help of an example.

 **Example 1: Dropping a Custom/User-Defined Type in PostgreSQL**

The user-defined data type name “ **solar_system** ” is already created in my database which can be seen under the “Types” section.

Let’s try to drop it using the DROP TYPE statement. The query for this looks like:
    
    
    DROP TYPE IF EXISTS solar_system;

The query will simply drop the solar_system type that is created by the user itself.

We can see that the user-defined data type has been dropped.

 **Example 2: Dropping a Non-Existing Custom/User-Defined Type in PostgreSQL**

Now if we try to drop a type that does not exist using the DROP TYPE IF EXISTS statement, the query will raise a notice instead of showing an error. Let’s try deleting a type “non_existing_type” that does not exist.
    
    
    DROP TYPE IF EXISTS non_existing_type;

The output of this query is:

We can see that a notice is raised instead of throwing an error and then ships the statement as the custom_type does not exist.

 **Example 3: Dropping a Custom/User-Defined Type Forcibly in PostgreSQL**

The user-defined data type name “ **scholarship_details** ” is already created in my database which can be seen under the “Types” section.

Let’s try to discard it using the DROP TYPE statement. The query for this looks like:
    
    
    DROP TYPE IF EXISTS scholarship_details;

The above query is responsible for dropping the user-defined data type named “scholarship_details” but after the execution of this query, we see that the **query throws an error**. The error is:

The error shows that the type “scholarship_details” is in use by some object. So if we really want to drop this type we will forcibly apply the DROP statement on it. This can be done by using the **CASCADE** keyword. This always drops the object forcibly even if this is used by some object. The query will be manipulated like this:
    
    
    DROP TYPE IF EXISTS scholarship_details CASCADE;

This query will drop the user-defined data type even if it is used by some object. The query will look like this:

The above query has dropped the user-defined data type successfully. We can verify this by executing the “\dT” in psql or looking for the name of the type in the side panel of the pgAdmin under the option of “Types”. We will see that the user-defined data type will no longer be present under it like this:

We can see that our defined data type is no longer present. This ensures the deletion of the data type we defined.

###  **Conclusion**

We can drop the already existing user-defined data type that is no longer in our use by using the **DROP TYPE IF EXISTS** clause. This statement deletes the user-defined data type if it exists, if not it will not throw an error. If that data type is already in use by some objects in the database, then we have to add a **CASCADE** keyword at the end of the query to forcibly drop the type. In this write-up, we have learned to delete the custom data types in PostgreSQL with valid execution.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-customuser-defined-type-in-postgresql/)

---

# How to Use DISTINCT ON Expression in Postgres

> In PostgreSQL, the DISTINCT ON clause works similarly to the DISTINCT clause as it returns the unique records of data after discarding the duplicate records.

A commonly used expression in Postgres is the **DISTINCT** expression. The DISTINCT clause is used to remove duplicate/same Postgres rows from the table. The **DISTINCT ON** clause works the same as the **DISTINCT** clause; the only difference is that the DISTINCT ON clause keeps the very first record of the duplicated records.

This write-up demonstrates the use of the **DISTINCT ON** expression in PostgreSQL.

##  **How to Use DISTINCT ON Expression in Postgres?**

We can discard all the identical/duplicate rows from a database table by making use of the **DISTINCT** and **DISTINCT ON** expressions. The DISTINCT operator removes the duplicated rows from a database record in addition to this the DISTINCT On keeps the first row/record and discards the duplicated ones. The basic syntax of the expression is:
    
    
    SELECT DISTINCT ON col_1, col_2 
     FROM tab_name
     ORDER BY col_1, col_2;

In the above syntax:

● The columns in which we want to remove the duplicated records are specified after the **DISTINCT** **ON** keyword.

● The table’s name is written after the **FROM** keyword.

● The columns are ordered.

● We can also add some optional conditions in the query.

To get clarity on the concepts, let’s move towards an example.

 **Example: DISTINCT ON Expression in PostgreSQL**

Let's create a table named “Students_marks” having data redundancy as the students attempted an online test multiple times:
    
    
    CREATE TABLE Students_marks (
    Student_id SERIAL PRIMARY KEY,
    Student_name VARCHAR(100) NOT NULL,
    Test_marks DOUBLE PRECISION NOT NULL
    );

Inserting the values in the table:
    
    
    INSERT INTO Students_marks (student_name, Test_marks) VALUES
      ('Katherine', 7.25),
      ('Williams', 2.50),
      ('Alex', 5.00),
      ('John', 7.25),
      ('Smith', 2.50),
      ('Alex', 8.00),
      ('Smith', 8.50),
      ('Peter', 9.00),
      ('John', 7.25),
      ('Katherine', 9.50);

The resultant table will be:

Now we can see that the names of the students are repeated multiple times. So in order to discard the redundant data and keep the marks of the students for their first attempt we will make use of the DISTINCT ON clause. The query for this use case will look like this:
    
    
    SELECT
      DISTINCT ON
      (student_name)student_name, Test_marks
     FROM
      Students_marks
     ORDER BY student_name, Test_marks;

In the above code:

● We have used the DISTINCT ON expression to remove the redundant entries from the column ”student_name” of the table “students_marks”.

● We have ordered the data by the student_names and test_marks.

The query returns the table with the unique entities from the column “student_names” giving us the first records for each student in the table and the names of students ordered in alphabetical order. The output looks like this:

We can observe that the names of students are ordered in alphabetical order and the first attempt marks for every student are returned in the table.

This was all about the working of **DISTINCT ON** expression.

###  **Conclusion**

The **DISTINCT ON** clause works similarly to the **DISTINCT** clause as it returns the unique records of data after discarding the duplicate records. In addition to this, the DISTINCT ON expression returns the first record from the set of redundant data. In this article, we have learned about the DISTINCT ON expression in detail with the help of a practical example.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-distinct-on-expression-in-postgres/)

---

# How to Use TIMETZ (Time With Time Zone) Data Type in PostgreSQL

> The TIMETZ data type stores the time information with the timezone. This data type is used to store the data where the timezone is considered to be important.

PostgreSQL offers many time and date data types to store this kind of data in the required and accurate format. There are several variants of DateTime data types that PostgreSQL provides. Sometimes we store the time as a simple time, sometimes we need to store it as a timestamp, sometimes it has to be the time with a time zone, and sometimes without a time zone. This article revolves around a data type that stores time with time zones. This type is the TIMETZ data type.

##  **How to Use TIMETZ (Time With Time Zone) Data Type in PostgreSQL?**

Users can store information about time along with the time zone using the TIMETZ data type in PostgreSQL. The format of this data type works similarly to the time data type but additionally, the TIMETZ also specifies the time zone. The basic syntax for this data type is:
    
    
    name_of_time_variable TIMETZ;

The data type declared with this data type will store the time along with the zone information.

Let’s see how to use the TIMETZ data types in PostgreSQL.

 **Example: How To Use the Timetz Data Types In PostgreSQL**

Let’s construct a time named “job_timings” containing the schedule of duty timing of different persons working in a company at different times. The query can be written as:
    
    
    CREATE TABLE job_timings (  
      id SERIAL PRIMARY KEY,
      job_start_time TIMETZ NOT NULL,
      job_timezone TEXT NOT NULL
       );

We have defined the “job_start_time” as the TIMETZ data type. After the successful creation of the table, we will be inserting some data into the table using the following query:
    
    
    INSERT INTO job_timings(job_start_time, job_timezone) VALUES
       ('07:30:00-05:00', 'America/Los_Angeles'),
       ('10:00:00+01:00', 'Europe/Paris'),
       ('06:00:00+08:00', 'Asia/Shanghai');

Executing the above query will successfully insert the values in the table which can be verified by following output:

Now, if we select the table to see the values, we will run the following query:
    
    
    SELECT * FROM job_timings;

The output is:

In the above output, you can note the data type of the “job_start_time” is time with time zone because it was defined as TIMETZ data type.

So this is how the TIMETZ data type can be used in Postgres.

###  **Conclusion**

The **TIMETZ** data type stores the time information with the timezone. This data type is used to store the data where the timezone is considered to be important. In this article, we have seen why the TIMETZ data type is used and how is it used in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-timetz-time-with-time-zone-data-type-in-postgresql/)

---

# How to Create a User-Defined Data Type in PostgreSQL

> To Create a user-defined data type in PostgreSQL, users can use either the CREATE DOMAIN statement or the CREATE TYPE statement.

We always need to define the data types while creating objects in the PostgreSQL database. These are usually built-in data types in PostgreSQL. Sometimes we have to define the data types of our choice. For this purpose, the user-defined data types can be created in two ways. The first approach is by using the **CREATE DOMAIN** and the second approach used is the **CREATE TYPE** clause. In this tutorial, we will demonstrate the ways to create user-defined data types. So let’s get started.

##  **How to Create a User-Defined Data Type in PostgreSQL?**

The **CREATE DOMAIN** is used to define user-defined data types with constraints like NOT NULL, CHECK, etc., and the **CREATE TYPE** is used to create composite type data types which are utilized to determine the structure of complex data objects. It is mostly utilized in a stored procedure as per the data type of the returned value. Let’s discuss both methods one by one.

###  **Using CREATE DOMAIN Clause to Create a User-Defined Data Type in Postgres**

We can create a user-defined data type using a **CREATE DOMAIN** clause. The domain is a data type having a unique name in the schema scope and it contains some constraints like NOT NULL, check, etc. The domain is usually utilized for centralizing the management of some attributes/fields having some common property. Let’s discuss the topic using an example to bring more clarity to it.

 **Example: Using CREATE DOMAIN Clause to Create a User-Defined Data Type**

Consider if we create a table named “merit_scholarship” containing the data for students getting the scholarship. Now if we make two separate columns for name i.e. first name and second name. Both of these fields are not allowed to contain a NULL and a space. The query for this case can be written as:
    
    
    CREATE TABLE merit_scholarship(
      id SERIAL PRIMARY KEY,
      fname VARCHAR NOT NULL,
      lname VARCHAR NOT NULL,
      scholarship_amount integer,
      CHECK (
      fname !~ '\s'
      AND lname !~ '\s'
      )
       );

In the above query, we have defined all the columns in the table. We have also defined a check constraint that says that the first name i.e. fname and the last name i.e. lname both do not contain spaces. Moreover, where they are defined they say that they can not be NULL. the user can do so by another approach. Instead of a CHECK constraint, we can create a DOMAIN named “student_full_name”, which will do the same thing i.e. it will not contain the NULL and spaces. The query for the domain is written as:
    
    
    CREATE DOMAIN student_full_name AS 
     VARCHAR NOT NULL CHECK (value !~ '\s');

The execution of the query will result in the successful creation of DOMAIN which can be ensured by the following output:

We have created a domain instead of the CHECK constraint in the table, we will simply remove the CHECK constraint from the table. The query will become:
    
    
    CREATE TABLE merit_scholarship(
    id SERIAL PRIMARY KEY,
    fname student_full_name,
    lname student_full_name,
    scholarship_amount integer
    );

We have defined the data type of the fname and lname fields as domains that we define ourselves. A table will be created as a result of this query like this:

Now we will insert values into the table with the **space** to see what happens. The query for inserting the values is:
    
    
    INSERT INTO merit_scholarship(fname, lname,scholarship_amount)
    VALUES('Katherine S','Smith', 40085.9);

We can see that the data we want to insert in the fname field contains a space between two letters so the query will definitely throw an error like this:

The error clearly shows that we have violated the conditions defined for the “student_full_name”. Let’s see if it works fine after removing the space:
    
    
    INSERT INTO merit_scholarship(fname, lname,scholarship_amount)
    VALUES('Katherine','Smith', 40085.9)

The output is:

We can see that the values have been successfully inserted into the table if they satisfy the applied checks to the domain. We can see all the domains present in the system by running the “\dD” meta-command in psql. Otherwise, we can simply see all the domains in the side panel of the pgAdmin 4 under the domain options:

This is how we can create User-defined data types using the CREATE DOMAIN clause and by implementing the above method.

We have another method to create user-defined types; let’s see how can we do the same with the other method.

###  **Using CREATE TYPE Clause to Create a User-Defined Data Type in PostgreSQL**

The **CREATE TYPE** creates a composite type and this composite type can be declared as the return type of a function. Let’s take the help of an example to understand the concept clearly.

 **Example: Using CREATE TYPE Clause to Create a User-Defined Data Type**

Let’s suppose we write a function to get the id, name, and scholarship amount for a student, we can use the CREATE TYPE data type. We can first create a user-defined data type using the CREATE TYPE then we will use it in function to return value. The query for the data type creation is:
    
    
    CREATE TYPE scholarship_details AS (
     Student_id INT,
     Student_name VARCHAR,
     Scholarship_amount DOUBLE PRECISION
     );

The query will create a type. The output will be:

Now if we want to use this data type in the function, we will have to create the function and use it in the function. We can write the query for this as:
    
    
    CREATE OR REPLACE FUNCTION get_scholarship_details (s_id INT) 
      RETURNS scholarship_details AS 
       $$ 
     SELECT
      Student_id,
      Student_name,
      Scholarship_amount
     FROM
      Students_scholarships
     WHERE
      Student_id = s_id ; 
       $$ 
       LANGUAGE SQL;

In the above function, we have declared the returned type of the function to be the user-defined data type i.e. scholarship_details. The function retrieves the scholarship details for students from the table name “Students_scholarships”.

The execution of this query will ensure the creation of the function by the following output:

Now if we want to get the scholarship details of the student with student ID 2, we will write the following query:
    
    
    SELECT * FROM get_scholarship_details(2);

We can see the creation of data types by executing the “\dT” in psql and also in the side panel of pgAdmin under the option of “Types” like this:

These were the two methods to create a user-defined data type in PostgreSQL.

 **Conclusion**

Postgres supports the creation of user-defined data types using two different ways. The first way to create a user-defined data type is by utilizing the **CREATE DOMAIN** statement and the second way is by using the **CREATE TYPE** commands. In this blog, we have discussed both methods in detail with the help of proper implementation to bring clarity to the topic.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-user-defined-data-type-in-postgresql/)

---

# What Does json_extract_path() Function Do in PostgreSQL

> The json_extract_path() function is a JSON function that is used to extract the values from the JSON data. The path of the values that are to be fetched is spe…

The data in PostgreSQL is stored in the form of a table. The stored data can be of any valid data type including **JSON**. This data type stores the values as key-value pairs. PostgreSQL provides many functions to retrieve the data from JSON columns. One of the most significant functions used to retrieve nested values from JSON values using its path is the _“_ ** _json_extract_path()_** _”_ function. The content of this post will be the json_extract_path() function and its functioning. So let’s get started with the post to learn more about this function.

##  **What Does json_extract_path() Function Do in PostgreSQL?**

The PostgreSQL JSON function named the “json_extract_path()” fetches the nest JSON value from the JSON data on the basis of the path specified. The basic syntax of this function is:
    
    
    json_extract_path(json_value JSON, VARIADIC Path TEXT[])

In the above syntax:

● The **“json_extract_path()”** function takes in 2 parameters.

● The first parameter i.e. **“json_value”** is the JSON value from which we will extract the nested value.

● The second parameter i.e. **“VARIADIC Path TEXT[]”** specifies the variadic list which illustrates the path of the value to extract.

The function will return the **JSON value** pointed out by the specified path from the “json_value” and will return **NULL** if no valid path is found.

We will discuss the topic with the help of examples to bring more clarity.

 **Example 1: The json_extract_path() Function in PostgreSQL**

Below is an example to show the working of the json_extract_path() function in PostgreSQL and how the values are retrieved from the JSON array at the specified path. Consider the following query:
    
    
    SELECT
      json_extract_path('["John", "Alex", ["Cate", "Smith"]]', '0') AS value_1,
      json_extract_path('["John", "Alex", ["Cate", "Smith"]]', '1') AS value_2,
      json_extract_path('["John", "Alex", ["Cate", "Smith"]]', '2') AS value_3;

In the above queries:

● We have specified the JSON values as **“[ "John", "Alex", ["Cate", "Smith"]]”** and the second parameter is the path or index(in this case). So for the first query, the function json_extract_path() function extracts the value at the **0th index** in the JSON value i.e. ** "John**".

● For the second query, the function json_extract_path() function extracts the value at the **index 1** in the JSON value i.e. **" Alex"**.

● For the third query, the function json_extract_path() function extracts the value at the **index 2** in the JSON value i.e. **[ "Cate", "Smith"]** array.

The query will return these outputs. You can see the output below:

We have seen that the last query has returned a nested array at index 2. We will get the individual nested values of that JSON array as well. The query for this can be written as:
    
    
    SELECT
     json_extract_path('["John", "Alex", ["Cate", "Smith"]]', '2','0') AS   nested_value_1,
     json_extract_path('["John", "Alex", ["Cate", "Smith"]]', '2','1') AS   nested_value_2;

By executing the query, we will get to know that the output will be as per expectations as it is returning the nested values. The output is given as:

So this is how we can get nested values from JSON nested arrays.

Let’s consider another example.

 **Example 2: JSON Object**

This example will illustrate how we can get a value from the JSON object at a specific path. The example contains the information of a customer, it contains details about the customer id, products, and their quantity present in the cart. Consider the following query:
    
    
    SELECT
      json_extract_path('{"customer_id": 1, "cart_products": {"apple": 2, "pear": 3}}', 'customer_id') AS customer_id,
      json_extract_path('{"customer_id": 1, "cart_products": {"apple": 2, "pear": 3}}', 'cart_products') AS cart_products;

The above query gives the expected results which can be shown in the following output:

We can see that the query has given the JSON values at the specified path. In this case, we can get the nested values as well, as we have done in the above example. Consider the following query for this purpose:
    
    
    SELECT
      json_extract_path
      ('{"customer_id": 1, "cart_products": {"apple": 2, "pear": 3}}', 'cart_products','apple')
      AS customer_id,
      json_extract_path
      ('{"customer_id": 1, "cart_products": {"apple": 2, "pear": 3}}', 'cart_products','pear') 
      AS cart_products;

The query will give the nested values from the nested JSON array. The output will be:

This is how we can use the **json_extract_path()** function to fetch the JSON values from JSON objects.

 **Conclusion**

The **json_extract_path()** function is a JSON function that is used to extract the values from the JSON data. The path of the values that are to be fetched is specified as an argument in the function. In this article, we have seen what a **json_extract_path()** function actually does in PostgreSQL and how we can get JSON values and nested JSON values using this function with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/what-does-json_extract_path-function-do-in-postgresql/)

---

# How to Use WHERE Clause With Arrays in PostgreSQL?

> Arrays are among the most commonly used data types in Postgres. In Postgres, the WHERE clause is used with arrays to get and update the records as per users re…

PostgreSQL offers many data types among which the arrays are very significant. This data type is a variable-size data type, offering a variable length and multiple dimensions. An array can be built-in data type or user-defined data type, we can declare any kind of array as per our need. Moreover, Postgres allows us to define table columns using the array data type.

In this article, we will learn how to use the WHERE clause with arrays.

##  **How to Use WHERE Clause With Arrays in PostgreSQL?**

In PostgreSQL, we can retrieve either the entire data or partial data of any array-type column using a SELECT query. Specifically, if we want to fetch partial data from an array-type column, we use the **WHERE** clause. The basic syntax to perform this specific function is:
    
    
    SELECT col_name_1, col_name_2,... column_N 
    FROM tab_name 
    WHERE cond;

In the above syntax:

● The **SELECT** statement extends the names of columns that we want to get in return for the query.

● After the **FROM** keyword, the name of the table is specified.

● After the **WHERE** clause, the condition is given which needs to be fulfilled and only those records are returned which fulfill this condition.

###  **Example 1: Using WHERE Clause With Arrays**

To use the WHERE clause with the arrays we first need to create a table using the array data type. Follow the steps to use the WHERE clause with arrays in PostgreSQL.

###  **Step 1: Create a Table Using Array Data Type**

We will create a table named **“projects”** using the array data types. The query will be:
    
    
    CREATE TABLE projects(proj_id serial PRIMARY KEY, proj_name varchar (100),proj_status varchar []);

The stated query successfully creates a table in the database.

###  **Step 2: Insert Values in the Table**

The next step is to insert the values in the table so that they can be retrieved. The query can be written as:
    
    
    INSERT INTO projects(proj_name, proj_status) 
     VALUES('Mobile App', '{"Completed","Tested","pending"}'),
     ('Game App', '{"Pending","TO-DO"}'),
     ('Web App', '{"TO-DO"}'),
     ('online E-commerce App', '{"Tested","Pending"}');
     SELECT * FROM projects;

The “proj_status” is basically a backlog for the project statuses. The values will be inserted and the table will look like this:

###  **Step 3: Fetch Array Data**

Once the values have been inserted in the table, we can get the values from the table by using the below query:
    
    
    SELECT proj_id , proj_name ,proj_status [ 1 ] 
    FROM projects;

This query will return the proj_id, proj_name, and the proj_status at **index 1** for all the projects. The project status at index 1 is the current status of the project. The output is given as:

For getting the project status at **index 2** the above query will become:
    
    
    SELECT proj_id , proj_name ,proj_status [ 2 ] 
    FROM projects;

The output for the query is:

The query returned the project statuses of all the projects at index 2 declared in the array. The project “web App” had only one index so the returned values for that record are NULL.

###  **Step 4: Use WHERE Clause**

Now here comes the concept of how can we use the **WHERE** clause. The WHERE clause is used to specify any condition according to which the query will return the results.

If we want to get the name of the project whose current status is completed. The query used will be:
    
    
    SELECT proj_name FROM projects 
    WHERE proj_status [ 1 ] = 'Completed';

On execution of this query, the name of the project is returned where the project status at index 1 is declared as completed. The output looks like this:

###  **Example 2: Updating a Value Using WHERE Clause**

We can also update the value in a table using the WHERE clause. For example, if we want to update the status of a project we can write the query as:
    
    
    UPDATE projects SET proj_status= '{"Pending","TO-DO"}'
    WHERE proj_name= 'Web   App';

In this query, we have updated the project status from “TO-DO” to {"Pending", "TO-DO"} for the field where the project name is “Web App”.

The query will return:

Now we will print the whole table, to see if the update has reflected the change on the table or not, using the following query:
    
    
    SELECT * FROM projects;

The output gives the whole table like this:

We can clearly see that the value of project status has been changed from “TO-DO” to {"Pending", "TO-DO"} for the field where the project name is “Web App”.

This is how the WHERE clause works.

###  **Conclusion**

Arrays are among the most commonly used data types in Postgres. In Postgres, they can be used to store column data. We can use the WHERE clause with these arrays to get and update the records as per our requirements. It is such that the records that satisfy the condition specified with WHERE are returned or updated. In this article, we have seen, how can we use the WHERE clause with arrays.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-where-clause-with-arrays-in-postgresql/)

---

# How to Use SUM() Function with Group By Clause in PostgreSQL

> The GROUP BY clause and SUM() function are used together when we want to calculate the sum of values based on the specific groups.

In Postgres, it is usually the case that we want to get the data of one category from different records. This was never simple before the **GROUP BY** clause came to the rescue. The GROUP BY statement makes groups of the given data by some specified column or columns.

The GROUP BY is usually found complementing the aggregate functions to give useful results. The prime use case for the situation when the **GROUP BY** clause and **SUM()** function are used together is when we want to get the sum of all the prices belonging to the same products sold till now.

In this article, we will see how can we use the GROUP BY clause with the SUM() function.

##  **How to Use SUM() Function with Group By Clause in PostgreSQL?**

The GROUP BY() clause works as a conjunction when it is being used with the [aggregate functions.](<https://commandprompt.com/education/postgresql-aggregate-functions-with-practical-examples/>) We will discuss how the SUM() function and the GROUP BY clause are used together. The SUM() function is a built-in function that returns the sum of the given parameter it is usually used with the GROUP BY clause. The basic syntax for the query can be written as:
    
    
    SELECT col_name, SUM (exp)
     FROM tab_name
     GROUP BY col_names;

In the above syntax:

● With the **SELECT** statement, we specify the column names we want to get in return for the execution of the query.

● The **SUM()** function takes in the parameters and returns their sum.

● After the **GROUP BY** clause, the name of the column is specified.

Let’s consider an example that brings more clarity to the topic.

###  **Example: SUM() Function With GROUP BY Clause**

Let's consider the table named “store_sales_details”. The table looks like this:

Now if we want to group the data by product present in the table. We will write the query as:
    
    
    SELECT
      product,
      SUM (price) AS total_price
     FROM   store_sales_details
     GROUP BY product;

The above code says:

● The table will return the product column and another column that sums the price. This column will be named as total_price.

● The table is grouped by the product column.

● In short, the query returns the sum of all the prices of the same products.

This means that the GROUP BY clause groups the table by product and sums up the prices that belong to the same product in a separate column named “total_price”.

The output looks like this:

The output advocates the concept that we have discussed above.

We can also apply some ordering or limit to the queries with the SUM() function and GROUP BY function.

Like this:
    
    
    SELECT
    product,
    SUM (price) AS total_price
    FROM store_sales_details
    GROUP BY product
    ORDER BY total_price DESC;

The query performs the same function as the above one and additionally, it will order the product prices in descending order. The output looks like this:

So this is how we use the **SUM()** function and the **GROUP BY** function together.

###  **Conclusion**

GROUP BY clause is used to group the data and it is most fruitful when it is used with any aggregation function. In this article, we particularly focused on the SUM() function used with the GROUP BY clause. This combination can be used to retrieve the sum of the same category of data (as we have seen in the example).

---
[View this page online](https://www.commandprompt.com/education/how-to-use-sum-function-with-group-by-clause-in-postgresql/)

---

# How to Create an Extension in PostgreSQL

> In PostgreSQL, the extensions can be created by using the CREATE EXTENSION statement which is followed by the name of the extension.

PostgreSQL offers a wide range of functionalities, data types, aggregates, and operators. But sometimes these are not enough to implement the functionality we want. To cater to the shortcomings in functionality, extensions came to the rescue. The extensions are the add-ons that enhance the functionality. These can work like the built-in features when created in PostgreSQL.

The content of this article will revolve around the way we can create an extension in PostgreSQL.

##  **How to Create an Extension in PostgreSQL?**

As we have discussed above, the extensions that are used to enhance the functionality are present in the database as add-ons. They need to be created to be used in PostgreSQL. Let’s consider the case of CITEXT extension.

The CITEXT is basically a data type that is a case-insensitive data type that allows us to do text comparisons without being case-sensitive. For instance, if we wish to get the data where the name of the student is “Peter”. If we have declared the variable with some data type other than CITEXT and we fetch the data using the small casing, the query will not return the correct results. To understand the CITEXT data type, you can head over to our PostgreSQL [CITEXT Data Type](<http://commandprompt.com/education/postgresql-citext-data-type>) article to get more clarity.

Now if we are using this CITEXT data type for the first time it will throw an error like this:

This is because this data type needs an extension to work. We have to create the CITEXT extension to resolve this error.

To create an extension, the following is the basic syntax:
    
    
    CREATE EXTENSION exten_name

You simply need to specify the name of the extension you want to create. To create the CITEXT extension, the query will be:
    
    
    CREATE EXTENSION CITEXT

After the execution of this query, the extension will be created which can be verified from the following output:

We can also verify the creation of the extension from the side panel. All the extensions are listed in the side panel under the “Extensions” option.

In case you do not see your created extension, just refresh the extension option by right-clicking on the extension option like this.

By performing these steps, you will surely be able to see your created extension.

Now running the query having **CITEXT** data type won’t cause an error and will definitely work fine. So this is how extensions are created.

###  **Conclusion**

We can enhance the functionality of our code by using the extensions that work as built-in features once they are created and loaded. Using the extensions before they are created results in errors. The extensions can be created by using the **CREATE EXTENSION** clause which is followed by the name of the extension. In these above-given paragraphs, we have learned to create an extension in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-an-extension-in-postgresql/)

---

# Understanding Postgres Log Functions - ln(), log(), log10()

> In PostgreSQL, the log functions are used to find the logarithm of a particular number(provided in the function as a parameter). These functions include: log()…

To perform mathematical computations, PostgreSQL offers many built-in functions. **Log** functions are among the most significant and commonly used functions. The log functions return the logarithm of the specified numbers. There are different variants of log functions that are differentiated from each other on the basis of the base they have. This article will provide you with the three basic log functions i.e. ln(), log(), and log10(). Let’s discover these functions together.

##  **Understanding Postgres Log Functions -** **log(), log10(), ln()**

The log() functions are used to compute the logarithm of the specified number. The difference between the log(), ln(), and log10() function is basically their base. Let’s discuss these functions one by one.

###  **log() Function in PostgreSQL**

The **log() function** is used to compute the logarithm of the base specified in the given number. The base and the number both are specified as parameters in the [log() function](<https://commandprompt.com/education/how-to-use-log-function-in-postgresql/>). The basic syntax of the general log function is:
    
    
    log(base, num)

The function takes the base and the number as arguments are returns the log of the base of that number. The log function returns **NULL** if the parameter is **NULL**.

Let’s consider some examples of the log() function.

###  **Example: Understanding the Log() Function**

Consider the following example to get a clear understanding of the log() function:
    
    
    SELECT
      log(2, 6) AS "log_1",
      log(10, 9) AS "log_2";

The above queries will return the logarithms of specified numbers like this:

This is how the log() function works.

###  **Log10() Function in PostgreSQL**

We can also write the **log(10, num)** as log10(num). For the log10() function, the base is specified as 10. It means that the log10() function gives the logarithm of base 10 of a particular number.

Let’s have a glance at what a function will return, in case of certain input:

● The log function returns **NULL** if the argument is NULL.

● If the number specified is “ **zero** ”, the function will return an error that _“ERROR:_ _cannot take the logarithm of zero”_.

● If the specified number is **negative** , it will again throw an error i.e. _“ERROR:_ _cannot take logarithm of a negative number”_.

Let’s move towards some examples of the log10() function.

###  **Example: Understanding the Log() Function**

Consider the following queries to understand how the function works:
    
    
    SELECT
      log10( 6) AS "log10_1",
      log10( 9) AS "log10_2";

The above queries return the logarithm of base 10 for the specified numbers. The output looks like this:

Now if we write the query to find the log10 of **zero** , it will return an error that looks like this:
    
    
    SELECT log10(0);

The query will return an error as claimed above.

Now we will try finding the log10 of a **negative number**. The query will look like this:
    
    
    SELECT log10(-8);

This also returns an error that is illustrated below:

So this is how log10() works.

##  **ln() Function in PostgreSQL**

The **ln() function** returns the natural log of a particular number. The basic syntax for the ln() function is given as:
    
    
    ln(num)

The ln()function only takes in the specified number and returns the natural log of that number.

Let’s see the implementation of this function using an example.

###  **Example: Understanding the ln() function**

Consider the following queries to find the natural number of the specified numbers:
    
    
    SELECT
      ln(6) AS "ln_1",
      ln(9) AS "ln_2";

The output of these queries is:

The ln() function also throws an error if we try to calculate the natural log of **Zero** or a **negative number**. Like this:
    
    
    SELECT ln(0) AS "ln_1";
     SELECT ln(-9) AS "ln_2";

The output shows the errors as:

This is how the ln() function returns the natural log of the specified numbers **except zero** and **negative numbers**.

###  **Conclusion**

The log functions are used to find the logarithm of a particular number(provided in the function as a parameter). The log() function takes in two parameters; the base and the number whose logarithm is to be returned. The log10() and ln() functions are the variants of the log() function based on the base. The ln() function has base “e” while the log10() function has base “10” and accordingly they compute and return the logarithm of the number specified. In this post, we tried to understand the Basic Postgres log functions with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/understanding-postgres-log-functions-ln-log-log10/)

---

# How to Drop an Extension in PostgreSQL

> In PostgreSQL, the extensions can be dropped by using the DROP EXTENSION statement which is followed by the name of the extension.

Implementing a wide range of functionalities, data types, and operators is possible in PostgreSQL. But to implement some advanced functionalities, these functionalities provided by PostgreSQL are not enough. To effectively implement these functionalities, we use extensions.

Extensions are the additional features that upgrade the functionality. These extensions can operate/work like the built-in features in PostgreSQL when they are created and loaded properly. But sometimes these extensions are of no use to us, so we prefer to drop them despite keeping them.

The article teaches us the method we can drop an extension in PostgreSQL. Let’s get started with it.

##  **How to Drop an Extension in PostgreSQL?**

When the extensions are of no use we prefer to discard them rather than keep them. Let’s suppose we have a CITEXT extension already existing in our system, we can drop it using the DROP EXTENSION.

 **Note:** We have already learned how to [create an extension](<http://commandprompt.com/education/how-to-create-an-extension-in-postgresql>) in PostgreSQL. You can see the article if you want to learn more about the CITEXT extension and the method to create it.

Now we will see how to drop an extension. To drop an extension following is the basic syntax:
    
    
    DROP EXTENSION exten_name

You simply need to specify the name of the extension you want to drop. To drop the CITEXT extension, the query will be:
    
    
    DROP EXTENSION CITEXT

After the execution of this query, the extension will be dropped which can be verified from the following output:

But if the extension is being used by any database. In this case, if we want to drop any extension, the following will be the error thrown by PostgreSQL:

To forcibly drop the extension, we will use the **CASCADE** keyword like this:

This will ensure that the extension has been dropped by PostgreSQL.

We can also verify the deletion of the extension from the side panel. All the extensions are listed in the side panel under the “Extensions” option. The name or the extension will be removed from the extension option.

By doing so you will definitely be able to see drop the extension.

###  **Conclusion**

We use extensions to implement some advanced functionality of our code. But if they are not being used it's better to discard/drop them. The extensions can be dropped by using the **DROP EXTENSION** clause which is followed by the name of the extension. Executing this command will drop/discard the extension. In this write-up, we have learned how to drop an extension in PostgreSQL with proper implementation.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-an-extension-in-postgresql/)

---

# How to Switch User in PostgreSQL

> We can switch a user in PostgreSQL by simply executing the SET ROLE command. But the point to be noted is that we can only switch the user if it already exists…

In PostgreSQL, the owner or the User role for every database object is defined. By default, the User of every database object is “postgres”. However, the user can also be defined and changed. The user has the excess to do some critical activities such as deleting/dropping the database objects, you are able to delete the database objects only if you are the owner of that object. In this article, we will learn how we can switch or change a user from a “postgres” user to something else, so let’s get started with the article.

##  **How to Switch Users in PostgreSQL?**

To switch the user you need to run some commands to set a new user role. These commands are described step by step in the portion below. Let’s follow the steps to switch the user:

###  **Step 1: Connect to the Database**

First, you have to establish a connection with PostgreSQL. There are two ways to get connected to the database but the simplest way to do this is by opening the psql and pressing the enter key to the first 4 fields, dining this will set them to default. On the very next field where it asks for the password, enter the password that you set for your PostgreSQL installation. The following output will ensure your connection with the database:

###  **Step 2: Display the Current User**

Now, execute the following query on the psql terminal to get the current_user and session_user:
    
    
    SELECT current_user, session_user;

The query has given the following output:

We can see that the current_user and the session_user in our case are **postgres**.

###  **Step 3: Set a New Role**

Now we will set a new role for our database. This can be done by running the following basic syntax:
    
    
    SET role new_User_name;

You need to add the name of the user that you want to switch to. I will name it “John”. For that, my query will be:
    
    
    SET role John;

The query will successfully switch the new user as we have set a new role as a user i.e.

We can ensure whether the user is switched or not by using the command we have already used to display the current user and session. The query can be written as:
    
    
    SELECT current_user, session_user;

The above query returns:

The above output advocated that the user has been switched from the default “Postgres” user to “John”.

###  **Important**

Note that **you will only be able to switch the user if the user already exists**. If the user does not exist and you try switching the user will result in an error:

To see the list of users that exist in your system run the following meta-command:
    
    
    \du

This meta-command will return the list of all the users existing in the database. The output in my case is:

You can see that only one user exists i.e. the “postgres” which is created by default. This is the reason why we get **“** ** _ERROR:_** **_role <USER> does not exist_** **”** errors.

To cater to this, you need to have the user already existing in order to switch it. Otherwise, you can create a user as well by running the following query:
    
    
    CREATE USER   new_user_name;

I’ll execute the following query:
    
    
    CREATE USER John;

By executing the above query, we will be able to create a user that can be ensured if the following output is returned:

You can also see the user in the list of users by running the **\du** meta-command.

Now if we try switching the user, that will be successfully done by using the **SET ROLE** command like this:
    
    
    SET role John;

The query will simply switch the user for you, which can be ensured by the **SELECT** query as executed above.

So this is how we can switch the user in PostgreSQL.

###  **Conclusion**

We can switch a user in PostgreSQL by simply executing the SET ROLE command. But the point to be noted is that we can only switch the user if it already exists. Otherwise, switching the user to a user that does not already exist causes an error. So we have to create a user first in order to switch it. In this post, we have learned how to switch the user in PostgreSQL with the proper implementation.

---
[View this page online](https://www.commandprompt.com/education/how-to-switch-user-in-postgresql/)

---

# How to Use Generated Columns in PostgreSQL

> The generated columns do not have a fixed value; rather this value is automatically computed by the expression that is determined at the time of column definit…

PostgreSQL database stores records. These records can then be used to perform necessary analytics and computations. However, Postgres also provides some features that can perform automatic computations and show them to users. One such feature is the generated columns.

The generated column is a special kind of column that depends on other column values to get their value. Simply, this kind of column does not have a specific value; rather its value is automatically computed based on the expression specified when defining the column.

The content of this post revolves around the generated columns we will discuss the following in this article:

● How to use generated columns in PostgreSQL.

● Types of generated columns in PostgreSQL

● How are generated columns defined and used in PostgreSQL?

● Updating the value for generated columns.

##  **How to Use Generated Columns in PostgreSQL?**

The generated columns do not have a fixed value; rather this value is automatically computed by the expression that is determined at the time of column definition. Let’s discuss the types of generated columns.

###  **Types of Generated Columns**

There are two types of generated columns:

 **Virtual Generate Columns** \- This type of generated column does not store its value. The values are calculated when reading the columns.

 **Store Generate Columns** \- This type of generated column stores the value. The value of the row is recomputed if the value is modified or updated.

Let’s see how to use these columns in PostgreSQL and what is their need.

###  **Example: How to Use Generated Columns in PostgreSQL**

Let's suppose we have a table named “sales_details” which contains the data of sales of an e-commerce store. The table is given as:

Now if we want to compute the total_sales amount for each product we will add another column to calculate the sales amount. The total_sales_amount will be obtained by taking the product of the number of products sold and the price of a single product. The query can be written as:
    
    
    SELECT *, (price * quantity) AS total_sales_amount FROM sales_details;

The output of the query is:

The above method is absolutely correct. But the generated columns can make our work easy and will definitely save us from querying the SELECT statements again and again.

We can define the generated column when defining the other columns for the table. The basic syntax of the generated column is given as:
    
    
    name_of_col d_type
    GENERATED ALWAYS AS (custom_expression) STORED

In the above syntax:

● The “ **GENERATED ALWAYS AS** ” indicates that it is a generated column.

● The “ **custom_expression** ” specifies the expression that will be utilized to compute its value.

● The **STORED** illustrates that the column(generated) is the **stored generated column**.

We will add the generated column to a pre-existing table i.e. sales_details by making use of the ALTER statement. The query for this can be written as:
    
    
    ALTER TABLE sales_details
    ADD COLUMN total_sales_amount_gcol DECIMAL
    GENERATED ALWAYS AS (quantity * price) STORED;

In this syntax, we have altered the table to add another column called “total_sales_amount_gcol” having the DECIMAL data type. The column added is a generated column having the product of the quantity and price as the expression.

Executing the query will alter the table successfully like this:

Now let’s see how the table is altered by executing the SELECT statement. The output will be:

We have successfully implemented the generated column in the above example. We will now try updating the generated column values.

###  **Updating the Value for Generated Column**

We cannot update or modify the value of any generated column. Let’s see a use case in which we will try to **insert the row** containing the generated column value. Consider the following query:
    
    
    INSERT INTO sales_details ( product,Quantity, price, total_sales_amount_gcol)
     VALUES ('blender', 600 , 15000, 24000);

The above query will result in an error because we can not insert a hardcoded value into the generated column. It is always calculated automatically using values of quantity and price. The output of the above query is:

Now we will try to update the value of the generated column and see what happens. Consider the following query to update the value of the generated column i.e. _“total_sales_amount_gcol”_.
    
    
    UPDATE sales_details
    SET total_sales_amount_gcol = 30000
    WHERE product = 'total_sales_amount_gcol';

This query will also throw an error as we can not update the value of a generated column. The output of the above query is:

So this was all about the generated columns.

###  **Conclusion**

The generated column is a special kind of column that depends on other column values to get their value. The generated columns do not have a fixed value; rather this value is automatically computed by the expression that is determined at the time of column definition. In this post, we have discussed the generated columns, their types, their definition, and their working with proper implementation in a real-world use case.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-generated-columns-in-postgresql/)

---

# How to Transpose Columns to Rows in PostgreSQL?

> In PostgreSQL, the crosstab() function and the unnest() function are used to transpose columns into rows. These functions help us transform the table by return…

There are multiple events when we want to display data in a transformed way. This transformation includes changing the data rows into columns and vice versa. We can transpose the column to rows mainly by using two methods. This article comprises the methods to transpose columns to rows that are:

● Using crosstab() function to transpose columns to rows in PostgreSQL

● Using unnest() function to transpose columns to rows in PostgreSQL

##  **How to Transpose Columns to Rows in PostgreSQL?**

We can get the transposed table, by two approaches i.e. converting the columns of a Postgres table into rows and data rows into columns. Let’s see what these two methods are and how we can utilize/implement them to transpose columns to rows.

###  **Method 1: Using crosstab() Function**

The **crosstab()** function is supported by PostgreSQL version 9.7 and above. We can use the crosstab() function to get the transpose of a table. This function is used in different ways, with different parameters. The PostgreSQL documentation provides a comprehensive description of these [variants](<https://www.postgresql.org/docs/current/tablefunc.html>).

For the scope of this tutorial, just the _“crosstab(sql text)”_ will be discussed _._ The parameter of this function is a SQL query. We will move toward an example so that the concept is more clear to us.

 **Example: Transpose Columns to Rows Using crosstab() Function**

Let's consider a table named “students_marks” containing the marks of the students.

The names of some students and their respective marks occurred more than one time because some of the students have attempted the test multiple times as two attempts were allowed.

Now if we want to see which student attempted the test both times and how many marks they got on each attempt we will write the following query:
    
    
    SELECT *
     FROM crosstab($$
      select student_name::text,student_id::text, test_marks::text
      from students_marks
      order by 1,2
       $$)
     AS   registration(student_name text, Attempt_1 text, Attempt_2 text);

In the above code, the crosstab() function takes a SQL query as a parameter which comprises a select statement. This select statement must have 3 columns specified those are:

○ The first one specifies each row for the returning table.

○ The second column identifies the category.

○ The last one specifies the value of each cell.

These three columns have to be of TEXT data type. In my case they were not so I did type casting of them into text data type. The last line of the query specifies the new columns of the transposed table.

 **IMPORTANT:** Here one thing is to be noted that if you have never used the crosstab() function previously, running the above syntax will return an error like this:

But no need to worry! The solution to this error/problem is creating an extension called **“tablefunc”**. This error arises because this extension is missing. So we need to create this extension first. Execute the following query to create the extension:
    
    
    CREATE EXTENSION tablefunc;

By executing this query you will successfully create the extension in your PostgreSQL like this:

After doing this your query for the crosstab() function will execute properly with no error. The output for the query is given as:

The resulting table gives the transposed table. The marks of a student are arranged in the form of a row with respect to his/her attempt. If the student attempted the test once, the second attempt column gets the value NULL.

This is how we use the crosstab() function to transpose columns to rows. Let's move towards the second method.

###  **Method 2:Using unnest() Function**

The unnest() function can also be utilized to achieve a similar purpose. We can transpose the columns to rows effectively in PostgreSQL using this unnest() function. The query for the transposing column to rows is written like this:
    
    
    SELECT unnest('{StudentID, StudentName, Address,city}'::text[]) AS col
      , unnest('{1,John,13th Street. 47 W ,New York}'::text[]) AS row_1
      , unnest('{2,Alex,24th Street. 32 E , San Diego}'::text[]) AS row_2
      , unnest('{3,Peter,6th Street. 23 W, San Francisco}'::text[]) AS row_3
      , unnest('{4,Williams,4430 Davenport Street Northwest , Boston}'::text[]) AS row_4;

The function will return the given parameters as columns. The output for clarity is given below:

So using these two above-mentioned methods, we can transpose the columns into rows and vice versa.

 **Conclusion**

We can transpose columns into rows as per our need in PostgreSQL. There are 2 functions that can be used for this i.e. the crosstab() function and the unnest() function. These functions help us transform the table by returning the transposed table. In this blog, we have understood in detail, the functioning of these functions work using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-transpose-columns-to-rows-in-postgresql/)

---

# How to Select Random Rows in PostgreSQL

> To get random rows from a database table, use the RANDOM() function with the ORDER BY clause. We can also specify the limit of the number of rows we want to fe…

In PostgreSQL, we can select the random records from the database table. These records are of huge use sometimes and can be selected by using the **RANDOM()** function. This post will cover the method to select the random rows in a Postgres record.

##  **How to Select Random Rows in PostgreSQL?**

Generally, the **RANDOM()** function in Postgres is used to generate random numbers. But we can use it with the **ORDER BY** clause to retrieve random rows from a Postgres table. The basic syntax is
    
    
    SELECT * FROM tab_name ORDER BY RANDOM() LIMIT no_of_rows;

In the above syntax:

\- The table name is specified from which we want to retrieve the rows.

\- The **ORDER BY** clause and the **RANDOM()** function are used together to get the random rows from a table.

\- The number of rows you want to fetch/get is specified after the LIMIT keyword.

Let’s include an example for a better understanding of the topic.

###  **Example 1: Using RANDOM() Function to Select Random Rows in Postgres**

Consider the table named “test_scores”.

Now let’s suppose we want to get 3 random rows from the table. We can write the query as:
    
    
    SELECT * FROM test_scores ORDER BY RANDOM() LIMIT 3;

This query returns 3 random rows from the table as shown in the following output:

We can see that the query has retrieved 3 random rows with no underlying set criteria.

###  **Example 2: Retrieve Rows Based on Some Conditions**

We can also place some conditions to extract the random records. For example, we can write the query to ask Postgres to generate the 3 random records for the male gender. The query will be:
    
    
    SELECT * FROM test_scores WHERE candidate_gender = 'Male' 
    ORDER BY random() LIMIT 3;

The query will return the output having 3 randomly retrieved rows of male gender like this:

This was all about fetching random rows in Postgres.

###  **Conclusion**

To get random rows from a database table, use the **RANDOM()** function with the **ORDER BY** clause. We can also specify the limit of the number of rows we want to fetch/retrieve. In this article, we have discussed getting the random rows from a table using the RANDOM() function with practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-select-random-rows-in-postgresql/)

---

# Understanding Postgres LCM() and GCD() Functions Using Examples

> The lcm() and gcd() functions take two numeric type parameters and return their lowest common factor and the greatest common divisor respectively.

PostgreSQL offers many mathematical functions that assist us in performing mathematical computations. These functions include; **cbrt()** , **factorial()** , **log()** , **pi()** and **round()** etc. Among these mathematical functions, the most frequently used are LCM() and GCD().

In this article, we will be discussing two mathematical functions i.e. LCM() and GCD() in detail with the help of examples.

 **Understanding Postgres LCM() in PostgreSQL**

The lcm() function is used to get the lowest common multiples of two specified numbers. The basic syntax of the lcm() function is:
    
    
    lcm(num1, num2)

In the above syntax:

● “num1” and “num2” are the integers/numbers of which we want to get the lcm. Both of these should be of numeric type, otherwise, the function will display an error.

● The function returns the **lowest common multiple of both the specified numbers** that are also of numeric type. The function returns value NULL if any of the values is NULL.

Let’s observe some example queries to understand how the function works.

 **Example: How Does LCM() Work in Postgres?**

Let’s consider the following queries:
    
    
    SELECT
    lcm(4, 5) AS "lcm_1",
    lcm(24, 40) AS "lcm_2",
    lcm(7.3, 5.7) AS "lcm_3";

The above query will simply return the LCMs of the specified numbers in the function. The output of the function will be:

So we can notice that the function has given the lcm of the specified numbers. This is how the lcm() function works in PostgreSQL.

Moving on to the GCD() function let’s see how it works.

 **Understanding Postgres GCD() in PostgreSQL**

The GCD() function is used to get the greatest common divisor of two numbers provided as arguments/parameters. The basic syntax of the gcd() function is:
    
    
    gcd(num1, num2)

In the above syntax:

● “num1” and “num2” are the integers/numbers of which we want to get the greatest common divisor. Both of these should be of numeric type. Otherwise, the function will display an error.

● The function gives the **greatest common divisor of both the specified numbers** that are also of numeric type. The function returns value NULL if any of the values is NULL.

Let’s observe some example queries to understand how the function works.

 **Example: How Does the GCD() Work in Postgres?**

We now will observe the below example to understand how the gcd() function works.
    
    
    SELECT
    gcd(4, 5) AS "gcd_1",
    gcd(24, 40) AS "gcd_2",
    gcd(6.3, 9.6) AS "gcd_3";

The above query will simply return the GCDs of the specified numbers in the function. The output of the function will be:

So, we can note that the function has given the gcd of the specified numbers. This is how the gcd() function works in PostgreSQL.

This write-up demonstrated the working of lcm() and gcd() functions in PostgreSQL.

 **Conclusion**

The **lcm()** and **gcd()** functions are the commonly used mathematical functions. Both the functions take two numeric type parameters and return their lowest common factor and the greatest common divisor respectively. The content of this article comprised of the details of these two functions with their practical examples.

---
[View this page online](https://www.commandprompt.com/education/understanding-postgres-lcm-and-gcd-functions-using-examples/)

---

# How to Query Data Between Specific Date Ranges in PostgreSQL

> To get the data between two specified date ranges, use the “WHERE” and “AND” clauses, the BETWEEN operator, the SYMMETRIC keyword, and the Range data types.

The time and date-specific data is very crucial for some use cases such as e-commerce stores. They can use daily generated data to get insights and perform data analysis with those insights. These insights and analyses can then be used to track the activity and performance of their products. In Postgres, we can generate data between two dates in order to get some insights. In this post, we will be discussing the methods to get the data between two specific dates.

##  **How to Query Data Between Specific Date Ranges in PostgreSQL?**

We can get the data between two specific date ranges by various methods that we are going to discuss in this post. For that consider the following table named “store_sales_details”:

The table contains the data of an e-commerce store. Suppose we have to find them for sales of products between the two dates i.e. '2023-05-20' and '2023-08-25'.

Let's see the method using which we can find the data between these two specified date ranges.

###  **Method 1: Using WHERE and AND**

We can use the WHERE and AND clauses to specify the data range and get the data between these two dates. The query will be written as:
    
    
    SELECT * FROM store_sales_details
    WHERE
    date_of_order >= '2023-05-20'
    AND date_of_order <= '2023-08-25';

In the above syntax, we have specified the _date_of_order_ range using WHERE and AND keywords and using the relational/comparison operators. The resulting table contains the data between these two dates:

###  **Method 2: Using BETWEEN**

This method is almost the same as the above method with the addition of the BETWEEN keyword. The query for this method can be written as:
    
    
    SELECT * FROM store_sales_details
    WHERE
    date_of_order BETWEEN '2023-05-20'AND '2023-08-25';

This query returns the data between the two specified date ranges using the BETWEEN keyword. The output looks like this:

###  **Method 3: Using SYMMETRIC**

The **SYMMETRIC** keyword is used with the BETWEEN keyword. This query works the same as the above method. The query can be written as:
    
    
    SELECT * FROM store_sales_details
    WHERE
    date_of_order BETWEEN SYMMETRIC '2023-05-20' AND '2023-08-25';

The query will return the data between the two specified date ranges:

###  **Method 4: Using Range Types**

The range types are supported by Postgres from Postgres version 9.2 and above. We will use the date range for our use case. Let’s see how it works:
    
    
    SELECT * FROM store_sales_details
    WHERE '[2023-05-20, 2023-08-25]'::daterange @> date_of_order;

The above syntax:

● The date range is specified with the **WHERE** keyword.

● The query will return the data that lies between the specified range contained in the “date_of_order” column.

So the output of the query will be:

The above-mentioned were the methods to fetch the data between the specified date range in PostgreSQL. That was all for this topic.

###  **Conclusion**

We can get the data between two specified date ranges using the methods that we extensively discussed in this article. These methods include the “WHERE” and “AND” clauses, the BETWEEN operator, the SYMMETRIC keyword, and the Range data types. This data proves to be very beneficial for tracking and analysis purposes. We can easily get insights and metrics about any product to analyze its performance in the market.

---
[View this page online](https://www.commandprompt.com/education/how-to-query-data-between-specific-date-ranges-in-postgresql/)

---

# How to Find the Size of a Postgres Tablespace

> To find the size of the Postgres Tablespace, use the “pg_tablespace_size” function that takes the tablespace name as an argument and returns its size.

The **tablespace** in Postgres is the location on the disk where all the data of the database is stored. This data includes tables, triggers indexes, etc. The tablespace is actually needed by Postgres for mapping the logical name onto the physical address/location on the disk. The 2 default tablespaces that are being provided by Postgres are pg_default and pg_global. The first one stores default data while the other one stores global data.

This write-up will teach us the method to get the size of the tablespace in PostgreSQL.

##  **How to Find the Size of a Postgres Tablespace?**

To find the size of the Postgres Tablespace, we use a built-in function named “pg_tablespace_size” that takes the table name as an argument and returns the size of the tablespace. The basic syntax for this function is as follows:
    
    
    SELECT pg_tablespace_size('tabsp_name');

In the above syntax:

● The pg_tablespace_size() function is used to find the size of a tablespace.

● The tablespace’s name is provided as a parameter to the function.

The function takes the name of tablespace as an argument to give its size in bytes.

To make the size of a tablespace human-readable the “pg_size_pretty()” function is used. In this case, the “pg_size_pretty()” function will take the result of the “pg_tablespace_size()” as its parameter and return the size of the tablespace in bytes that is a human-readable format.

The syntax of using pg_tablespace_size() along with pg_size_pretty() is:
    
    
    SELECT pg_size_pretty(
    pg_tablespace_size('tabsp_name'));

Let's see the example in order to get the size of a Postgres tablespace.

###  **Example: Finding the Size of a Postgres Tablespace**

To get the size of the tablespace named “example_tablespace” (that is already created) in bytes, we write the query as:
    
    
    SELECT pg_size_pretty(
    pg_tablespace_size('example_tablespace'));

On execution of this query, the output will look like this:

We can see that executing the query gives the size of the tablespace in KBs.

So that was all about the tablespace size.

##  **Conclusion**

We can find the size allocated to a tablespace in Postgres by utilizing the pg_tablespace_size() function. This function takes in the name of the tablespace and returns the size of the tablespace. Another function that is used to make the returned size human-readable is “pg_size_pretty()”. In this post, we have discussed both the functions to get the size of a tablespace in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-the-size-of-a-postgres-tablespace/)

---

# How to Round an Average to 2 Decimal Places in PostgreSQL

> To find the average of a column we use the AVG() function taking the name of the column as a parameter. The ROUND() function rounds off a specified number up t…

There are some real-time cases when we want to find the average of some entities and then round these averages to some specified decimal places. The most prominent/significant use case of this statement is calculating the CGPA. When calculating CGPA, we have to find the average first then we round it up to 2 decimal places. This post will demonstrate to us how we can round an average to 2 decimal numbers. Let’s get started.

 **How to Round an Average to 2 Decimal Places in PostgreSQL?**

To find the average of entities, we use an aggregate function that is the “[AVG() function](<https://www.commandprompt.com/education/how-to-use-avg-function-in-postgresql/>)”. The AVG() function takes in the name of the column and returns the average of all the numbers of the column. The fundamental/basic structure of the **AVG()** function is:
    
    
    AVG(col_name);

To round a number to a certain decimal place we use the **ROUND()** function. We can write the syntax of the ROUND() function in two different ways. The first one is:
    
    
    ROUND(Num dp or numeric)

This syntax only takes one parameter which is the number it will round and returns the nearest integer. In this syntax, you can not provide the parameter for the number of decimal places you want to round up to. The parameter passed into the function must be of **DOUBLE PRECISION** or **Numeric** data type.

The second syntax is:
    
    
    ROUND(Num numeric, decimal_places int)

This syntax has two parameters defined in the function. The first parameter is the number that needs to be rounded off in numeric data type and the second parameter is the integer specifying the number of decimal places the rounding off should occur.

So now how can we round an average up to 2 decimal places using these functions? The concept will be more clear using an example. Let's move towards an example.

 **Example: Rounding an Average to 2 Decimal Places in PostgreSQL**

Consider the table named “test_scores” containing the data and score records for candidates who appeared in the entrance test of a high school. That table looks like this:

Now we can find the average of scores obtained in the test and round it up to 2 decimal places:
    
    
    SELECT ROUND(AVG(candidate_score), 2)
    FROM test_scores;

We have written the **AVG()** function in the **ROUND()** function to get the average rounded up. We have specified “2” as a second parameter in the ROUND() function in order to get the average rounded up to 2 decimal places. The output for the query is:

So the query returned the average marks that candidates obtained, in the test rounded, up to 2 decimal places.

This is how we can average up to two decimal points.

 **Conclusion**

To find the average of a column we use the AVG() function taking the name of the column as a parameter. The ROUND() function rounds off a specified number up to particular decimal places. To get the rounded average up to 2 decimal places, we use both functions simultaneously. In this post, we have elaborated on how can we get the rounded average up to 2 decimal places.

---
[View this page online](https://www.commandprompt.com/education/how-to-round-an-average-to-2-decimal-places-in-postgresql/)

---

# How to Custom Sort in PostgreSQL ORDER BY Clause?

> In PostgreSQL, the ordering is done by using the ASC and DESC keywords but we can also customize the sorting order using several ways, such as the CASE keyword…

PostgreSQL table data can be sorted based on some criteria. The data is usually sorted in ascending or descending order by making use of the **ORDER BY** clause and the **ASC** and **DESC** keywords(used to specify the sorting order). We can also custom-sort the data according to our needs and requirements. The following paragraphs will demonstrate about the methods that can be used to custom-sort data. These methods are:

● Method 1: Custom Sort Using CASE

● Method 2: Custom Sort Using array_position Function

● Method 3: Custom Sort JOIN

Let’s get started with the article to see how can we custom-sort our data using these methods.

 **How to Custom Sort in PostgreSQL ORDER BY Clause?**

We can customize the sorting order as per our wish by using some methods enlisted above. Let’s see how these functions can be utilized to customize the sorting order.

 **Method 1: Custom Sort Using CASE**

To custom sort the data in PostgreSQL, the most commonly used way is by doing it using CASE. the basic syntax for this method to perform custom sorting is:
    
    
    SELECT * FROM tab_name
     ORDER BY CASE 
      WHEN col_value = "val1" THEN   priority_1
      WHEN col_value = "val2" THEN priority_2
      WHEN col_value = "val3" THEN priority_3
      ELSE priority_n 
      END;

This method specifies each value of the column in a specific order or priority. Consider the table named “projects” to implement the custom sorting methods on it. The table is given as:

Now we will be sorting the projects by their statuses in the following order:

>  **Tested** **= >** **Completed** **= > Pending =>** **TO-DO**

The query can be written as:
    
    
    SELECT * FROM projects
     ORDER BY CASE
      WHEN proj_status = 'Tested' then 1
      WHEN proj_status = 'Completed' then 2 
      WHEN proj_status = 'Pending' then 3
      WHEN proj_status = 'TO-DO' then 4
      END;

In the above syntax, we have simply specified the sorting order. This query will return the custom-sorted table. The output is given as:

This is how we can sort tables according to our wishes.

Let's move towards another alternative method to do the same thing.

 **Method 2:** **Custom Sort Using array_position Function**

An alternate method to do custom sorting is by using the array_position() function. The array takes the two required parameters. The 1st one is the array and the 2nd is the element whose position is to be found in the array. In our case, we will provide the sorted array, as we want the table to be sorted, and give the column name from the table on which we want to apply sorting. The query can be written as:
    
    
    SELECT * FROM projects
    ORDER BY array_position(array['Tested','Completed','Pending','TO-DO'], proj_status);

The query will return us the custom sorted array same as we needed. The output is:

So this is how we can perform custom sorting.

 **Method 3:** **Custom Sort Using JOIN**

We can then JOIN to order the data in a customized way. Consider the query for our use case using this method:
    
    
    SELECT * FROM projects
     JOIN (VALUES ('Tested', 1), ('Completed',2), ('Pending', 3), ('TO-DO', 4)) 
     as o(value, sorting_number) ON proj_status = o.value
     ORDER BY o.sorting_number;

The above query fetches all the columns from the “projects” table and joins them with a temporary table. The temporary table contains the status values and sorting numbers. Finally, the ORDER BY clause sorts the result set according to the sorting_number.

The query results in the customized ordered data which looks like this:

The output shows that our query worked well.

So these are the approaches to customize and sort the data in PostgreSQL.

 **Conclusion**

In PostgreSQL, the ordering is done by using the **ASC** and **DESC** keywords but we can also customize the sorting order using several ways; the first one is the most commonly used for this purpose i.e. by using the CASE keyword, the second is by using the array_position() function and the third one is by using JOIN. In this blog, we have discussed all three methods of custom-sorting the data according to our requirements with valid implementation.

---
[View this page online](https://www.commandprompt.com/education/how-to-custom-sort-in-postgresql-order-by-clause/)

---

# How to Change Primary Key in Postgres

> To change a Primary key in Postgres, remove the existing primary key from the table, and add a new primary key using the “ALTER TABLE ADD PRIMARY KEY” statemen…

The primary[ key](<https://www.commandprompt.com/education/postgresql-primary-key-a-complete-guide/>) is used to uniquely identify a record or we can define the primary key as the the column that is used to uniquely identify a row. A database table must have a single primary key. It is a better approach to have a primary key per table while creating a table. Usually, primary keys are declared when creating a table. However, we can also change afterward if the need arises.

This write-up will extensively elaborate on the method to change the primary key so let’s get started.

 **How to Change Primary Key in Postgres?**

We can change the already declared primary key for a database table in Postgres. But let’s start from the very beginning by creating a table and declaring the primary key there.

 **Creating a Table and Declaring the Primary key**

Let's create a table named **“Students_scholarships”** and declare the student_id as the primary key which uniquely identifies each student in the table. The query for this will be:
    
    
    CREATE TABLE Students_scholarships (
    Student_id SERIAL PRIMARY KEY,
    Student_name VARCHAR(100) NOT NULL,
    Scholarship_amount DOUBLE PRECISION NOT NULL
    );

Here we have declared the primary key as “student_id” so Postgres will store it as the primary key for the table “Students_scholarships”. If we do not specify the primary key Postgres will consider “table-name_pkey” by default.

Now if we want to change the already declared primary key we will follow the following steps:

 **Step 1: Remove the Primary Key Attribute**

The first step is to remove the primary key attribute from the previous/former primary key. This can be done by using the following syntax:
    
    
    ALTER TABLE   <tab_name> DROP CONSTRAINT   <tab_name>_pkey;

For our particular use case, the query will become:
    
    
    ALTER TABLE Students_scholarships DROP CONSTRAINT Students_scholarships_pkey;

By running this query, the table will successfully be altered for the removal of the primary key.

Also by running the select query, we can see that the “student_id” is no longer a primary key. For reference, you can look at this.

The next step is to change the name of the primary key and the candidate properly.

 **Step 2: Set a New Primary Key**

After removing the previous primary key from a table, we will now assign a new primary key to the table. The basic syntax of the query looks like this:
    
    
    ALTER TABLE <tab_name> ADD PRIMARY KEY (new_primary_key);

In the above syntax:

● We will alter the table by specifying the table name.

● We will alter the table for a new primary key by specifying the name of the new primary key after the ADD PRIMARY KEY keyword.

Let’s execute this in our use case. Our query will look like this:
    
    
    ALTER TABLE Students_scholarships ADD PRIMARY KEY (Student_name);

The query says that the table “students_scholarships” is altered and we have added, “student_name” as the primary key. By executing this query, we will successfully alter our table for the change.

Now let’s select the table to see if the primary key change has been reflected on the table or not. Run the select query like this:
    
    
    SELECT * FROM Students_scholarships;

The table is returned by the query which looks like this:

We can clearly see that the primary key for the table has been changed. So this is how we can change a primary key for an existing table.

There is a one-step query doing the same thing. The basic syntax for this query can be written as:
    
    
    ALTER TABLE <tab_name>
     DROP CONSTRAINT <tab_name>_pkey CASCADE,
     ADD PRIMARY KEY(new_primary_key);

In this above query, the table is altered to drop the constraint as a primary key and add a new primary key in the table in a single query. The query for our use case will be:
    
    
    ALTER TABLE Students_scholarships
     DROP CONSTRAINT Students_scholarships_pkey CASCADE,
     ADD PRIMARY KEY(Student_name);

The query will be successfully altered as:

To select the table we will write the select query:

We can use any of the queries to do the same thing as they both are doing the same function. This is all about the way to change the existing primary key in Postgres.

 **Conclusion**

To change a Primary key in PostgreSQL, first, you need to remove the existing primary key from the table. After that, a new primary key can be added to the desired column using the “ALTER TABLE ADD PRIMARY KEY” statement. The main purpose of primary keys is that they are used to uniquely identify each record/row. But sometimes we need to change the existing primary key for the Postgres table. This can be done by altering the table to first drop the existing primary key and then by adding a new primary key of your choice. In this article, we learned about the method to change the primary key in an effective way using an example.

---
[View this page online](https://www.commandprompt.com/education/how-to-change-primary-key-in-postgres/)

---

# How to Concatenate Columns in Postgres

> To concatenate multiple columns in PostgreSQL, the CONCAT() function is used. Moreover, we can also use the concatenation operator “||”.

PostgreSQL database stores data in the form of tables. There is a great possibility that the database tables contain unnecessary and extra columns, that can be created as one. For example, in some cases, where the city or the location is not that important, there is no need to separate 2 columns for address and city. We can simply create one column that may be named “address” which contains the detailed address and the city. This can be done by concatenating the two columns.

In this post, we will see a couple of ways to concatenate columns in PostgreSQL:

● Concatenating Table Columns Using the **CONCAT()** function.

● Concatenation of two different data types tables using the **“||”** operator.

Let’s get started with the article.

 **How to Concatenate Columns in PostgreSQL Using CONCAT() Function?**

In PostgreSQL, the **CONCAT()** function is generally used to concatenate/combine two or more strings, taken as arguments. This function can also be utilized to combine two or more columns in Postgres. The columns that we want to concatenate are passed into the CONCAT() function as arguments. The basic syntax to concatenate columns can be written as
    
    
    SELECT *, CONCAT(col_1,col_2,... col_n) AS <new_col_name> FROM tab_name;

In the above syntax:

● The names of columns that we want to concatenate are passed into the **CONCAT()** function in sequence as parameters.

● After the **AS** keyword, the name of the new column is specified which is returned as a result of concatenation.

● The name of the targeted table will be written after the **FROM** statement.

Let’s see how the CONCAT() function works with the help of examples.

 **Example: Concatenate Two Columns in PostgreSQL**

We can concatenate two columns in Postgres using the CONCAT() function. Let's consider the following table named “registration” containing the columns “studentid”, “studentname”, “address”, “city”, and “phone_no” of each student. The table is as follows:

Now here we can combine the address and city columns in a single column named “complete_address”. The query will be written as:
    
    
    SELECT *, CONCAT(address, city) as complete_address from registration;

After execution of this query, we will see that another column is created that has both the columns concatenated like this:

We can also concatenate the columns using some character such as a hyphen or underscore between them. The query for this can be customized as:
    
    
    SELECT *, CONCAT(address,' - ',city) as complete_address from registration;

The query will add the “-” between the entries of both columns.

We will now see how the concatenation is done in the case of two columns of different data types.

 **How to Use || Operator to Concatenate Columns?**

We can also concatenate two columns using the “||” operator. However, the additional function this operator offers is that we can concatenate the two columns with different data types. This is done by typecasting one of them. For example, in the above-considered case, the “studentname” column is of character data type, and the “Phone_no” is an integer. So if we want to concatenate these columns we will write the query like this:
    
    
    SELECT *, studentname || Phone_no::text AS   student_ph FROM   registration;

In the above code:

● The “studentname” column had the character data type.

● The “Phone_no” column had an Integer data type.

● So we are basically typecasting the “Phone_no” column into the character/text data type before concatenating it with the other column.

● A new column, named “student_ph”, will be formed.

The output of the above query will be as follows:

This is how we can concatenate two columns in PostgreSQL.

 **Conclusion**

To concatenate multiple columns in PostgreSQL, the **CONCAT()** function is used. Moreover, we can also use the **concatenation** operator “||”. The **CONCAT()** function takes the columns to be concatenated as parameters. We can also specify any special symbol using which we want to concatenate the columns. Postgres allows us to concatenate the columns with different data types by typecasting them first. In this article, we have learned about the concatenation of columns in PostgreSQL and discuss both the concatenation cases with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-concatenate-columns-in-postgres/)

---

# What Does NOT LIKE Operator Do in Postgres

> The NOT LIKE operator looks for the specified character/text/string in the database and returns those records that do not contain that specified string/pattern…

In PostgreSQL, we have **LIKE** and **ILIKE** operators for simple search purposes. These operators return true when a specified term matches with the term in the data. There also exists an operator that works opposite to these operators. This operator is referred to as the **NOT LIKE** operator. The NOT LIKE operator returns false if the match to the specified text is found and true when the match is not found after searching. This means that when searching for a term with the NOT LIKE operator, the query will retrieve all those records that do not contain or match that text/string.

This write-up will investigate the functioning NOT LIKE operator in detail.

 **What Does NOT LIKE Operator Do in Postgres?**

The search operators basically use wildcards to do the text/string matching. These wildcards are specified using 2 operators: the percentage sign “ **%** ” that matches the set of characters and the underscore sign “ **_** ” that matches a character. The matching is done using the wildcards and the values are returned accordingly. The NOT LIKE operator matches the string using the wildcards and returns the values that are not matched to the specified string. The basic syntax for the NOT LIKE operator is given as:
    
    
    SELECT FROM tab_name
    WHERE col_name NOT LIKE match_pattern;

In this syntax:

● First, we have to specify the table name after the **SELECT FROM** clause.

● After the **WHERE** statement, we will specify the name of the column in which we want to search for the string.

● Lastly, after the “NOT LIKE” operator, we will specify the match_pattern of our choice using the wildcards.

Let’s move towards an example to get a good grip on this topic.

 **Example: How Does the NOT LIKE Operator Work in Postgres?**

Let’s consider a table named “simplesearch”, the data of which is depicted in the following screenshot:

Suppose we want to get the document entry that does not contain the word “ate. To perform this specific thing, we will execute the following syntax:
    
    
    SELECT document 
     FROM simplesearch
     WHERE document NOT LIKE '%ate%';

The above query will give all the data which do not contain the “ate” word. The output is:

The query has searched for the word ”ate” in the whole list of documents. If any record matches the string “ate” it will not be returned. Conversely, if the string does not match any record, it will be included in the query results.

This is how the NOT LIKE operator works in Postgres.

 **Conclusion**

The **NOT LIKE** operator functions opposite the **LIKE** and **ILIKE** operators in Postgres. This operator looks for the specified character/text/string in the database and returns those records that do not contain that specified string/pattern. The pattern is specified using the wildcards. In this post, we have learned about the NOT LIKE operator in Postgres with a practical example and how is it different from the other simple search operators.

---
[View this page online](https://www.commandprompt.com/education/what-does-not-like-operator-do-in-postgres/)

---

# How to Fix Error “function ntile() Does Not Exist” in PostgreSQL

> In PostgreSQL, the error “function ntile() Does Not Exist” basically arises when we do not provide any argument to the ntile() function.

While executing different queries in PostgreSQL, it is very much possible that we can encounter some errors. We definitely need to fix these errors in order to get the expected output result from the query. An error i.e. **“function ntile() Does Not Exist”** shows up when we execute the function, ntile(). This function divides a segment into different groups also called buckets. The function tries to divide the rows equally. Let’s find out the reason why we encounter the error “function ntile() Does Not Exist” and its appropriate solution using examples.

 **How to Resolve Error “function ntile() Does Not Exist” in PostgreSQL?**

While executing the queries using this[ ntile() function](<https://www.commandprompt.com/education/how-to-use-postgresql-ntile-function/>), we usually encounter the error “ **function ntile() Does Not Exist** ” as shown in the following output:

The error, “function ntile() Does Not Exist” occurs when we do not pass any **argument** in the ntile() function. The ntile() function takes in an **integer** that specifies the number of buckets/parts we want to divide our table rows into. Let’s see how can we fix this error with the help of an example:

 **Example: How to Fix “function ntile() Does Not Exist” Error in PostgreSQL?**

Let’s consider that we wrote the query to partition the data of the table named “test_scores” into 4 buckets. The query looks like this:
    
    
    SELECT *,
     ntile( ) 
     OVER ( ORDER BY candidate_id ) 
     AS "ntile"
     FROM test_scores;

Running this query results in an error that the “function ntile() Does Not Exist”. Now in the above query, we can see that the ntile() function has not been provided with any argument, which is the primary/main reason for this error.

Now let’s pass “4” as an argument in the function which will instruct the function to make 4 buckets from the total rows of the table. The query will be as follows:
    
    
    SELECT *,
      ntile(4) 
      OVER (ORDER BY candidate_id ) 
      AS "ntile"
     FROM test_scores;

Executing this function will result in the expected output i.e. the function works fine and the error is removed.

The output for this query is:

We can see that the ntile() function has divided the whole table data rows into 4 almost equal buckets. This is the basic functioning of the ntile() function.

The argument must be an **integer** or **numeric data** and also the integer needs to be **greater than 0.** We can also encounter other errors due to the issue with the argument like if we give the argument as 0.
    
    
    SELECT *,
      ntile(0) 
      OVER (ORDER BY candidate_id ) 
      AS "ntile"
     FROM test_scores;

The output will be:

Specifying the **argument as 1** will give the whole table as it considers all the data as one bucket.

This is how we can resolve the “function ntile() Does Not Exist” error.

 **Conclusion**

The error **“function ntile() Does Not Exist”** basically arises when we do not provide any argument to the ntile() function. The function requires a mandatory argument that has to be **numeric type** and should be **greater than 0**. Passing 1 as an argument will return the whole table as one bucket. In this post, we have learned how to resolve the “function ntile() Does Not Exist” error with practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-error-function-ntile-does-not-exist-in-postgresql/)

---

# How to Create a Tablespace in PostgreSQL

> To create a tablespace in PostgreSQL, the “CREATE TABLESPACE” statement is used with the “LOCATION” clause. It refers to the location on the disk where all the…

The **tablespace** in Postgres is the location on the disk where all the data of the database is stored. This data includes tables, triggers indexes, etc. The tablespace is actually needed by Postgres for mapping the logical name onto the physical address/location on the disk. There are two default tablespaces:

● Pg_default - This tablespace stores default data.

● Pg_global - This tablespace stores global data.

In this post, we will gain some understanding of how to create the tablespace in PostgreSQL.

 **How to Create a Tablespace in PostgreSQL?**

We have already seen why tablespace is needed by Postgres. Now we will acquire some knowledge of creating a tablespace in Postgres. The basic syntax for creating a tablespace is given below:
    
    
    CREATE TABLESPACE tabspace_name
    OWNER user
    LOCATION dir_path;

In the above syntax:

● The tablespace is created by using the **CREATE TABLESPACE** command. After this command, the name of the tablespace is specified.

● We have to write the owner’s name after the **OWNER** clause. Also if we want to assign another owner/user to the tablespace, we can declare it here.

● The directory path is also written after the **LOCATION** clause. This directory path is an absolute path of a directory that must be owned by the user so that the data can be read and written in this directory. Initially, this directory should be empty.

Let’s dive into the topic using an example to make it more clear.

 **Example: Creating a Tablespace in PostgreSQL**

Open the SQL Shell or psql and write the following command to create a table space:
    
    
    CREATE TABLESPACE example_tablespace
    LOCATION 'C:\Program Files\PostgreSQL\15\data';

The above code will create a tablespace named “example_tablespace” using the physical address “C:\Program Files\PostgreSQL\15\data”. But you have to keep in mind that the directory location you provided must exist. The above query has successfully created a tablespace.

Now if we want to list all the table space in this Postgres database server we will execute the following command:
    
    
    \db

By executing this command the shell will return you all the tablespaces created in the database server like this:

We can see that the example_tablespace we created is visible to us. If we want to get some additional information related to the tablespace we execute the following meta-command:
    
    
    \db+

This will give more extensive information about the tablespace such as size and other options like this:

So this was all about creating a tablespace in PostgreSQL.

 **Advantages of Creating Tablespace**

Tablespaces are beneficial in many ways. The most significant of them are:

● The tablespaces are used to derive the statistics. These stats are then used to optimize the performance parameters.

● The tablespace allows the administrators to manage the storage more efficiently.

 **Conclusion**

To create a tablespace in PostgreSQL, the “CREATE TABLESPACE” statement is used with the “LOCATION” clause. Tablespace is the location on the disk where all the data for a database is stored. In this article, we have learned about tablespace and how to create a tablespace and retrieve detailed information about them using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-tablespace-in-postgresql/)

---

# How to Use REAL Data Type in PostgreSQL

> The REAL data type is a numeric data type used to store the single-precision floating point numbers. It requires fewer storage constraints as compared to the D…

PostgreSQL stores information in the form of tables and to use and modify the table data we will have to create them first. While creating tables, we need to define their data types also. These data types are necessary to store the specific data in the table columns. These data types include numeric data types, time and date data types, character data types, boolean data types, etc. This post will cover a numeric data type that is used to store single-precision floating-point numbers basically 32-bit in size.

Let’s see how to use these REAL data types in PostgreSQL.

 **How to Use REAL Data Type in PostgreSQL?**

The **REAL** data type is actually a floating-point type that stores the single-precision floating-point numbers. The size of these data types is 32-bit, which means that it uses comparatively less storage as compared to the **DOUBLE PRECISION** data type. However, the precision of this data type is also less as compared to the DOUBLE PRECISION data type. So if we wish to have more precision, you can go for the DOUBLE PRECISION data type.

However, the **REAL** data type is extensively used in the fields of engineering, finance, economics, etc. to store the numeric values containing the floating point.

Now let’s see how we declare and use the **REAL** data type in PostgreSQL using an example.

 **Example: How to Use REAL Data Type in PostgreSQL?**

Consider creating a table named “Velocity” having a “velocity_value” column which is of REAL data type. The query can be written as:
    
    
    CREATE TABLE Velocity(
     velocity_value REAL
     );

Upon the execution of the above query, a table will be created. Now we will insert some values in the table by the following query:
    
    
    INSERT INTO Velocity(velocity_value) VALUES (784.93);
    INSERT INTO Velocity(velocity_value) VALUES (256.87);

The values will be inserted in the table successfully which can be ensured by the following output:

Execute the SELECT statement to get the table:

We can see that the data type of the column is REAL data type. This is how we use the REAL data type in this database.

 **Conclusion**

The REAL data type is a numeric data type used to store the single-precision floating point numbers. This data type requires fewer storage constraints as compared to the DOUBLE PRECISION data type. It can be storage efficient at times but they offer less precision. If we wish to have high precision, we can use DOUBLE PRECISION data types. In this post, we have discussed how to use the REAL data type in PostgreSQL using examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-real-data-type-in-postgresql/)

---

# How to EXTRACT TIME Part From a TIMESTAMP IN PostgreSQL

> The time can be extracted from the timestamp in PostgreSQL by typecasting the timestamp to time. This helps us analyze the data based on the time.

Users can store time and date using the timestamp data type. But sometimes they need to get the time or the date part from the timestamp. Users can extract the time part from the timestamp data type by casting the timestamp. In this article, we will learn how can we extract the time part from the timestamp in PostgreSQL.

 **How to EXTRACT TIME Part From a TIMESTAMP in PostgreSQL?**

The time can be extracted from the timestamp in PostgreSQL by typecasting the timestamp to time.

Let’s learn this using an example.

 **Example: Extracting Time Part From a TIMESTAMP**

Consider the following query:
    
    
    SELECT TIMESTAMP '2023-11-09 16:41:15'::time ;

The above query is meant to extract time from the given timestamp. The output of the query is:

In this way, we can get the time from the timestamp. Let’s implement the same query for the table.

 **Example: Extracting Time Part From a TIMESTAMP Column**

Consider the table named “store_sales_details”.

Now if we want to get the time from the whole column, we will first have to typecast the column to the timestamp data type and then to the time. The query can be written like this:
    
    
    SELECT *, time_and_date_of_order:: timestamp:: time FROM store_sales_details;

In the above syntax:

We first type-casted the whole column as a timestamp and then as time. The output will give another column containing all the times extracted from timestamps.

The output looks like this:

You can see that we have extracted the time from the timestamps through a PostgreSQL query.

 **Conclusion:**

We can extract the time from the timestamp by type-casting the timestamp into the time. Getting the time from the timestamp may be of great interest in many cases such as in this case when doing the analysis for the time when the product is generating sales and performing well. In this article, we have learned to extract the time from the timestamp with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-extract-time-part-from-a-timestamp-in-postgresql/)

---

# How to Get the First, Last, and nth value of a Partition in Postgres

> In PostgreSQL, users can get the first, last, and any nth values from each partition using the FIRST_VALUE(), LAST_VALUE(), and NTH_VALUE(), respectively.

In PostgreSQL, partitions play an important role in categorizing the data and dividing them into parts based on some criteria. We can easily get some useful information from each partition. For example, if we partition the record of students who appeared in the test based on gender, we can easily find the top scorer from both genders the least scored marks from both genders, and in fact, we can get the marks at any position. The Nth-value function performs this for us. Let’s see how can we get the first, last, and nth values of a partition in PostgreSQL.

 **How to Get the First, Last, and Nth Value of a Partition in Postgres?**

We can get any value from a partition using the nth value function. We can write the basic syntax for this function like this:
    
    
    NTH_VALUE ( Expression, Offset ) 
       OVER ( 
      [PARTITION BY partition_expression, ... ]
      ORDER BY sorting_expression [ASC | DESC], ...
       )

In the above syntax:

● The NTH_VALUE() FUNCTION takes in two arguments.

● The “Expression” is the expression we want to apply the NTH_VALUE function.

● Offset depicts the number of rows in one window relative to the first row. It is basically an integer.

● PARTITION BY clause divides the data values into partitions.

Let's consider an example to apply the concepts on so that it brings more clarity.

 **Example: How to Get the First, Last, and Nth Value of a Partition in Postgres**

Let’s consider the table named “test_scores” containing the candidate data and marks records of all the candidates who appeared in the test. The table looks like this:

Now let’s move toward finding the first value of a partition.

 **Example 1: How to Get the First Value of a Partition in PostgreSQL**

Will can get the first value of a partition from table “test_scores” using the above example.

The query for this case can be written as:
    
    
    SELECT *, FIRST_VALUE (candidate_score) 
     OVER (
     PARTITION BY candidate_gender -- we will partition on the base of gender
     ORDER BY candidate_score DESC -- The   ordering will take place based on scores
       ) AS top_scores
     FROM test_scores;

In the above syntax:

● After the **PARTITION BY** , we have specified the name of the column on the base of which we want to partition the data. It is candidate_gender in this case.

● We have sorted our score data in descending order.

● The **FIRST_VALUE()** function takes an argument as candidate_scores, this means that we will get the first value from the candidate_score column.

So what this code does is, We have applied the FIRST_VALUE() function on the candidate_score so the first value will be returned. It arranges the candidate_score in descending order that is the top scores are arranged in the table first. Now the partition is done based on gender so there will be two partitions male and female. Now the FIRST_VALUE() function will simply give the 1st value of every partition.

The above code will give the top scorers from both of the partitions i.e. genders. The output looks like this:

You can see that the new column, top_scores gives the first value i.e. the top scores for both the gender categories.

So this is how we can find the first value of any partitions.

 **Example 2: How to Get the Last Value of a Partition in PostgreSQL**

We can similarly get the last value of a partition in PostgreSQL. The specific function used for it is the LAST_VALUE function. Let’s take the exact example as we did above and find the last value for the partitions. The query can be written as:
    
    
    SELECT *, LAST_VALUE (candidate_score) 
     OVER (
     PARTITION BY candidate_gender
     ORDER BY candidate_score DESC 
      RANGE BETWEEN -- A description of this constraint is provided below
      UNBOUNDED PRECEDING AND 
      UNBOUNDED FOLLOWING
       ) AS lowest_marks
     FROM test_scores;

This syntax is almost the same as previous one, just there is one change i.e.:

 **“RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING”** This statement is made up of two-row clauses. The purpose of the row clauses is to specify the window frame relative to the current row. The **UNBOUNDED PRECEDING** gives all rows that are present before this/current row and the **UNBOUNDED FOLLOWING** means all rows that are present after this/current row. We have defined our window range this way.

The output of the above query is:

The query has returned the last value for each partition. The last value gives the lowest marks from each partition.

Using the same approach, the last value from a partition can be found. Any nth value can also be found similarly. Let’s see how.

 **Example 3: How to Get the nth Value of a Partition in PostgreSQL**

We can get the nth value for partitions in a similar way. We will need to set and specify the offset as well. The offset will be an integer representing the n. For instance, to get the 3rd value, we will specify the offset as 3.

Let’s see how to query this.
    
    
    SELECT *, NTH_VALUE (candidate_score,3) 
     OVER (
     PARTITION BY candidate_gender
     ORDER BY candidate_score DESC 
      RANGE BETWEEN UNBOUNDED PRECEDING AND -- description of this constraint is provided above
      UNBOUNDED FOLLOWING
       ) AS third_position
     FROM test_scores;

The query is the same as in the above cases additionally we have specified the offset as 3.

The output of this query will give the 3rd value for both of the partitions. The output looks like this:

So this is how all the functions work.

 **Conclusion**

We can get the first, last, and any nth value from each partition. The **FIRST_VALUE()** function takes in the column name from where we will get the first value similarly in the **LAST_VALUE()** function. The **NTH_VALUE()** function takes 2 arguments the first is the column name from which we want to get the nth specified function and the second argument is the offset that specifies the value we want to get. In this article, we have discussed how to get the first, last, and nth values from each partition in detail with practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-first-last-and-nth-value-of-a-partition-in-postgres/)

---

# How to Run PostgreSQL Queries in psql

> First, establish a connection with the postgres database from psql, after that, you can run all the PostgreSQL queries like DDL and DML in psql in similar ways…

The **SQL Shell** , better known as **psql** is an interactive command line interface or a terminal on which the PostgreSQL queries are run. We can administer the PostgreSQL using the psql.This will teach us to execute the PostgreSQL queries in psql.

Let’s get started with the learning.

 **How to Run PostgreSQL Queries in psql?**

The psql can be used as an alternative for the GUI-based PostgreSQL management tools, for writing and executing PostgreSQL queries. To run the PostgreSQL queries in psql, firstly we have to create a **connection with database**. This can be done in two ways:

 **Method 1: Connection With the Database Using Command Prompt**

We can use the command Prompt to connect to the database. Open the **cmd**. To make sure your psql is installed you can run “psql --version”. Running this will ensure the psql installation by retrieving the version of your psql. In my case, it gave the output as:

It means that psql version 15.4 is installed in my system. Next, run the following pattern customized according to your case to make a connection to the database:
    
    
    psql -d database_name -U username

Where “-d” is the shorthand notation for the database name and “-U” for username.

By default, when we install PostgreSQL, the database and username are created as “Postgres”. So we run the following query to get connected to that database:
    
    
    psql -d postgres -U postgres

Executing this command in the CMD prompts you to enter the password, this password is the same that you chose to install PostgreSQL on your system. After you enter the correct password, the connection with the database will be successfully established.

If the **“postgres=#”** appears, this **confirms the connection with the database**.

We can do the same thing with another approach.

 **Method 2: Connection With the Database Using psql**

This method is easier than the first one. Simply just launch the **psql application**. After doing so, the application will prompt you to enter the server, database, port, username, and password. You can skip the first 4 fields by pressing the “Enter” key from the keyboard. The application will then prompt you to enter/insert the password. You need to enter the password, this password is the same that you chose to install PostgreSQL on your system. After you enter the correct password, the connection with the database will be successfully established.

Again the **“postgres=#”** confirms the database connection.

Till now, we have successfully connected to the database. Now we can get started with the psql.

 **Getting Started With psql**

There are various meta-commands that we use in psql. The basic meta-command that can be used to get help is:
    
    
    \?

Running this meta-command will provide you with some assistance with the other meta-commands. It will return meta commands for psql like this:

We have already discussed the [psql meta-commands](<http://www.commandprompt.com/education/a-comprehensive-guide-on-psql-meta-commands>) in another article. You can head over to that article to understand them in detail.

Now we will be studying how to use the DDL and DML queries in psql.

 **Using DDL and DML in psql**

We can also use the [DDL](<https://www.commandprompt.com/education/postgresql-data-definition-language-ddl/>) and [DML](<https://www.commandprompt.com/education/postgresql-data-manipulation-language-dml/>) that are used in PostgreSQL in psql as well.

We can create, update, and delete the database, table, etc. using these commands and queries. To proceed with this article we will be running the PostgreSQL DDL and DML queries in psql. Let’s see how these queries work in psql.

 **Creating a Database**

We can create a database in psql by executing the following command.
    
    
    CREATE DATABASE   db_name;

Let's create a database named “psql_database”. The query written for this purpose will be:
    
    
    CREATE DATABASE   psql_database;

This query will successfully create a database which can be ensured by the following output:

We can see all the created databases in our system by running the following command:
    
    
    \l

Executing this command will return all the listed databases present.

We can see that our recently created database is present in the list of databases, which can also ensure its creation.

 **Deleting a Database**

We can also drop an existing database same as we can do in pgAdmin. The general syntax looks like this:
    
    
    DROP DATABASE db_name

After the DROP DATABASE statement, you have to specify the name of the already existing database you want to drop/delete like this:
    
    
    DROP DATABASE psql_database;

 **Creating a Table**

We can also create a table by running the basic DDL command of a table. The basic syntax for creating a table is:
    
    
    CREATE TABLE tab_name(col_name dat_type constraint_name);

The syntax is simple, you just need to specify the name of the table you want to create and within brackets, you need to specify the column names.

I’ll create the table name “psql_test_table”. For that, the query will be:
    
    
    CREATE TABLE psql_test_table(table_id SERIAL PRIMARY KEY, table_name VARCHAR(100) NOT NULL);

Executing the above query will create a table in psql, which can be proven by:

We can see the list of all the created tables in psql by running the “ **\dt** ” meta-command. The creation of a table can also be ensured by running this meta command:

We can see the name of the newly created table in the list of tables which makes sure that it has been created.

We can also add/insert the data values in the Postgres table.

 **Inserting Values in a Table**

To insert the values in the table we have created above, we'll be executing the following query:
    
    
    INSERT INTO psql_test_table(table_name) VALUES ('table_name_1'), ('table_name_2'), ('table_name_3');

We will successfully be able to insert values into the table with the above query. The insertion can be ensured if the output looks like this:

In this way, we can insert the values in the table.

 **Selecting the table**

Now to see the inserted values in the table we will execute the **SELECT** query. This query will return the table in which the values are inserted. The query is:
    
    
    SELECT * FROM psql_test_table;

This query will return the table with inserted values like this:

This is how we can select the table.

 **Rename the Table**

We can also rename the table by making use of the ALTER statement. The ALTER command is a DML command used to perform changes to rename the table considered above, we will write the following command:
    
    
    ALTER TABLE psql_test_table RENAME TO new_psql_test_table;

The table will be successfully altered for its name by executing this command:

We will run the \dt meta-command to see if the name changes or not. Running the command returned the following output:

This ensures that the table has been renamed from **“psql_test_table”** to **“new_psql_test_table”**.

 **Dropping a Table**

We can delete a table that is no longer in use. The syntax of deletion of our table is:
    
    
    DROP TABLE new_psql_test_table;

The table is successfully dropped using this syntax.

We will execute the \dt meta-command to see if the table is still present or not. The output after running the command is:

We can see that there is no such table existing in the list of tables.

This way we can execute any Postgres query in SQL Shell and get the desired results.

 **Conclusion**

To run PostgreSQL queries in SQL Shell or psql, first, open the psql, and access the postgres database by specifying the appropriate privileges. Once you are connected to postgres database, you can run all the PostgreSQL **DDL** and **DML** queries in psql in similar ways as you run them in pgAdmin. In this article, we have seen execution of some of the PostgreSQL queries in psql, with proper implementation, other queries can also be executed in a similar way.

---
[View this page online](https://www.commandprompt.com/education/how-to-run-postgresql-queries-in-psql/)

---

# How to Remove all the Spaces From a Column in PostgreSQL

> Sometimes we need to remove all the spaces from the column in PostgreSQL. This thing is possible in PostgreSQL using a function named “REPLACE()”. In this blog…

Sometimes we need to remove all the spaces from the column in PostgreSQL. This thing is possible in PostgreSQL using a function named “ **REPLACE()** ”. In this blog, we will be discussing the method using which we can remove all the white spaces present in the column. Let’s get started with the article.

 **How to Remove All the Spaces From a Column in PostgreSQL?**

We can remove the white spacing from start, end and both using the regexp_replace() function and the trim() function by using their variants. However, removing all the spaces from a column is not possible using these two functions.

To remove all the spaces from a column in PostgreSQL, we use the simple **REPLACE() function**. This function finds a string or a substring in a string and replaces it with the specified substring. It basically accepts 3 parameters. The 1st argument is the string or the column’s name from where the query will find the string/substring(to replace) specified as the 2nd parameter. The last parameter is the substring which is the replacement. To understand this function in detail, you can see the article on [REPLACE() function](<https://www.commandprompt.com/education/how-to-replace-a-string-using-replace-function-in-postgresql/>). Let’s consider an example for more clarity.

 **Example: Remove all the Spaces From a String in PostgreSQL**

We will now see this function is used to remove all the whitespaces from a string. Consider the following query:
    
    
    SELECT REPLACE(' This is Command Prompt ',' ','');

In the above syntax:

● We can see that we have provided a string to the function in which the replacement will occur.

● The second parameter is specified as a space. This means that the function will replace all the spaces from the string.

● The third argument is an empty string. This shows that the spaces will be removed.

Let’s see the output for the above query:

The function has replaced all the whitespaces from the start, end, and in the string. This is how we can remove whitespaces from a string. Now let’s consider a table named “simplesearch” having a column named “document”.

Now if we want to remove all the spaces from the column we will write the following query:
    
    
    SELECT *, REPLACE(document,' ','') AS no_whitespaces FROM simplesearch;

The query will return a row with no whitespaces as they are removed. The output for the above query will be:

The output given above clearly shows that there is no white space in any entry of each column.

 **Conclusion**

We can remove all the whitespaces from a column in PostgreSQL by making use of the **REPLACE()** function. In the function, we need to specify the string or column name from where we want to replace the substring (specified as the second argument) with the substring (specified as the third argument). In this article, we have learned how the REPLACE() function assists in removing all the white spaces from a column.

---
[View this page online](https://www.commandprompt.com/education/how-to-remove-all-the-spaces-from-a-column-in-postgresql/)

---

# PostgreSQL json_extract_path() Vs json_extract_path_text() - What's the Difference

> The Postgres json_extract_path() function and json_extract_path_text() function both are JSON functions that are used to extract the nested values from JSON va…

JSON data type is also used to store data in key-value pairs. We can fetch the JSON data using some built-in functions that are being provided by PostgreSQL. In this article, we will be drawing a comparison between the two significant functions used to extract the JSON nested value present on a specific path. These functions are; json_extract_path() Vs json_extract_path_text() function. Let’s see what they do and how they are different.

 **PostgreSQL json_extract_path() Function**

This PostgreSQL JSON function, the json_extract_path() function, retrieves the nest JSON value from the JSON value present on the path that is specified in the function. The basic syntax of this function is:
    
    
    json_extract_path(json_value JSON, VARIADIC Path TEXT[])

In the above syntax:

● The **“json_extract_path()”** function takes in 2 arguments.

● The **“json_value”** specifies the JSON value from which the nested value will be extracted.

● The **“VARIADIC Path TEXT[]”** is the list that gives us the path to the value we want to extract.

The json_extract_path() function returns the nested **“JSON value”** specified by the path from the “json_value”. If the path specified is not valid, the function gives NULL.

 **PostgreSQL json_extract_path_text() Function**

This PostgreSQL JSON function, the “json_extract_path_text()” function, retrieves the nest JSON value from the JSON value present on the path that is specified in the function and returns the result in the form of tex **t**. The basic syntax of this function is:
    
    
    json_extract_path_text(json_value JSON, VARIADIC Path TEXT[])

In the above syntax:

● The **“json_extract_path_text()”** function takes in 2 arguments.

● The **“json_value”** specifies the JSON value from which the nested value will be extracted.

● The **“VARIADIC Path TEXT[]”** is the list that gives us the path to the value we want to extract.

The json_extract_path_text() function returns the nested JSON value specified by the path from the “json_value” as a text. This simply implies that the return type of the json_extract_path_text() function is **TEXT**. If no valid path is found, the function returns NULL.

 **PostgreSQL json_extract_path() Vs json_extract_path_text() - What 's the Difference?**

In the above sections, the working of both functions is given that is they their working is almost the same. Both functions refer to the specified path in the specified JSON value. But there is a distinction in both functions. The difference is in the return data type of both of the functions i.e.

● The PostgreSQL **json_extract_path()** function returns the JSON value of the **JSON** **data type**.

● While the PostgreSQL **json_extract_path_text()** function returns the value in the **TEXT** **data type**.

Let’s implement both functions to see the difference.

 **Example : The json_extract_path() Vs json_extract_path_text() Function in PostgreSQL**

Consider an example that illustrates the working and difference between the json_extract_path() function and json_extract_path_text() function in PostgreSQL and how the values are retrieved from the JSON array at the specified path. Consider the query:
    
    
    SELECT
      json_extract_path('["Peter", "Katherine", ["Oliver", "Mendis"]]', '0')
      AS val_extract_path,
      json_extract_path_text('["Peter", "Katherine", ["Oliver", "Mendis"]]', '0')
      AS val_extract_path_text;

By implementing these queries we will get the value at index 0 in JSON value given as the first parameter. Both queries will return the same output but the data type of both will be different. The output of the above queries is:

We can see that the returned data type of both functions is different. The **json_extract_path()** function returns the value in **JSON** data type while the **json_extract_path_text()** function returns the value in **TEXT** data type. This is the difference between both functions.

 **Conclusion**

The PostgreSQL **json_extract_path() function** and **json_extract_path_text() function** both are JSON functions that are used to extract the nested values from JSON values specified at a certain path. That JSON value and the path both of these are provided to the functions as arguments. These functions return the same value but the difference between both these functions is in the returned data type. The json_extract_path() function returns the value in **JSON data type** while the json_extract_path_text() function returns the value in **TEXT data type**. This article covered the basic concept of both of these functions and their distinctions and differences.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_extract_path-vs-json_extract_path_text-whats-the-difference/)

---

# Postgres Drop Function If Exists

> In PostgreSQL, the DROP and DROP IF EXISTS statements are used to delete any existing database object. We can drop a database, table, column, function, any ext…

In PostgreSQL, the DROP and DROP IF EXISTS statements are used to delete any existing database object. We can drop a database, table, column, function, any extension, etc. in Postgres by using the DROP or DROP IF EXISTS statements. These statements do the same job of dropping an object but they also have a difference in their working. We will specifically talk about the DROP FUNCTION IF EXISTS statement.

The DROP FUNCTION statement drops/deletes a specified function. But what is the function that is specified does not exist already? The DROP FUNCTION statement will definitely throw an error in such a case. To handle such cases, **DROP FUNCTION IF EXISTS** is used. It drops the specified function only if that function exists and, in this way,, it avoids error.

Let’s see how the DROP FUNCTION IF EXISTS statement works.

 **How Does the Postgres Drop Function If Exists Work?**

The **DROP FUNCTION IF EXISTS** drops the specified function if it exists in the database. This function will not throw an error if the function is not present in the database. The fundamental and basic syntax for the DROP FUNCTION IF EXISTS statement is given as:
    
    
    DROP FUNCTION IF EXISTS func_name (args)
    [Cascade | restrict];

In the above syntax:

● After the **DROP FUNCTION IF EXIST** statement, we have to write the function’s name that we want to drop.

● We can optionally use the **CASCADE** and **RESTRICT** options.

Let’s see how this statement works with the help of an example.

 **Example: Postgres Drop Function If Exists**

Let’s consider the following query for dropping a function through the **DROP FUNCTION IF EXISTS** statement:
    
    
    DROP FUNCTION IF EXISTS example_function;

The **“example_function”** is the user-defined function already existing in my database. The above query is written to drop the function using the DROP FUNCTION IF EXISTS statement. The query will simply drop the function because it is already existing. The output is:

We can see that the function has been dropped.

Now consider the case for dropping a function that does not exist. The query will be:
    
    
    DROP FUNCTION IF EXISTS non_existing_function;

The above query will not return an error as in the case of the DROP function. The DROP FUNCTION IF EXISTS statement will instead raise a notice and the other query parts will work fine.

The output for the above query is:

If we write another statement with this we can see that if the function does not exist it will not return an error. It will let the other statement execute properly without causing an error. Like this:

We can see that dropping a non-existing function has not caused any error if we used the **DROP FUNCTION IF EXISTS** statement and has not disturbed the execution of the second statement.

That is how the Postgre only if that function exists and in this way, it avoids error. While the DROP FUNCTION statement also performs the same function, but it throws an error if the function does not exist. In this blog, we have seen the functioning of the PostgreSQL DROP FUNCTION IF EXISTS statement in detail using practical examples.SQL **DROP FUNCTION IF EXISTS**.

 **Conclusion**

 **DROP FUNCTION IF EXISTS** drops the specified function only if that function exists and in this way, it avoids error. While the **DROP FUNCTION** statement also performs the same function, it throws an error if the function does not exist. In this blog, we have seen the functioning of the PostgreSQL DROP FUNCTION IF EXISTS statement in detail using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgres-drop-function-if-exists/)

---

# How to Extract First N or Last N Characters From a Column in PostgreSQL

> We can extract the first and last n characters from a table column and use them as per our needs. This can be done by utilizing the LEFT() and RIGHT() function…

PostgreSQL stores data in the database in the form of tables. We can manipulate these data using the functions offered by PostgreSQL itself. Similarly, PostgreSQL also provides us with functions using which we can extract some information. Sometimes we want to get some characters from the start and end of the column data. This post will assist us in extracting the first n or last n characters from a column in PostgreSQL. Let’s see how it is done.

 **How to Extract First N or Last N Characters From a Column in PostgreSQL**

We can extract any specified number of characters from the start or end of any entry in any column. the **LEFT()** and **RIGHT()** functions can be utilized for this purpose respectively. Let’s see how both these functions work.

 **How to Extract First N Characters From a Column in PostgreSQL**

In order to get the n characters from the start, of a column, we will make use of the **LEFT()** function. The basic syntax of this function is:
    
    
    LEFT(Main_String, no_of_characters)

In the above syntax:

● The **LEFT()** function takes in 2 parameters.

● The 1st argument is the **string** from which we wish to retrieve the characters.

● The 2nd parameter is an **integer,** that depicts the **number of characters** to be fetched from the left.

The LEFT() function will give the particular number of characters from the left i.e. the start of the main string.

 **Note:** The space between words is also considered as a character.

 **Example 1: Extract the First N Characters From a Column Using the Left() Function**

Consider the following query to get the first six characters from the specified string from the start:
    
    
    SELECT LEFT('This is command prompt. ',6);

The query will return the first 6 characters from the string. The above query returns the following output:

We can also specify the **negative integer** in the function. The negative integer will depict that “return all the character except the last n”. For example, if we specify “-9” as the second parameter the query will return all the characters starting from left except the last 9 characters like this:

We can also get the specified number of characters from the table columns. For this let's consider the table named “simplesearch” having a column named “document”.

We can get the first 5 characters from each document using the following query:
    
    
    SELECT LEFT(document,5) FROM simplesearch;

The query results in the following output:

The above output advocated the accurate working of the LEFT() function in the tables as well. Next, we learn to get, in return, n characters from the last in the PostgreSQL column.

 **How to Extract Last N Characters From a Column in PostgreSQL**

In order to get the n characters from the start, of a column, we will make use of the **RIGHT()** function. The syntax of RIGHT() function is:
    
    
    RIGHT(Main_String, no_of_characters)

In the above syntax:

● The **RIGHT()** function takes in 2 parameters.

● The 1st argument is the **string** from where we wish to retrieve the characters.

● The 2nd parameter is an **integer,** which depicts the **number of characters** to be fetched from the right.

The RIGHT() function will give us the particular number of characters from the right i.e. end of the main string.

 **Note:** The space between words is also considered as a character.

 **Example 1: Extract the Last N Characters From a Column Using the Right() Function**

Consider the following query to get the last characters from the specified string from the end
    
    
    SELECT RIGHT('This is command prompt. ',6);

The query will return the last 6 characters from the string. The above query returns the following output:

We can also specify the negative integer in the function. The negative integer will depict that “return all the character except the first n”. For example, if we specify “-9” as the second parameter the query will return all the characters starting from right except the first 9 like this:

We can also get the specified number of characters from the table columns. Consider the same table named “simplesearch” that we considered above. We can get the last 5 characters from each document using the following query:
    
    
    SELECT RIGHT(document,5) FROM simplesearch;

The query results in the following output:

The above output advocated the accurate working of the RIGHT() function in the tables as well.

We have seen how to get the first n and last n characters from the column in PostgreSQL. So that was all from the topic.

 **Conclusion**

We can extract the first and last n characters from a table column and use them as per our needs. This can be done by utilizing the **LEFT()** and **RIGHT()** functions provided by PostgreSQL. Both of the functions take two parameters; the first one is the string or the column name from where we want to retrieve the characters and the second one is the number of characters we want to retrieve either from the start or the end. In this post, we have discussed the working of these two functions in detail with the help of practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-extract-first-n-or-last-n-characters-from-a-column-in-postgresql/)

---

# How to Use inet_client_port() and inet_server_port() Functions in Postgres

> The inet_client_port() function gives the IP port number of the current client and the inet_server_port() function returns the IP port number of the server

Sometimes we need to get the system information in PostgreSQL. This information can be related to the user/owner, versions, client and server ports and their addresses, etc. To get this information, PostgreSQL provides many functions. This blog will particularly be covering the two functions that are used to get the client and server port numbers. These functions are inet_client_port() and inet_server_port(). Let’s discover the functionality of these functions.

 **How to Use inet_client_port() Function in PostgreSQL**

The function **inet_client_port()** gives the **IP port number of the present/current client**. The basic syntax of this function is:
    
    
    inet_client_port()

The function does not need any argument and returns the IP port number of the current/present client. The returned IP port number has an **INTEGER** data type.

Now we will see the implementation of this function for a better understanding of the working of the inet_client_port() function. For this you simply need to run the following query in the psql/SQL Shell:
    
    
    SELECT inet_client_port();

The query returns the IP port number of the current client. The output is as follows:

We can see that the above output has returned the IP port number of the client.

So this is how this function works. We can also get the server’s IP port number. Let’s see how we can do this.

 **How to Use inet_server_port() Functions in PostgreSQL**

The function **inet_server_port()** gives the **IP port number of the server that accepts/receives the current connection**. The basic syntax of this function is:
    
    
    inet_server_port()

The function does not need any argument and returns the IP port number of the server that accepts the current connection. The returned IP port number has an **INTEGER** data type.

Now we will see the implementation of this function for a better understanding of the working of the inet_server_port() function. For this, you simply need to run the following query in the psql/SQL shell:
    
    
    SELECT inet_server_port();

The query returns the IP port number of the server that accepts the current connection. The output is as follows:

We can see that the above output has returned the IP port number of the server.

 **Conclusion**

The **inet_client_port()** and **inet_server_port()** functions come under the category of system information function in PostgreSQL. These functions give an Integer. The inet_client_port() function gives the IP port number of the present/ **current client** and the inet_server_port() function returns the IP port number of the **server** that accepts the establishment of the connection. This article comprised the working and usage of both these functions with their implementation.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-inet_client_port-and-inet_server_port-functions-in-postgres/)

---

# How to Drop a Tablespace in PostgreSQL

> To drop a tablespace in Postgres, execute the DROP TABLESPACE statement followed by the name of the tablespace to be discarded.

To store the data of the database, we need to offer some location to the data on the disk. This location is called the tablespace in PostgreSQL. The data can be tables, triggers indexes, etc. However, if a tablespace is no longer needed, it can be dropped in PostgreSQL. The tablespace can be dropped by the owner of the tablespace. In this blog, we will drop the tablespace in PostgreSQL.

 **How to Drop a Tablespace in PostgreSQL?**

We can drop a tablespace in Postgres. The basic syntax for dropping the tablespace is given as:
    
    
    DROP TABLESPACE [IF EXISTS] tabsp_name;

In this syntax:

● We write the command **DROP TABLESPACE** to drop the tablespace.

● The **IF EXISTS** clause is also written which will drop the tablespace only if it exists. If the tablespace does not exist, it will just raise a notice. In case this clause is not written it will simply throw an error if it encounters a case where a tablespace does not exist.

● These statements are followed by the name of the tablespace.

Let's see the dropping of the tablespace using an example.

 **Example: Dropping a Tablespace in Postgres**

Consider the following queries to drop a tablespace. First of all, we will create a tablespace named “tablespace”.
    
    
    CREATE TABLESPACE tablespace
    LOCATION 'C:\Program Files\PostgreSQL\15\data';

This will successfully create a tablespace. The next step is to create a database for our tablespace like this:
    
    
    CREATE DATABASE test_database 
    TABLESPACE = tablespace;

The database will be created. After that, we will create a new table in the database with the following query:
    
    
    CREATE   TABLE example (
      serial_no serial PRIMARY KEY,
      title VARCHAR (255) NOT NULL
       ) TABLESPACE tablespace;

The table will be created. To get objects of the “tablespace” tablespace, execute the following query:
    
    
    SELECT
      ts.spcname,
      cl.relname
       FROM
      pg_class cl
       JOIN pg_tablespace ts 
      ON cl.reltablespace = ts.oid
       WHERE
      ts.spcname = 'tablespace';

This query will return all the objects in the tablespace. The output of the query looks like this:

Now we will try to drop the tablespace with the following query:
    
    
    DROP TABLESPACE tablespace;

This will give an error that the tablespace is not empty.

The tablespace cannot be dropped until it is not empty. So we can simply drop the database.
    
    
    DROP DATABASE test_database;

This statement will simply drop the database like this:

Or instead of deleting the database, we can also shift it to some other tablespace. Like in the below query, we have shifted the database to”pg_default” using the ALTER TABLESPACE statement. The query is:
    
    
    ALTER DATABASE test_database
    SET TABLESPACE = pg_default;

By following any of the above methods, we can now delete the tablespace as the tablespace becomes empty now so execute the following query again:
    
    
    DROP TABLESPACE tablespace;

The query has dropped the tablespace successfully.

So this is how the tablespace is dropped.

 **Conclusion**

To drop a tablespace in Postgres, execute the DROP TABLESPACE statement followed by the name of the tablespace to be discarded. In this blog, we got to know about dropping tablespace using practical examples. As we know the tablespace contains the database and tables. So we can not directly drop them if they are not empty. We will have to delete the database in them or may have to shift the database to some other tablespace. Then we can drop a tablespace.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-tablespace-in-postgresql/)

---

# How to Alter a Tablespace in PostgreSQL

> To alter a tablespace in PostgreSQL, the “ALTER TABLESPACE” statement is used with “RENAME TO”, “OWNER TO”, and “SET” clauses.

In PostgreSQL, the tablespace offers the location on the disk where we can store all the data of the database. The data may include tables, triggers indexes, etc. The tablespace is usually used to map the logical name onto the physical address on the disk. Sometimes we need to alter the tablespace. The tablespace can be altered in many ways. In this post, we will learn about how we can alter the tablespace in PostgreSQL.

 **How to Alter a Tablespace in PostgreSQL?**

We can alter our tablespace in many ways. We may need to alter the name of the tablespace i.e. rename the tablespace, change the owner of the tablespace, or maybe alter some parameter name. Let's try to alter these, one by one.

 **Rename the Tablespace**

To change the name of the tablespace we will have to alter it. We use the ALTER TABLESPACE RENAME TO statement to rename the tablespace. The basic syntax looks like this:
    
    
    ALTER TABLESPACE tabsp_name 
    RENAME TO newName;

 **Example: Rename the Tablespace Using the ALTER statement**

Let’s consider an example for this particular case:
    
    
    ALTER TABLESPACE example_tablespace
    RENAME TO tablespace;

We created a tablespace named example_tablespace in our previous article. Now we can rename the tablespace by using the above query. The output of the above query will be:

The name of the tablespace has been altered and the tablespace has been renamed to “tablespace” from “example_tablespace”.

 **Change/Switch the Owner of Tablespace**

We can also change/switch the owner of any tablespace by using the ALTER TABLESPACE OWNER TO statement. The basic syntax for such a query is given as:
    
    
    ALTER TABLESPACE tabsp_name 
    OWNER TO newOwner;

Specify the name of the new owner after the OWNER TO clause. Let's do it using an example.

 **Example: Changing the Owner Name Using the ALTER Statement**

Let’s change the name of the owner of the tablespace “tblsp_name” to “joseph”. The query will be:
    
    
    ALTER TABLESPACE tblsp_name 
    OWNER TO joseph;

By executing this command we will get:

 **Changing any Parameter Value**

We can also change the value of any parameter using the ALTER statement. The basic query for this is:
    
    
    ALTER TABLESPACE tabsp_name 
    SET para_name = val;

These were the use cases of the **ALTER** statement. We can rename a tablespace, we can switch/change the owner of the tablespace and we can replace/change the value of any parameter.

 **Conclusion**

To alter a tablespace in PostgreSQL, the “ALTER TABLESPACE” statement is used with “RENAME TO”, “OWNER TO”, and “SET” clauses. By doing so, we can rename a tablespace, we can switch/change the owner of the tablespace, and can replace/change the value of any parameter. In this article, we have learned to do all this by making use of the ALTER statement.

---
[View this page online](https://www.commandprompt.com/education/how-to-alter-a-tablespace-in-postgresql/)

---

# How to Log Queries in PostgreSQL

> To log queries in Postgres, first, locate the config file, then locate the data directory path. After that, configure the configurations and direct the output …

PostgreSQL **logs** are text files that give us all the information about what events are occurring in our database system. These valuable resources include who has access to which component, what queries are in progress, what settings have changed, troubleshooting problems, tracking performance, and their issues, and tracing the database activity.

This write-up will demonstrate how to log queries in Postgres.

 **How to Find the Location of Logs in PostgreSQL?**

If we want our PostgreSQL to start making our log files, we must enable the _logging_collector_ parameter. By doing so, your logs will start going into a default location specified by your OS. There are the default directories of some of the most commonly used operating systems:

● Windows: C:\Program Files\PostgreSQL\15\data\pg_log

● Debian-based system: /var/log/postgresql/postgresql-x.x.main.log. X.x.

● Red Hat-based system: /var/lib/pgsql/data/pg_log

We can also change the location directory of where log files are to be saved. This is done by enabling the log collector. We can specify our new custom directory, in which we want to save the log file, in the log_directory parameter.

 **How to Log Queries in PostgreSQL?**

It is easy to enable logging temporarily in PostgreSQL by making some changes in the configuration settings and then restarting the server. But we will look at how to log files permanently. Below are the steps to log queries in PostgreSQL:

 **Step 1: Find Configuration Files**

If we need to know where **_PostgreSQL.config_** is located, we have to connect it to the Postgres client(pgsql) for which the “ ** _SHOW config_file_** _”_ statement is used.
    
    
    SHOW config_file

This will give the location of the config file. In my case, it is:

 **Step 2: Locate the Data Directory Path**

Now we have to find the path of the data directory. We will use the **SHOW** statement again:
    
    
    SHOW data_directory

Executing the “SHOW” command will retrieve the data directory’s path. In our case, this retrieved path is:

It is possible that the configuration and the data directory are located on the same path as in my case. However, it might be different in some cases.

 **Step 3: Configure the Postgres to Generate Output Log**

Now open the config file(the location of which you have traced earlier) with the text editor of your choice. Scroll down to the “REPORTING AND LOGGING” part. The most important sections in this part are **_log_destination_** and **_logging_collector_** _._ Given below are the recommended settings that are to be done if not present already:

In my case, it was, _log_destination = 'stderr_ ** _'_** , in which I replaced _‘stderr’_ with _‘_ ** _csvlog_** _’._ Doing these settings will basically reflect that we are instructing Postgres to generate/create the logs in **_CSV_** **format** and show them to the **_log_** folder.

 **Step 4: Restart the Postgres Service**

Now we have to restart the Postgres service, to reflect the changes on it. Performing the restart may differ from OS to OS. Since I am using Windows the way I did it is by ‘ **Services Manager** ’. For this purpose, search and open the Services from the taskbar and follow the screenshot attached below:

 **Note:** To learn more ways to restart your Posgres service head over to the following [Postgres guide](<https://www.commandprompt.com/education/how-to-start-stop-or-restart-the-postgresql-server>).

 **Step 5: Check the Log Generation**

Now that we have restarted the system, we will have to check the log generation because the protocol has to start immediately. To check this we have to scroll to the data directory/log of the Postgres installation. We have already found the path to the data directory earlier now just add ‘ **\log’** to navigate to the log directory. We have done this because we reflected the logs output to the “log” in step no 3.
    
    
    C:\Program Files\PostgreSQL\15\data\log

You can clearly see that the log files in CSV format have been created in the directory.

So this is how queries are logged in PostgreSQL.

 **Conclusion**

To log queries in Postgres, first, locate the config file, then locate the data directory path. After that, configure the configurations and direct the output to the log file. Finally, restart the Postgres service to check if the log files have been generated yet or not. In this article, we have seen a procedure to log queries in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-log-queries-in-postgresql/)

---

# PostgreSQL UPDATE Vs. UPDATE...FROM - What's the Difference

> The UPDATE statement updates the table&#x27;s data with the new values provided in the query. While the UPDATE FROM statement updates a table&#x27;s data in accordance w…

In PostgreSQL, we can manipulate the database data in a customized way using the [DML](<https://www.commandprompt.com/education/postgresql-data-manipulation-language-dml/>) clauses. Using these clauses, we can **SELECT** , **INSERT** , **DELETE** , and **UPDATE** data. The data can be updated in a way that we can set the value of any row to a new value and we can also update the data of one table according to the data of another table. This is the function or **UPDATE** and **UPDATE FROM** statements respectively.

This write-up will draw a comparison between the UPDATE and the UPDATE FROM statement in PostgreSQL.

 **Postgres UPDATE Statement**

The **UPDATE** statement works in a simple way in that it updates the pre-existing value in the table with a new value. Let’s update the name of a student as “Jack” from the table “attendance_list”.

The query can be written as:
    
    
    UPDATE attendance_list
     SET st_name = 'Jack'
     WHERE st_id = 7
     SELECT * FROM attendance_list;

The above query will update the name of a student having ID 7. The output is:

We can see that the name of the student has been updated from “ **John** ” to “ **Jack** ”.

 **Postgres UPDATE FROM Statement**

The **UPDATE FROM** statement has the extended functionality as of the UPDATE statement. The UPDATE FROM statement is also used to update the table values. In addition to that, the UPDATE FROM statement is used to update the value of one table according to the other.

For example, if we want to update the value in the table “attendance_list” to get the scores of each candidate, from the other table named “test_scores” concatenated with their names.

The table “attendance_list” is given as:

The table named “test_scores” containing the data of candidates and scores is given as:

The query can be written as:
    
    
    UPDATE attendance_list a
     SET st_name = st_name || ' got ' || b.candidate_score
     FROM test_scores b
     WHERE a.st_name = b.candidate_name
     RETURNING st_id,st_name;

We will get the updated “attendance_list” table having the st_name column with updated value as the name of student/candidate concatenated with the scores through the “got” string. The output is illustrated below:

So this is how the UPDATE FROM statement functions.

 **PostgreSQL UPDATE Vs. UPDATE...FROM - What 's the Difference**

The **UPDATE** and **UPDATE FROM** statements are used to update the data in the Postgres table. Both these statements update the table’s data, but they work differently. The difference between the **UPDATE** and **UPDATE FROM** statements is only that the UPDATE FROM statement extends the functionality of the UPDATE statement. In the UPDATE FROM statement, we need to have two tables; the one that is to be updated and the one according to which the value has to be updated.

 **Conclusion**

The **UPDATE FROM** provides the extended functionality of the **UPDATE** statement. The UPDATE statement updates the table's data with the new values provided in the query. While the UPDATE FROM statement updates a table's data in accordance with the values of the other table. This is the difference between both statements. This blog illustrated the difference between the UPDATE and the UPDATE FROM statements with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-update-vs-updatefrom-whats-the-difference/)

---

# How to Write Case-Insensitive Queries in PostgreSQL

> There are four methods to write the case-insensitive matching in PostgreSQL. Those are CITEXT extension, LOWER() function, ILIKE operator, and Case conversion.

We need to use **case-insensitive** queries in order to get better results while performing some operations, especially search operations. Consider a case where we are searching for a specific term, but we use lowercase to specify the term to search for. The search results will return all the data where the data has occurred in the lower casing if we have used case-sensitive queries. But there might be some cases where the term is present but in upper case letters or even one upper case letter. The data associated with that term will not be returned by the research result in this case.

Under such circumstances, there comes the need for **case-insensitive** queries. The case-insensitive queries will return the search results without bothering about the case. Let’s see how can we query the case-insensitive queries in PostgreSQL.

 **How to Write Case-Insensitive Queries in PostgreSQL?**

There are several ways we can write the case-insensitive queries. All the methods are enlisted and discussed below one by one:

● Using the ILIKE operator.

● Using the CITEXT Extension.

● Using the LOWER function.

● Using Case Conversion.

Let’s go over them one by one.

 **Method 1: Write Case-Insensitive Queries Using the ILIKE Operator**

We can write case-insensitive queries by using the ILIKE operator. This operator is used for pattern-matching and particularly for case-insensitive pattern matching. Let’s see how this operator works.

 **Example: Case-Insensitive Search Using ILIKE**

Consider the table named “simplesearch” having a column named “document” consisting of all the texts in which we will be performing the search. Let’s see what the table looks like:

Now if we want to look for the term “ate” we will write the query as:
    
    
    SELECT document, document ILIKE '%ATE%' AS term_contained FROM simplesearch;

This will return all the boolean values showing the respective data/documents containing “ATE” or not irrespective of their case. The output of the query gives:

We can see that all the documents are returned along with a boolean value “true” or “false”, indicating whether "ate" is included in those documents or not. So this is how we can write case insensitive queries using the ILKIE operator.

To learn about the ILIKE operator in detail, you can head over to our article named [ILIKE Operator: Case-Insensitive Pattern Matching in PostgreSQL](<https://www.commandprompt.com/education/ilike-operator-case-insensitive-pattern-matching-in-postgresql/>).

 **Method 2: Write Case-Insensitive Queries Using the CITEXT Extension**

We can use the **CITEXT** extension to write the case-insensitive queries. This extension allows us to declare some fields using the CITEXT data type. This data type is a case-insensitive data type that can help us perform case-insensitive text comparisons. In order to utilize this CITEXT data type, we will have to create the CITEXT extension first.

 **Example: Case-Insensitive Search Using CITEXT**

Consider the table name “Students_Info” with CITEXT data type fields such as studentname, address, and city. The table is given as:

Now if we want to get data for “Alex” we can write the case-insensitive query as:
    
    
    SELECT * FROM students_info WHERE studentname = 'aLEx';

The output of the query will return the case-insensitive comparison of the “alex”. This can be advocated by the output itself. The output is:

We can see that the query has searched for the term “Alex” regardless of the case we specified while searching.

To learn CITEXT in detail, you can refer to the article named PostgreSQL CITEXT Data Type.

 **Method 3: Write Case-Insensitive Queries Using the LOWER() function**

We can also use the LOWER() function to write the case-insensitive queries. The LOWER() function takes in a string as a parameter and converts its case to its lowercase string. To learn about this function in detail you can see the [PostgreSQL LOWER() Function](<https://www.commandprompt.com/education/postgresql-lower-function-with-practical-examples/>) article. However, we will see here how can we do case-insensitive matching/searching using the LOWER() function.

 **Example: Case-Insensitive Search Using LOWER()**

Consider the same example as used above of the “students_info” table. The lower() function here in this case can be used like this:
    
    
    SELECT * FROM students_info WHERE LOWER(studentname) = LOWER('aLEx');

The above query will search for case-insensitive matching. The LOWER(studentname) will convert all the entries of studentname as lowercase and in this table, it will search for lowercase “aLEx”.

This will return the entry where the case-insensitive matching will occur. The output is:

This is how we can use the LOWER() function to write case-insensitive queries.

 **Method 4: Write Case-Insensitive Queries Using the Case Conversion**

Another method to write case-insensitive queries is using case conversion i.e. by creating a lower or upper function index on the column we want to perform matching. Indexing speeds up the querying results.

The query for our case can be written as:
    
    
    CREATE INDEX lower_col ON students_info (LOWER(studentname));
     SELECT * FROM students_info WHERE studentname = 'alEx';

The query will do the case-insensitive text comparison by indexing. The output for this query can be written as:

The same thing can be done by using the UPPER() function as shown below:
    
    
    CREATE INDEX upper_col ON students_info (UPPER(studentname));
     SELECT * FROM students_info WHERE studentname = 'alEx';

The output will again be the accurate case-insensitive matching. The output of the above query is:

So, this is how we can perform the case insensitive matching by creating a lower or upper function index on a specified column.

These were the four effective methods to write case-insensitive queries in PostgreSQL.

 **Conclusion**

Writing the case-insensitive queries is a crucial task to do in order to perform effective searching/matching in PostgreSQL. There are four methods to write the case-insensitive matching. The first one is by using the ILIKE operator, and the second in using the CITEXT extension. Using the LOWER() function also proves to be a good approach in writing case-sensitive queries and lastly creating the lower or upper function indexes is also a helpful approach. In this article, we have learned all these methods with their implementation to make the concepts clear.

---
[View this page online](https://www.commandprompt.com/education/how-to-write-case-insensitive-queries-in-postgresql/)

---

# How to Connect to PostgreSQL From Visual Studio Code

> To Connect to PostgreSQL From VS Code, launch the VS Code, press “CTRL + Shift + X” to open the Extensions view, select the “PostgreSQL” extension, and Install…

Microsoft offers an open-source, free-of-cost, and highly customizable code editor named **Visual Studio Code (VS Code)**. It offers numerous features, including cross-platform support, extensive extensions, linting tools, debugging capabilities, and many more. With all these features, it remains a top choice for users/developers worldwide.

Postgres is a widely used feature-rich RDMS that comes up with its own command line and graphical interfaces. Despite having its CLI and GUI interfaces, users can also access Postgres from VS Code by installing the appropriate extension. Doing this will allow users to interact with PostgreSQL databases directly within the VS Code editor.

This post demonstrates a step-by-step process of connecting to Postgres from Visual Studio Code.

 **How to Connect to PostgreSQL From VS Code**

An extension named “PostgreSQL” is used to connect to a PostgreSQL database from Visual Studio Code. It offers an interactive GUI to manage databases efficiently. Follow the below-provided step-by-step instruction to set it up:

 **Step 1: Install Postgres in VS Code**

First, launch the VS Code, and press “ **CTRL + Shift + X** ” to open the Extensions view:

Head into “Search Bar”, type “Postgres”, select the “PostgreSQL” extension owned by Microsoft, and click on the “Install” button to begin the installation:

The installation process will be completed within a few minutes, and it will enable PostgreSQL in VS Code.

 **Step 2: Launch the Command Palette**

Press the “ **Ctrl + Shift + P** ” to open the Command Palette. After that, search for “PostgreSQL: New Query” in the Command Palette and select the respective command from the drop-down:

After that, select a connection from the existing profiles or create a new connection profile:

 **Step 3: Provide the Connection Details**

Specify the connection details like hostname, database name, user name, and so on:

If everything goes fine, you will see the following “Profile created” notification on the right bottom side of the VS Code:

 **Step 4: Access and Use Postgres From VS Code**

Now click on the “PostgreSQL” icon to open the PostgreSQL Explorer:

On clicking the “PostgreSQL” icon, the “PostgreSQL Explorer” Window will appear in the left pane of your “VS Code” editor. Click on the below-highlighted “+” icon, and specify the connection details in the database connection “palette”:

First, it will ask you to provide the hostname and hit the “Enter” button, in this case, we specify “localhost” as the hostname:

After that, specify the user name and hit the “Enter” button:

Next, provide the appropriate password for the specified user:

Leave the port number as default and hit the Enter button to proceed:

Now select a connection from the available options and hit the “Enter” button to continue, in this case, we select “standard connection”:

Select a specific database or click on “Show all databases”:

Leave the display name of the database connection as default and hit the “Enter” button:

Upon doing so, a database tree will appear in the left pane:

Expand the tree to see more details about the available databases:

The output shows all the available databases, select the desired one and perform any database operation of your choice on that particular database.

That’s all about creating a Postgres profile and connecting to it using VS Code.

 **Conclusion**

To Connect to PostgreSQL From VS Code, first, launch the VS Code, and press “ **CTRL + Shift + X** ” to open the Extensions view. Head into “Search Bar”, type “Postgres”, select the “PostgreSQL” extension owned by Microsoft, and click on the “Install” button to begin the installation. After that, press the “Ctrl + Shift + P” to open the Command Palette, search for “PostgreSQL: New Query”, and select the respective command from the drop-down. Specify the connection details like hostname, database name, user name, etc. Upon doing so, you will see the “Profile created” notification on the right bottom side of the VS Code.

---
[View this page online](https://www.commandprompt.com/education/how-to-connect-to-postgresql-from-visual-studio-code/)

---

# PostgreSQL transaction_timestamp() Function

> The transaction_timestamp() function returns the timestamp for the current transaction. This function does not need any argument.

PostgreSQL offers many time and date functions. Among these functions, transaction_timestamp() is one of the most commonly used functions. The **transaction_timestamp()** method retrieves the timestamp at the start of the recent transaction. The transaction_timestamp() function works similarly to the [now()](<https://www.commandprompt.com/education/postgresql-now-function-with-practical-examples/>) and the [current_timestamp()](<https://www.commandprompt.com/education/postgresql-current_timestamp-function-with-examples/>) functions.

In this post, we will see how the transaction_timestamp() works.

##  **What Does PostgreSQL transaction_timestamp() Function Do?**

The transaction_timestamp() function retrieves the **timestamp with the time zone offset** for the recent/current transaction. The syntax for this function looks like:
    
    
    transaction_timestamp();

The function requires no argument/parameter. It returns the timestamp when the recent transaction is initiated and its return type is TIMESTAMPTZ.

Let’s see how the transaction_timestamp() function works with the help of examples.

 **Example 1: Working of transaction_timestamp() Function**

To understand how the transaction_timestamp() function works consider the following query:
    
    
    SELECT transaction_timestamp();

The function returns the timestamp for the current transaction. The output is:

We can see that the function has returned the date and time at the start of this transaction along with the timezone information.

 **Note:** One thing that needs to be taken notice of is, that the function returns the timestamp when the statement that contains the function is executed. Not the time when the stated function initiates execution. The concept will become more clear using an example.

 **Example 2: Using the Function with pg_sleep Function**

We will use the pg_sleep() function with the transaction_timestamp(). The pg_time() function creates a pause for the specified seconds between the two transaction_timestamp() functions. the syntax can be written as:
    
    
    SELECT
        transaction_timestamp(),
        pg_sleep(5),
        transaction_timestamp();

In this specific case, we have placed a pause for 5 seconds between both functions. Now we will execute the query to see the result of the query. The output will look like this:

We can see that despite the pause we have specified between both functions, both functions returned the same timestamp. This thing advocates the fact that the function returns the timestamp when the statement that contains the function is executed not the time when the function is executed.

So that's all about the transaction_timestamp() function.

##  **Conclusion**

The transaction_timestamp() function returns the timestamp for the current transaction. This function does not need any argument. The return data type of this function is TIMESTAMP with a time zone. The function returns the timestamp when the statement that contains the function is executed. Not the time when the stated function initiates execution.

---
[View this page online](https://www.commandprompt.com/education/postgresql-transaction_timestamp-function/)

---

# What Does starts_with() Function Do in PostgreSQL

> The starts_with() function takes a string and checks whether that string starts with another specified string passed as an argument in the function and returns…

There is a function provided by PostgreSQL that determines whether or not a string begins with the specified word or string. This function is known as the starts_with() function. The starts_with() function takes a string and checks whether that string starts with another specified string passed as an argument in the function.

In this blog, we will examine how the starts_with() function works.

##  **What Does the starts_with() Function Do in PostgreSQL?**

The starts_with() function checks whether the specified string starts with a string specified or not. The function takes both these strings as arguments to check and returns the boolean value depicting as result. The basic syntax of the given function is given below:
    
    
    starts_with(Main_String, Prefix)

In the above syntax,

  * The first argument is the main string in which we want to check whether the prefix of this string is the same as the specifies or not.
  * The second argument is the prefix or the string that needs to be matched with the argument.



The starts_with() function returns a value having a data type of **Boolean**. If the main string starts with the same word specified as a prefix(the second argument), the function returns “true” and in the other case when they do not match, it will return “false”.

Let’s implement the function through examples.

 **Example**

The below example illustrates the working of the starts_with() function:
    
    
    SELECT starts_with('commandprompt.com', 'command');

In the above query:

  * The string to check the first word from is “commandprompt.com”.
  * And the prefix/string that we want to check is “command”.
  * The function has checked whether “commandprompt.com” starts with “command”, the function has returned a boolean value of true.



The output is given as:

If we write the query as:
    
    
    SELECT starts_with('commandprompt.com', '.com');

The output will be:

The output is false because the string “commandprompt.com” does not start with “.com”.

This is the basic functioning of the starts_with() function and this is all about this function.

##  **Conclusion**

The starts_with() function is a simple function that gives a boolean value in return. The function checks for the prefix of the specified main string. If that prefix matches with the prefix(the second parameter) specified, the function returns a true otherwise false.

---
[View this page online](https://www.commandprompt.com/education/what-does-starts_with-function-do-in-postgresql/)

---

# Raise Notice Statement in PostgreSQL

> RAISE NOTICE is used to raise an error and report a message and that error is reported back to the user. It is followed by a format that is basically the strin…

PostgreSQL has built-in error handling mechanisms. We need to show these errors to users and report them through messages in order to maintain the normal execution of the program without interpreting it. The “RAISE NOTICE” statement is used for this purpose, allowing us to report messages to users. Let's explore how the “RAISE NOTICE” statement works in PostgreSQL.

 **RAISE NOTICE Statement in PostgreSQL**

In order to raise an error message, the RAISE keyword is used. RAISE NOTICE is used to raise an error and that error is reported back to the user. The basic syntax of RAISE NOTICE is:
    
    
    RAISE NOTICE [format]

Here format basically specifies the mirror message that is reported to the user. The format is basically a string. The **format** may contain a % placeholder, which will be substituted by an argument. It is necessary that the placeholders should be equal in number to the number of arguments. Otherwise, this would result in an error.

Let’s cover the topic with the help of a simple example:
    
    
    DO $$ 
    BEGIN 
     RAISE NOTICE 'Notice message  %', now();
    END $$;

In the above query, the **DO** statement is used to execute asynchronous blocks. The **BEGIN** and **END** specify the code block, in between these two clauses the queries/code is written. And between them, **RAISE NOTICE** is used followed by the **format** , which is basically the message to be shown to the user. The format also contains a % placeholder. **now()** function gets the current time. This current time is then replaced by the % placeholder. let’s find out what its output looks like:

The output is exactly as per our expectations.

Consider another example of shopping:
    
    
    DO $$ 
    DECLARE
     add_to_cart_products INTEGER = 5;
    BEGIN 
    
     add_to_cart_products = add_to_cart_products + 1;
     
     RAISE  NOTICE 'You have added another product into your cart';
      RAISE  NOTICE 'Now your cart contains % products', add_to_cart_products;
     
    END $$;

In the above example, another section is added i.e. DECLARE. Under the DECLARE statement, we declare all the variables to use in the code block. So we have declared a variable ‘add_to_cart_products’ and initialized its value as 5. In the code block, the variable declared is incremented by one. This gives us the current value which is 6. Let’s have a look at its output.

You can see that the first RAISE NOTICE statement just displays the string passed to it. The second statement contains a % placeholder that is replaced by the variable value that was incremented by 1 and has a current value of 6.

 **Conclusion**

RAISE NOTICE is used to raise an error and report a message and that error is reported back to the user. It is followed by a format that is basically the string we want to show to the user. In this post, we have seen the functioning of the RAISE NOTICE statement along with their practical example.

---
[View this page online](https://www.commandprompt.com/education/raise-notice-statement-in-postgresql/)

---

# How to Use strpos() Function in PostgreSQL

> The strpos() is a built-in function in PostgreSQL that is used to determine the position/location of a sub-string in a main string.

PostgreSQL offers many functions that can manipulate the string data or can be used to get some sort of information about that string. The **strpos()** function finds the position of a sub-string in a main-string. This function takes the main-string and the sub-string as arguments and returns the starting index of the position where the sub-string has occurred. Let’s dive deep into the workings of this function.

##  **How to Use strpos() Function in PostgreSQL?**

The strpos() function determines the position of a sub-string or maybe a character in a main-string. Both the strings to be matched are given to the function as parameters. The basic syntax of this function is given below:
    
    
    strpos(Main_String, Sub_String);

In the above syntax,

  * The main string is the string in which the function will match the sub-string and will return the index of that sub-string.
  * The second argument is the sub-string which we have to look for in the main-string.



The function gives the starting index of the sub-string occurrence in the main string. It means that the return data type of this function is **INTEGER**.

If in case the **sub-string is missing** in the main string, the function will return **0**. And if any of the parameters of the function are NULL the function will also return **NULL**.

 **Note:** This function works similarly to the [position() function](<https://www.commandprompt.com/education/how-to-use-the-position-function-in-postgresql/>). Just the positioning of arguments and the syntax are a little different.

Let’s consider the examples so that we can have a better idea of this function.

 **Example**

To illustrate the concept of the strpos() function, consider the following query:
    
    
    SELECT strpos('commandprompt.com', 'prompt');

The above query will return the starting index of the “prompt” in the main string like this:

We can clearly see that the “prompt” starts from index 8 in the main string.

We can also apply this function to the table. Let’s consider a table “test_scores” having 4 columns; candidate_id , candidate_name, candidate_gender and candidate_score.

Now we will find the position of sub-string “male” in the column candidate_gender. The query will be written as:
    
    
    SELECT candidate_id , candidate_name, candidate_gender,
    strpos(candidate_gender,'male') AS Position_of_male_Substring
    FROM test_scores;

The output of the above query will give a separate column for determining the position of “male” in the candidate_gender column. The output looks like this:

Here we can see that the function has returned the position of the “male” sub-string in the gender column. For the entries with the value “Male,” the strpos() function returns 0 because the function does **case-sensitive matching** and the function was not able to find the ”male” with lower case. While the sub-string “male” can be found in the string “Female”. so, all those entries where the value of gender is female get the value of 3.

So in this article, we have seen how strpos() function functions on a single main string and also on the column of a table. So this was all about this strpos() function.

 **Conclusion**

The strpos() function in PostgreSQL is used to determine the position/location of a sub-string in a main string. The function returns an integer that specifies the first index of the occurrence of the specified sub-string the main string. If the sub-string is missing from the string, simply a 0 will be returned as seen in the above example. Also, remember that the function does case-sensitive matching.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-strpos-function-in-postgresql/)

---

# What Does SELECT LIMIT Statement Do in PostgreSQL

> The SELECT LIMIT statement is used to limit data up to a specified number of rows. The number of rows has to be specified after the LIMIT keyword.

Several statements are used in PostgreSQL in order to make the query work and get our desired data from the database. The **SELECT LIMIT** statement is one of these statements. The whole statement is made up of two clauses/statements. The **SELECT** statement is used to get the data from one or more tables in the database and the **LIMIT** clause is optional but sometimes used with the SELECT statement to have a limit constraint on the number of rows returned by the SELECT statement.

In this article, we will see how SELECT LIMIT works in queries.

##  **What Does the SELECT LIMIT Statement Do in PostgreSQL?**

The SELECT LIMIT statement/command is used to get limited rows of specific data from one or multiple tables. The basic syntax for the SELECT LIMIT statement is given as follows:
    
    
    SELECT col_list
     FROM tab_name
       [WHERE Condition]
       [ORDER BY sorting_order]
     LIMIT row_count;

In the above syntax:

● The **SELECT** statement is followed by the name of the column that we want the query to return.

● After the **FROM** statement, we specify the name of the table from where we want to get the data.

● The **LIMIT** clause is followed by the row count meaning the number of rows we want the query to return.

● We can optionally use the **WHERE** clause and the ORDER BY clause. The WHERE clause is followed by the condition that we want to impose on the data.

● The **ORDER BY** statement is also optional, we can get the data in a specific sorted order.

If the row count declared after the LIMIT statement is **0** , the returning value will be an empty set. If the row count is **NULL** the query will return the same result as without a LIMIT statement.

Let’s move towards an example to get more clarity on the concept.

 **Example**

To demonstrate the working of the SELECT LIMIT statement, consider a table named ”test_scores” having 4 columns candidate_is, candidate_name, candidate_gender, and candidate_scores. The table is given as:

Now if we want to get the female top 3 scorers we can write the query as:
    
    
    SELECT *
     FROM test_scores
     WHERE candidate_gender = 'Female'
     ORDER BY candidate_score DESC
     LIMIT 3;

In the above query:

● We have selected all the columns from the table “test_scores” to return as a result of the query.

● We have imposed the condition that the query will return the rows where the candidate is female.

● The data is sorted in descending order.

● And lastly, the number of rows to be returned by the query is limited to 3 rows.

The output of the above query will be:

We can see that the output has returned the top 3 female scorers in the test. Similarly, we can customize the query for other conditions and and number of rows as well.

Sometimes we want to return the value from a specific offset, so we specify the offset in the query like this:
    
    
    SELECT *
     FROM test_scores
     WHERE candidate_gender = 'Female'
     ORDER BY candidate_score DESC
     LIMIT 3 OFFSET 1;

In the above query, we have specified the offset as 1. Now what this query will do is, that it will function the same as above but it will return the data after the first position of the data, not the first record itself. So the output will be as follows:

We can see that the records returned by the query are now after the first position as we have declared the offset as 1.

So this is how the SELECT LIMIT statement works.

##  **Conclusion**

The SELECT LIMIT statement is used to limit data up to a specified number of rows. The number of rows has to be specified after the LIMIT keyword. We can specify some conditions or the sorting order of the data optionally. The resulting data will be limited to a specified number of rows.

---
[View this page online](https://www.commandprompt.com/education/what-does-select-limit-statement-do-in-postgresql/)

---

# PostgreSQL array_fill() Function

> The array_fill() is a function that fills an array with a specified argument. The dimensions of that array are also specified in that function as an argument.

PostgreSQL offers many array functions that are used to return some information about the array or manipulate the array in different ways. **Array_fill()** function is one of these functions that are used to manipulate the array. The basic functionality this function provides is that it fills the array with a specified element. The element and the dimension of the array are passed in the function as arguments.

In this post, we will examine how the array_fill() function works.

##  **How Does the PostgreSQL array_fill() Function work?**

The array_fill() function fills the array with an element that is specified in the function as an argument. The dimension of the array is also specified as an argument. The basic syntax of the function is given below:
    
    
    array_fill(Element , Dimension[, lower_bound]) ;

In the above syntax:

● The first Argument is the element that we want to fill in the array.

● The second argument specifies the dimension of the array for example, if Array[4] is specified, it means that the array is one-dimensional and the length of the array is 4. If Array[3,4] is specified, this represents that the array is 2-dimensional, and the first dimension of the array is 3 and the second one is 4.

● The final argument is entirely optional. This determines the array's starting index.

The return values of this function have a data type of **ARRAY**. The function returns an array of a dimension specified and having an element that is also specified as an argument.

Let’s move towards the example to get more clarity on the concept.

 **Example**

Let's first consider a simple example of a one-dimensional array. The query is given below:
    
    
    SELECT array_fill(3, ARRAY[4]);

In the above query:

● The first argument is the element 3. It means the array will be filled with the element 3.

● The second element depicts the dimension of the array. Here in this case it is Array[4], which means that the array will be one-dimensional and will have the length 4.

So the output of the given query will be:

We can also specify the lower bound for this function which is completely optional, but let’s see how it works when it is specified:
    
    
    SELECT array_fill(3, ARRAY[4] ,ARRAY[2]);

In the above query, the lower bound “ARRAY[2]” is specified which means that the array will be starting from the index position of 2. The output will specify the starting and ending index of the array in case the lower bound is specified in the query. The output will be as follows:

The resulting array contains element 3 and has a length of 4, while the array is starting with an index of 2 to 5.

Now consider another example of a multi-dimensional array. The query for this case is given below:
    
    
    SELECT array_fill(3, ARRAY[4,2]);

In this query, the element will be 3. The second argument depicts that the array is 2-dimensional. The first dimension is 4 and the second dimension is 2. Let’s see what the output of the query looks like:

In the above output, it is clearly illustrated that the resulting array is 2-dimensional having a first dimension of 4 and a second dimension of 2.

Another multi-dimensional array is as follows:
    
    
    SELECT array_fill(3, ARRAY[4,2,2]);

The resulting array is 3 dimensional, having a first dimension of 4, a second dimension of 2, and a third dimension of 2 as well. The output is illustrated below:

###  **Input Type Error**

If we want to fill our array with an element “abc”, we will write the query as:
    
    
    SELECT array_fill('abc', ARRAY[4,2]);

By executing this query you will see that the output will be an error saying; ERROR: could not determine polymorphic type because input has type unknown.

This means that we have not specified the data type of the element. To fix this error we need to specify the data type in the query like this:
    
    
    SELECT array_fill('abc'::TEXT, ARRAY[4,2]);

This will resolve the issue and give us our required output like this:

This is how the array_fill() function works in PostgreSQL.

##  **Conclusion**

The array_fill() is a function that fills an array with a specified argument. The dimensions of that array are also specified in that function as an argument. The return values of this function have a data type of ARRAY. This article demonstrated how to utilize the array_fill() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-array_fill-function/)

---

# How to Use the make_interval() Function in PostgreSQL?

> The make_interval() method generates an interval based on the arguments passed into it. All the arguments are of INT data type except the last one i.e. seconds…

There are several date and time functions offered by PostgreSQL and we have discussed some of them previously. The **make_interval()** Function in PostgreSQL is used to create an interval using the given arguments. In this post, we will elaborate on the functioning of the make_interval() function.

##  **How to Use the make_interval() Function in PostgreSQL?**

The make_interval() function takes in 7 parameters i.e. Years, Months, Weeks, Days, Hours, Minutes, and Seconds. The first 6 parameters have a data type of **INTEGER** while the last parameter i.e. seconds has a data type of **DOUBLE PRECISION**.

The basic syntax of the function looks like this:
    
    
    make_interval(Years INT, Months INT, Weeks INT, Days INT, Hours INT, Mins INT, Seconds DOUBLE PRECISION);

The arguments have a **default value** of 0 and 0.0 in the case of the seconds parameter.

The make_interval() function returns an **INTERVAL** created by the arguments passed in the function.

Let’s move toward some examples to see how it works:

 **Examples**

Here is how the make_interval() function works:
    
    
    SELECT make_interval(10, 9, 8, 7, 6, 5, 4.321);

The above query will result in the interval created by the specified arguments. The output of the query will be:

The first argument is created as a year, the second one as months the third argument is always converted into days and added to the fourth argument(days). Similarly, all the arguments are mapped to their respective values.

We can also separate all the arguments **using named notation** to see how they work:
    
    
    SELECT
        make_interval(years => 1) AS "years_parameter",
        make_interval(months => 2) AS "months_parameter",
        make_interval(weeks => 3) AS "weeks_parameter",
        make_interval(days => 4) AS "days_parameter",
        make_interval(hours => 5) AS "hours_parameter",
        make_interval(mins => 6) AS "mins_parameter",
        make_interval(secs => 7) AS "secs_parameter";

Now execute the query. The output will look like this:

The **named notation** simply specifies the arguments by their names followed by **”= >”** and then their value. Such as:
    
    
    SELECT make_interval(Hours => 7);

 **Changing Output Style**

We can also change the format of the output interval style. The style can be any of these:

  * Postgres
  * postgres_verbose
  * sql_standard
  * iso_8601



We will see how these all change the format of output one by one.

  *  **Postgres**



This is the same format as the above outputs are in. Which looks like this:
    
    
    SET intervalstyle = 'postgres';
    SELECT make_interval(10, 9, 8, 7, 6, 5, 4.321);

  *  **postgres_verbose**



This query and the output for the format look like this:
    
    
    SET intervalstyle = 'postgres_verbose';
    SELECT make_interval(10, 9, 8, 7, 6, 5, 4.321);

This format has added more verbosity to the output.

  *  **sql_standard**



This query for this format will be:
    
    
    SET intervalstyle = 'sql_standard';
    SELECT make_interval(10, 9, 8, 7, 6, 5, 4.321);

This format looks like this:

  *  **iso_8601**



This query and the output for the format look like this:
    
    
    SET intervalstyle = 'iso_8601';
    SELECT make_interval(10, 9, 8, 7, 6, 5, 4.321);

##  **Conclusion**

The make_interval() method generates an interval based on the arguments passed into it. All the arguments are of INT data type except the last one i.e. seconds, which is of DOUBLE PRECISION data type, and the default values are 0 and 0.0 respectively. The arguments can be passed using the simple notation or named notation. The output format can also be changed by setting the interval style to that specific style by default it is Postgres style.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-make_interval-function-in-postgresql/)

---

# How to Use translate() Function in PostgreSQL

> The PostgreSQL translate() function returns a string after replacing a set of strings from one main string with some set of characters specified.

PostgreSQL offers many functions that are operated on the strings. The PostgreSQL **translate()** function returns a string after replacing a set of strings from one main string with some set of characters specified. The translate() function takes in the main string in which characters have to be replaced, the set of characters that have to be replaced, and the set of characters with which the replacement will take place.

Let’s dive into the details of this translate function in PostgreSQL and see how it works.

##  **What Does PostgreSQL translate() Function Do?**

The translate() function in PostgreSQL does one-to-one translation of characters in a single operation. The basic syntax of the function is:
    
    
    TRANSLATE(Main_String, String_from_set_to_replace, Replacement_String);

The function takes in 3 arguments:

● The first argument is the main string in which the translation will occur.

● The second argument is the set of strings that needs to be translated

● The third argument is the set of replacement strings that are to be replaced/ translated into the main string.

This function's return type is **STRING**. The function returns the main string in which the “String_from_set_to replace” and translated into ”Replacement_String”.If any of the parameters is NULL, the function will return NULL.

To make the concept more clear, let’s move towards the example.

 **Example**

A simple example of the translate() function in PostgreSQL is illustrated below:
    
    
    SELECT translate('abcdefghij', 'efg', '567');

In the above syntax:

\- The main string is ** 'abcdefghij'**

\- The string to be replaced from the main string is **“efg”**. This string is to be translated into the replacement string.

\- The replacement string is **“567”.**

\- The translate() function does one-to-one translation of characters, which means that the:

  * letter ”e” is translated into “5”.
  * letter ”f” is translated into “6”
  * letter ”g” is translated into “7”.



Hence, the output for the above query is:

We said that the function does the one-to-one translation. What if the characters that are being translated are repeated more than once in the main string? Let's see what happens in this scenario:
    
    
    SELECT translate('abcdefghij_gfe', 'efg', '567');

The output of the above query advocated the statement.

It means that the characters are individually translated and wherever they occur, they will be translated into the respective translated character.

One thing is to note here if the “String_from_set_to replace” is longer than the ”Replacement_String”, the extra characters are removed from the main string if they are present in it. For instance:
    
    
    SELECT translate('abcdefghij_gfe', 'efgabc', '567');

Now here in “String_from_set_to replace” the characters “abc” are extra so the characters will be removed from the main string giving the output as follows:

 **Replacing Single Character**

Let’s consider the query in which a single character is replaced let's suppose we want to replace the white spaces with the commas in the string containing the names of students, we will write the query as:
    
    
    SELECT translate('John Peter Alex Sarah', ' ', ',');

In the above query, the white spaces are replaced with commas. We will get the output as:

The names of students are separated by commas as they get replaced by the white spaces between them.

 **Encryption and Decryption of message**

This function can also be used for encryption and decryption of messages. The message to be encrypted can be written as the main string and the elements to be encrypted and characters in which the message is to be encrypted are declared in the function. Let's consider the below query:
    
    
    SELECT translate('This is translate function', 'abcdefghijklmnopqrstuvxyz', '0123456789zyxvutsrqponmlk');

The message will be encrypted as follows:

We can also similarly decrypt the message;
    
    
    SELECT translate('T78q 8q pr0vqy0p4 5ov2p8uv', '0123456789zyxvutsrqponmlk', 'abcdefghijklmnopqrstuvxyz');

So this is how the translate() function in PostgreSQL works.

###  **Conclusion**

The translate() function in PostgreSQL replaces a set of characters in the main string with some translated characters. The main string, the set of characters to be replaced, and the replacement characters are passed as arguments into the function. Message encryption and decryption is one of the most crucial applications of this function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-translate-function-in-postgresql/)

---

# How to Find Square of a Number in PostgreSQL

> In PostgreSQL, there are two ways to calculate/get the square of a number: the POWER() function and a user-customized logic, i.e., multiplying the number by it…

Sometimes we need to find the square of a given number number in PostgreSQL. PostgreSQL offers two approaches for finding the square of a number. This blog will focus on the three methods to calculate the square of a number in Postgres. These two methods are:

  * Method 1: Using Multiplication operation.
  * Method 2: Using Power Function.



Let’s discuss these methods one by one.

 **How to Find the Square of a Number in PostgreSQL?**

PostgreSQL offers two approaches for finding the square of a number. Let’s discuss.

 **Method 1: Using the Multiplication operation**

By multiplying the values/number by itself, we may find its square. This is a very simple method and the query can be written as follows:
    
    
    SELECT number*number;

We need to specify the numbers in the above query to find the square of that specific number.

To operate this method on a table we need to have a table of numbers consider the following table named num:

Now we will execute the following query to get the square of the numbers:
    
    
    SELECT
      *,
      x * x AS square
    FROM num;

The output of the above query will be a table having 2 columns one containing numbers and the second one containing their squares like this:

 **Method 2: Using Power Function**

We can also find the square of the function using the [POWER() function](<https://www.commandprompt.com/education/how-to-use-power-function-in-postgresql/>). This function takes two arguments as input. The first parameter/argument is the number itself and the second parameter is the power of that number. In the case of square, the second argument will always be 2. If we want to find the square of 3 we will write the following query:
    
    
    SELECT POWER(3,2);

The output will be **9**.

If we want to get a square of all the entries of a column of a table, below is the query for calculating the square using this power method:
    
    
    SELECT *,
     POWER( x, 2) AS square
    FROM num;

This will give the square of each entry of a column like this:

 **Conclusion**

There are two ways to calculate/get the square of a number. The first and simplest way is to apply the multiplication operation i.e. by multiplying the number by itself. The second is the POWER() function. This function takes in the number and the power to apply to that number. In the case of square power always has to be 2.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-square-of-a-number-in-postgresql/)

---

# PostgreSQL CITEXT Data Type

> The CITEXT data type in PostgreSQL is case-insensitive that allows us to do text comparisons without worrying about the case.

In PostgreSQL, we use CITEXT to store the data that can ignore case sensitivity. This data type is developed, based on the TEXT data type in PostgreSQL and provides an efficient way to compare the text ignoring the case sensitivity. Let’s see the details of CITEXT data type using examples.

 **PostgreSQL CITEXT Data Type**

The CITEXT data type is a case-insensitive data type that allows you to do text comparisons without considering the case an issue. For example, if we want to fetch data from the table, we can get it using a SELECT statement along with a WHERE statement if we need to get data for a specific condition. Let's consider the following table as an example:

Now if we want to get the data of the student named “alex” we will write the following query:
    
    
    SELECT * FROM students_info WHERE studentname = 'alex';

By executing this query we will see that this query did not give any result.

Whereas the student with the name “Alex” does exist in the database table. Which is not a good thing, we need to figure out the issue. So what's the issue?

The issue is that we have called the name of the student in lowercase letters. This means that the name field has been declared by the data type that is case-sensitive.

The CITEXT data type can rescue us in such conditions. This data type is case-insensitive and it can do data comparison without making the case a big issue. The basic syntax for using the CITEXT data type is:
    
    
    CREATE TABLE tab_name (
      col_name CITEXT
      );

While creating the table we need to declare the data type of the field as CITEXT. Now let’s fix the problem. Write the following query for the creation of a table and declare the columns as CITEXT:
    
    
    CREATE TABLE Students_Info
       (
       StudentID int,
       StudentName CITEXT,
       Address CITEXT,
       City CITEXT)
       );

Now if you are using the CITEXT data type for the first time, you may encounter an error that:

To fix this error you need to first create an extension of the data type CITEXT. Let’s do it by executing the following query:
    
    
    CREATE EXTENSION CITEXT

This query will successfully create an extension for CITEXT. Now if we create the table using the above written code we will be successful in creating it. The next step is to insert the values into the table.
    
    
    INSERT INTO students_info(studentid, studentname ,address,city)
     VALUES ( 01,'John','13th Street. 47 W 13th St' , 'New York'),
      ( 02,'Alex','24th Street. 32 E 24th St' , 'San Diego'),
      ( 03,'Peter','6th Street. 23 W 6th St' , 'San Francisco')
     RETURNING *;

The table with the values will look like this:

In the above output, we can see the data type of these fields is CITEXT. Now we will see if this has solved the issue or not. We will retrieve the data for the student name “alex”. Execute the following query:
    
    
    SELECT * FROM students_info WHERE studentname = 'alex';

Following is the output:

We can see that, the query has returned the output even though we have retrieved the data of the student with lowercase letters.

 **Conclusion**

The CITEXT data type is case-insensitive, allowing you to do text comparisons without worrying about the case. In this post, we have talked in detail about how the CITEXT data type assists in data integrity. The case-insensitive nature of the CITEXT data type is used in the comparison of texts without caring about the case.

---
[View this page online](https://www.commandprompt.com/education/postgresql-citext-data-type/)

---

# What is PostgreSQL DOUBLE PRECISION Data Type?

> DOUBLE PRECISION data type is a floating-point data type. It offers high precision and wide storage space of 8 bytes.

DOUBLE PRECISION data type stores numbers having a fractional part. The data type DOUBLE PRECISION are variable precision data type. Their precision may vary depending on the input values. This data type can be used where the accurate/exact number is not needed.

##  **What is PostgreSQL DOUBLE PRECISION Data Type?**

One of the most significant data types among all the data types in Postgres is the DOUBLE PRECISION data type. This data type offers memory storage of an 8-byte floating-point number. The number that contains the fractional part is stored in the DOUBLE PRECISION data type.

These data types offer a precision range of 15-17 digits which means it supports a very high precision. Let's see what the syntax of double precision type looks like:
    
    
    col_name DOUBLE PRECISION

The syntax for double precision is quite simple. The name of the column is specified before the DOUBLE PRECISION data type.

Let’s move toward an example that will make the concept of DOUBLE PRECISIONS more clear.

 **Example**

Let’s create a table “Students_scholarships” with a column “Scholarship_amount” having a DOUBLE PRECISION data type. The query for the table is:
    
    
    CREATE TABLE Students_scholarships (
        Student_id SERIAL PRIMARY KEY,
        Student_name VARCHAR(100) NOT NULL,
        Scholarship_amount DOUBLE PRECISION NOT NULL
    );

A table will successfully be created.

We will now insert some data into the table:
    
    
    INSERT INTO students_scholarships (student_name, scholarship_amount) 
    VALUES
        ('Katherine John', 14050.70),
        ('Williams Smith', 28440.85),
        ('Alex Peter', 175350.62);

The table with the above values will be created as follows:

We can also use the **ROUND** function to round off the scholarship amount as it will not create a huge difference in the amount. The query will be as follows:
    
    
    SELECT Student_name, ROUND(scholarship_amount) as rounded_scholarship_Amount
    FROM students_scholarships;

The output for the query will give the rounded scholarship amount:

So this was all about the DOUBLE PRECISION data type.

##  **Conclusion**

Understanding data types is important in PostgreSQL. It greatly influences the fact that our database will be interacting with the application program. DOUBLE PRECISION data type offers high precision and wide storage space of 8 bytes. This data type is widely used where accurate numbers are not of very high importance. Its applications include; finances, modern engineering, and scientific computations.

---
[View this page online](https://www.commandprompt.com/education/what-is-postgresql-double-precision-data-type/)

---

# PostgreSQL overlay() Function

> The OVERLAY() function in Postgres replaces some specified characters in the given main string with another specified string.

PostgreSQL offers many functions that are used to manipulate data. The **OVERLAY()** function is one of them. OVERLAY() function in Postgres replaces a specified number of characters in a main string with another specified string. This blog covers how the OVERLAY() function works. Let's get started!

 **How Does PostgreSQL Overlay() Function Work?**

The OVERLAY() function in Postgres replaces some specified characters in the given main string with another specified string. The information about the position of the replacement string is also provided in the query. The basic syntax for the OVERLAY() function is:
    
    
    SELECT OVERLAY(<the_main_str> PLACING <the_replacing_str>  FROM <start_position> [ FOR<number_of_char>] );

So in the above syntax, in the OVERLAY function:

  * The first thing we specify is the main string. It is the string in which the characters will be replaced.
  * Secondly, after using the PLACING keyword we will specify the string that is the replacement.
  * After the FROM statement, we will specify the position of characters in the main string from where the string will be replaced.
  * After the FOR keyword, we will write the number of characters that are to be replaced from the main string.



The above syntax will be more clear if we understand it using an example.

 **Example**

First, let’s see a simple example. Consider the main string as ‘Peter lives in England’. Now if we want to replace “Peter” with “Sarah” we will write the following query:
    
    
    SELECT OVERLAY('Peter lives in England' PLACING 'Sarah' FROM 1 FOR 5 );

Now let’s have a glance at how we write the above query. The description for the queries is given below:

The string “Peter” will be replaced by “Sarah” as the replacement starts from position 1 in the main string till the next 5 characters.

The output for the query is as expected:

For another example, let’s consider the string 'This is an example of PostgreSQL function' In this example if we want to replace the “PostgreSQL” with “overlay”, we need to consider the following query:
    
    
    SELECT OVERLAY('This is an example of PostgreSQL function' PLACING 'overlay' FROM 23 FOR 10 );

Now see the output of the function:

We want to replace ”PostgreSQL” which starts from the 23rd position so we will write FROM 23. And the whole word “PostgreSQL” contains 10 characters that are to be replaced, this is the reason we wrote 10 after the FOR keyword.

So this was all about the OVERLAY() function. We have learned how the overlay function works in detail.

 **Conclusion**

The OVERLAY() function in PostgreSQL replaces a specific string with some other string which is also specified in the query. The position and character to be replaced by the string are also specified in the query. This post has demonstrated the use of the OVERLAY() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-overlay-function/)

---

# PostgreSQL regexp_match() Function

> In PostgreSQL, the regexp_match() function matches a regular expression in a specified main string. This function takes in the string and the regular expressio…

In PostgreSQL, the **regexp_match()** function matches a regular expression in a specified main string. This function takes in the string and the regular expression to be matched along with a flag and returns the first matched substring from the main string.

Let’s get into the details of the regexp_match() function.

##  **How Does PostgreSQL regexp_match() Function Do?**

The regexp_match() function works almost the same as the regexp_matches() function. It basically returns the result of the first matching of the regular expression against the main string.The basic syntax of the regexp_match() function is given below:
    
    
    regexp_match(Main_String, Regexp[, flags]);

The regexp_match() function takes in 3 arguments:

  * The first parameter is the **main string** in which the search will take place.
  * The second argument is a **POSIX regular expression** that needs to be searched in the main string.
  * The third argument, which is completely optional, is the flag. The **flag** is responsible for controlling the behavior of the function for example; the **”i”** flag makes a matching case-insensitively. But note that the regexp_match() function does not support the “ **g** ” flag. A [list of flags](<https://www.postgresql.org/docs/current/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE>) is given in the Postgres documentation.



The function returns a set of string values. These values correspond to the matches of the expression in the main string. If the match does not exist, the result will be NULL.

Let’s have a look at an example to make it more clear.

 **Example**

If we want to match an expression from a string, we will write the query as:
    
    
    SELECT regexp_match('bats Eaten gate Atone', 'at.');

In the above query:

  * The main string is **' bats Eaten gate Atone’** in which the regular expression is going to be matched.
  * The expression we want to search for is **”at.”**. You can see the regular expression contains a dot **“.”** , we can use a dot or multiple dots after and before the regular expression. The number of dots and the placement of dots simply specify the number of characters before or after the expression in the returned text.



In case of one dot after the expression ‘at’, the query will search for the first string in the main string and will return the array of the string containing the first “at” and an additional character from the matched string after the “at”.

The output will look like this:

Let's add another dot before ”at” and see the results:
    
    
    SELECT regexp_match('bats Eaten gate Atone', '.at.');

The query will look for the first “at” match in the main string and will result in the string having a character before and after the matched string in the main string. The output is:

You can see that the query matched the “at” expression with the string and gets the first match. The dot before and after the expression will join a character before and after the expression from the string.

In the next example, let’s use the flag ”i”. The “i” flag does the matching case insensitively. Consider the below query:
    
    
    SELECT regexp_match('bats Eaten gate Atone', '.TO.', 'i');

So the query will search for the ”TO” expression being insensitive to the case. The result will be:

There is another flag that is usually used in the regexp_matches() function but is **not supported** by the regexp_match() function i,e, **“g” flag** , or a global flag. Let’s see how the query works if we have the flag “g”.
    
    
    SELECT regexp_match('bats Eaten gate Atone', '.at.', 'g');

The output will throw an error.

The error says that we can not use the **“g”** flag with the regexp_match() functions this flag is not supported by the function. Remember that the regexp_matches() function is more flexible than the regexp_match() because it only gives the first match result while the regexp_matches() can return first as well as all the matching results using the “g” flag.

So this was all about the regexp_matches() function.

##  **Conclusion**

The regexp_match() function matches a specified expression against a specified main string and returns the set to strings/characters that match first. We can not use the **“g”** with the function as we used it in regexp_.matches() function. The flags are completely optional but if added will give some specific results for the function. cIn this article, we have discussed the regexp_match() function in detail.

---
[View this page online](https://www.commandprompt.com/education/postgresql-regexp_match-function/)

---

# PostgreSQL regexp_split_to_array() Function

> In Postgresql, the regexp_split_to_array() function is used to split the specified string into an array using the specified POSIX regular expressions

In Postgresql, the regexp_split_to_array() function is used to split the specified string into an array using the specified POSIX regular expressions. The strings as well as the POSIX regular expression are provided to the function as an argument. This expression will act as a separator for the string elements in the array. A flag can also be specified in the function. This function works the same as the [string_to_array()](<https://commandprompt.com/education/string_to_array-function-in-postgresql/>) function.

Let’s get deep into the details of the regexp_split_to_array() function.

## PostgreSQL regexp_split_to_array() Function

As discussed earlier, the the regexp_split_to_array() function splits the given string into an array placing the regular expressions as separators. There also exists a third argument, which is completely optional, that can control some specific behavior of the function. The function returns an array. Let's have a look at the basic syntax of the function:
    
    
    regexp_split_to_array(String,   Regexp[, Flag]);

In the above syntax:

● The String is the main string that needs to be split.

● The second argument, Regexp, is the POSIX reg expression that will act as a separator.

● The third argument is the flag that can slightly mold the functionality of the function. For example **”i”** flag will consider the sensitive matching.

The function returns an array that contains the string split through the regular expressions as separators. Below are some of the important things about the value of Regex:

● If the Regex is NULL the function will also return NULL.

● If the value of Regex is an empty string, the function will simply return all the characters of the original string.

Let’s move on to the examples of the regexp_split_to_array() function to understand it better.

 **Example 1**

Consider the following query as an example:
    
    
    SELECT regexp_split_to_array('bats   Eaten gate Atone', '\s+');

In this query, the string, **' bats Eaten gate Atone'**, will be separated by whitespaces as the regular expression is ”\s+” which gives the white spacing between the string elements. The output of the query is:

Consider the case where the Regex is an empty string. The query is as follows:
    
    
    SELECT regexp_split_to_array('bats   Eaten gate Atone', '');

The output of this query will be separating all the characters of the string like this:

Now consider using the optional flags in the query. In the below query, we will be using the “i” flag.
    
    
    SELECT regexp_split_to_array('bats Eaten gate Atone', 'at.', 'i');

The “i” flag will match the regex for the case-insensitive characters in the string and then accordingly return the value like this:

In the above output, the” i” flag has found “at” in the string and its next character(represented by “.”) and separated them by commas. The double quotes “ ” are for spaces.

 **Example 2**

We can also use this function with the tables. Let's see how it works:

Consider the following table project_status having 4 columns:

Now if we want to apply the function regexp_split_to_array() on the proj_name column, we will have to write the following query:
    
    
    SELECT regexp_split_to_array(proj_name, '\s+')
     FROM   project_status;

This query will separate the proj_name strings into the array elements having the data type TEXT. the output will be:

The above output clearly proves that the function has been executed successfully and works the same in the case of tables too.

This was all about the regexp_split_to_array() function.

 **Conclusion**

This function works the same as the string_to_array() function does. The function takes the string, the regexp, and the flag(if any) as arguments and returns an array that contains the string elements/characters with the Regexp as separators. In this article, we have learned about the regexp_split_to_array() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-regexp_split_to_array-function/)

---

# What Do make_date() and make_time() Functions do in PostgreSQL?

> The make_date () function takes arguments, then creates and returns a date with them. The make_time() function takes arguments, then creates and returns a time…

To show the time and date we use the make_date() and make_time() functions. The make_date() function returns the date according to the input values and the make_time() function returns the time according to the parameters passed into the function. Both functions give errors when the input parameters have some issue, maybe due to the wrong data type or due to out-of-range parameters.

This article will show how make_data() and make_time() functions work. Let’s get started.

##  **What Do make_date() and make_time() Functions do in PostgreSQL?**

The things these functions have in common are that they take 3 parameters as input and return a type. The return type of value in the case of the make_date() function is the date and in the case of the make_time() function is time.

Let's discuss the make_date() function first.

###  **The make_date() Function in PostgreSQL**

The make_date() function manipulates the parameter it takes and converts it into date. These parameters are 3 in number: year, month, and day. remember that the sequence of these parameters has to be the exactly same otherwise, this could cause an error. The basic syntax for this function is:
    
    
    make_date(Year INT, Month INT, Day INT);

All these parameters are required and the type of all of them should be “Integer”.

Now let's see an example to get more clarity over the concept.

 **Example**

Consider the following query as an example:
    
    
    SELECT make_date(2023, 8, 24);

The function in the above query will convert the parameters into a proper date format as follows:

In the above output, you can see that the returned type of the function is date. We can verify it by using the “pg_typeof()” function. The “pg_typeof()” function takes in a parameter and returns the data type of that argument.

The query will look like this:
    
    
    SELECT pg_typeof(make_date(2023, 8, 24));

The output of the above query will clearly show the returned type:

So the make_date() function always returns the value having data type “date”.

Consider another example in which we will intentionally replace the value of a day parameter greater than 31 let's say it is 64. Let's see how the query responds to this case.
    
    
    SELECT make_date(2023, 8, 64);

When we execute this query, the output will be:

The query gives an **“out of range”** error. This is because the value of parameter days is more than 31 as the day in a month can not be greater than 31. The same case will happen if the value of the month parameter is greater than 12.

 **Special case**

As we have discussed above, the data type of each parameter should be INT. According to PostgreSQL documentation, it should be INT but there is a special case. If we pass the arguments in strings this also seems to work without any issue as soon as the values are in their proper range. This may be because they can be implicitly converted into integers. Let’s consider an example for this special case.
    
    
    SELECT make_date('2023', '8', '24');

By executing the above query we will get:

This means that under this condition the query also works properly.

But you have to make sure about one thing, the arguments must be valid to be converted into the INT. For example, if we execute the following query:
    
    
    SELECT make_date('2023', 'August', '24');

It will give an error that:

This is because the “August” is not valid and can not be converted into an integer lately.

If we want to consider the BC date we will have to place a minus(-) sign with the year such as:
    
    
    SELECT make_date(-2023, 8, 2);

The output will give the BC date:

That was all about the make_date() function. Now we will move towards the make_time() function.

###  **The make_time() Function in PostgreSQL**

The make_time() function also works almost the same as make_date(). It manipulates the parameter it takes and converts it into time. These parameters are 3 in number: **hour** , **min** , and **sec**. Remember that the sequence of these parameters has to be exactly the same otherwise, this could cause an error. The basic syntax for this function is:
    
    
    make_time(Hour INT, Minute INT, Second DOUBLE PRECISION);

All these parameters are required and the type of hour and min should be “Integer” while for a sec it has to be a “ **DOUBLE PRECISION** ”. The return value of the query is **time** or **time without the time zone**.

Now let's move towards an example.

 **Example**

Consider the following query as an example:
    
    
    SELECT make_time(10, 25, 27);

The function in the above query will convert the parameter into a proper time format as follows:

In the above output, you can see that the returned type of the function is **time without time zone**. We can verify it by using the “pg_typeof()” function.
    
    
    SELECT pg_typeof(make_time(10, 25, 27));

The output of the above query will clearly show the returned type:

Consider another example in which we will intentionally replace the value of a min parameter greater than 60 let's say it is 87. Let's see how the query responds to this case.
    
    
    SELECT make_time(10, 87, 27);

When we execute this query, the output will be:

The query gives an **“out of range”** error. This is because the value of parameter min is more than 60 as the minutes in an hour can not be greater than 60. The same case will happen if the value of the hours parameter is greater than 24 and seconds greater than 60.

 **Special case**

Similar to the make_date() function, this function also has a special case. As we have discussed above, the data type of hour and minute parameter should be INT and for the second it is DOUBLE PRECISION. According to PostgreSQL documentation, they should be INT and DOUBLE PRECISION but there is a special case. If we pass the arguments in strings this also seems to work without any issue as soon as the values are in their proper range. Let’s consider an example for this special case.
    
    
    SELECT make_time('10', '39', '35.05');

By executing the above query we will get:

This means that under this condition the query also works properly. But if any of the arguments exceeds its range, it will give the out-of-range error.

 **Conclusion**

There are many functions in PostgreSQL used to handle/manipulate the date and time. The functions make_date() and make_time() are significant among those. The make_date () function takes arguments, then creates and returns a date with them. The make_time() function takes arguments, then creates and returns a time without a time zone. The arguments have to be in range and specified data types.

---
[View this page online](https://www.commandprompt.com/education/what-do-make_date-and-make_time-functions-do-in-postgresql/)

---

# PostgreSQL regexp_split_to_table() Function

> The regexp_split_to_table() function takes the string, the regexp, and the flag(if any) as arguments and returns a table column that contains the string charac…

In Postgresql, the regexp_split_to_table() function is used to split the specified string into a table column using the specified POSIX regular expressions. The strings as well as the POSIX regular expression are provided to the function as an argument. This expression will act as a separator for the string elements in the table column. A flag can also be specified in the function. This function works the same as the [string_to_table()](<https://www.commandprompt.com/education/postgresql-string_to_table-function-with-examples>) function.

Let’s get deep into the details of the regexp_split_to_table() function.

##  **PostgreSQL regexp_split_to_table() Function**

As discussed earlier, the regexp_split_to_table() function splits the given string into a table column placing the regular expressions as separators. There also exists a third argument, which is completely optional, that can control some specific behavior of the function. The function returns a table. Let's have a look at the basic syntax of the function:
    
    
    regexp_split_to_table(String,   Regexp[, Flag]);

In the above syntax:

● The String is the main string that needs to be split.

● The second argument, Regexp, is the POSIX reg expression that will act as a separator.

● The third argument is the flag that can slightly mold the functionality of the function. For example, the **”i”** flag will consider the sensitive matching.

The function returns a table that contains the string split in the columns with the regular expressions as separators. Below are some of the important things about the value of Regex:

● If the Regex is NULL the function will also return NULL.

● If the value of Regex is an empty string, the function will simply return all the characters of the original string.

Let’s move on to the examples of the regexp_split_to_table() function to understand it better.

 **Example**

Consider the following query as an example:
    
    
    SELECT regexp_split_to_table('bats   Eaten gate Atone', '\s+');

In this query, the string, **' bats Eaten gate Atone'**, will be separated by whitespaces as the regular expression is ”\s+” which gives the white spacing between the string elements and separates them in column rows. The output of the query is:

Consider the case where the Regex is an empty string. The query is as follows:
    
    
    SELECT regexp_split_to_table('bats   Eaten gate Atone', '');

The output of this query will separate all the characters of the string in the columns of a table like this:

Now consider using the optional flags in the query. In the below query, we will be using the “i” flag.
    
    
    SELECT regexp_split_to_table('bats   Eaten gate Atone', 'at.', 'i');

The “i” flag will match the regex for the case-insensitive characters in the string and then accordingly return the value like this:

In the above output, the” i” flag has found “at” in the string and its next character(represented by “.”) and separated them in the columns of a table.

This was all about the regexp_split_to_table() function.

##  **Conclusion**

The regexp_split_to_table() function takes the string, the regexp, and the flag(if any) as arguments and returns a table column that contains the string elements/characters with the Regexp as separators. In this article, we have learned about the regexp_split_to_table() function in PostgreSQL. This function works the same as the string_to_table() function does.

---
[View this page online](https://www.commandprompt.com/education/postgresql-regexp_split_to_table-function/)

---

# PostgreSQL array_position() Vs. array_positions() - What's the Difference

> Array_position() function gives the first occurrence of an element while the Array_positions() function gives all the occurrences of an element in an array.

To find the position of occurrence of an element in an array we use array_position() and array_positions() functions. The common functionality of these functions is that they take an array and an element as arguments and return the index of where that element(specified in the array) has occurred in the array.

Let’s see how both of these functions particularly work.

##  **PostgreSQL array_position() Vs. array_positions() - What 's the Difference?**

As discussed above, the common functionality of both functions is that they both give the index of occurrence of an element in an array that is passed in the function as arguments. However, there is a difference between the functionality of both functions.

First, let’s discuss the functionality of array_position().

###  **PostgreSQL array_position() Function**

The array_position() function in PostgreSQL takes an array and an element as arguments and returns the index of the first occurrence of that element in the array. The basic syntax for the function is given as:
    
    
    array_position(Array, Element[, Start index]);

The array and the element are required arguments, the array is the first argument where the search will take place and the second argument is an element that is to be searched. The optional third argument specifies the index from where the function starts its search from.

Note that if the element is missing in that array, the function returns NULL.

Let's consider the below example to make it more clear.

 **Example**

To understand how the array_position() function works, consider the example below.
    
    
    SELECT array_position(ARRAY['John', 'Sarah', 'Peter', 'Alex', 'Williams', 'Sarah'], 'Sarah');

In the above query, we have passed an **array** i.e. **[ 'John', 'Sarah', 'Peter', 'Alex', 'Williams', 'Sarah**' **]** and we are finding an **element 'Sarah**' in it. This will return the position or the index where the element 'Sarah' is located first in the array.

We can clearly see that the element **' Sarah**' is located at the 2nd position first in the array. Note that the element is again repeated at position 6 but is not returned by the query because array_position() returns the index number where that element occurred first.

Now we will intentionally search for an element that is not present in the array to check the output. The query will be:

We can see that the query has returned NULL because it can not find the element in the array.

Consider another query as an example to demonstrate how the third argument will work in searching:
    
    
    SELECT array_position(ARRAY['John', 'Sarah', 'Peter', 'Alex', 'Williams', 'Sarah'], 'Sarah', 3 );

  * The array is **[ 'John', 'Sarah', 'Peter', 'Alex', 'Williams', 'Sarah']**
  * The element to be searched is **‘Sarah’**.
  * The third element indicated that you have to search for the element after that index position. This means if that element has occurred at a position before that specified index that will not count.



Let's see the output so it becomes more clear:

Now here you can see that the element ‘Sarah’ has appeared at index numbers 2 and 6 but the third argument is 3 which means that you have to look for the element ‘Sarah’ after index number 3. The query will return that index which represents the occurrence of ‘Sarah’ after index 3. That is why the query has returned 6.

So this is how the array_position() function works. We will move towards array_positions() next.

###  **PostgreSQL array_positions() Function**

The array_positions() function in PostgreSQL takes an array and an element as arguments and returns the index of all occurrences of that element in the array. The basic syntax for the function is given as:
    
    
    array_positions(Array, Element);

The array and the element are required arguments, the array is the first argument where the search will take place and the second argument is an element that is to be searched. The query will return all those indexes where the searched element has occurred. If the element is missing in that array, the function returns NULL.

Let's consider the below example to make it more clear.

 **Example**

To understand the concept of array_positions() more clearly, consider the query given below:
    
    
    SELECT array_positions(ARRAY['John', 'Sarah', 'Peter', 'Alex', 'Williams', 'Sarah'], 'Sarah');

In the above query:

  * The array is **[ 'John', 'Sarah', 'Peter', 'Alex', 'Williams', 'Sarah']**
  * The element to be searched is **‘Sarah’**.



Now the output of the above query is all the index positions where the element has occurred. The output is given below:

The element “Sarah” has occurred twice, first at index 2 position and second at index 6 position. The working of array_positions() is quite simple.

This is all about the working of both array_position() and array_positions() functions.

##  **Conclusion**

The difference between the Array_position() function and the Array_positions() function is that the Array_position() function gives the first occurrence of an element while the Array_positions() function gives all the occurrences of an element in an array. Both functions find the position of any element in an array. These functions take the array and the element as arguments and return the index of occurrence.

---
[View this page online](https://www.commandprompt.com/education/postgresql-array_position-vs-array_positions-whats-the-difference/)

---

# How to Use array_dims() Function in PostgreSQL

> The array_dims() gives out the information about the dimensions of an array. The array_dims() takes an array as a parameter and returns text that shows array d…

PostgreSQL offers a wide range of array functions, such as ARRAY_CAT(), ARRAY_REPLACE(), ARRAY_APPEND(), and so on. These functions can manipulate the array or get some information about the arrays depending upon how the function works. The array_dims() is one of the array functions that is used to find out the dimensions of an array.

Let's see how we use the array_dims() function.

 **How to Use array_dims() Function in PostgreSQL?**

The array_dims() gives out the information about the dimensions of an array. The array_dims() takes an array as a parameter and returns text. The basic syntax for the function is given below:
    
    
    array_dims(Array) -> TEXT

The array whose dimensions are to be checked is passed as an argument in the function. If the value in the function is NULL it will throw an error. The function returns a text having information about the dimensions of the array.

Let’s understand the topic better with an example.

 **Example**

Let's consider an array; [‘John’, ’Peter’]. If we want to get information about this particular array we will use the array_dims() function as follows:
    
    
    SELECT array_dims(ARRAY['John','Peter']);

When we execute the query, it will give the information about the dimensions of this array:

So the above query has returned **“[1,2]”** , which simply means the array passed is a one-dimensional array having indexes starting from 1 to 2.

Consider another example so that it is more clear to us:
    
    
    SELECT array_dims(ARRAY[
      ['John','Peter'],
      ['Willams','Sarah'],
      ['katherine','Alex']
       ]);

The output of the given query gives:

The two arrays for dimensions represent that the array is a 2-dimensional array, where the first array starts from index 1 to 3 and the second-dimensional array starts from index 1 to index 2.

Consider another example with a slightly more complexity level to check our concepts:
    
    
    SELECT array_dims(ARRAY[
      [['John','Peter']],
      [['Willams','Sarah']],
      [['katherine','Alex']]
       ]);

The output of the example is:

This clearly means that the array is 3-dimensional. The first-dimensional array starts from index 1 to 3, the second-dimensional array has index 1 to 1 means only one array in it, and the three-dimensional array has indexes from 1 to 3.

If we pass the array argument as NULL it will always throw an error.

 **Conclusion**

In order to get the dimension of a specific array we use the array_dims() function. An input array is provided to the function as a parameter and returns the information about its dimensions. If the argument in the function is NULL it will return an error. This post covered the functioning of the array_dims() function with the help of some practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-array_dims-function-in-postgresql/)

---

# How to Enable a Trigger in PostgreSQL

> To enable a trigger in PostgreSQL, the “ALTER TABLE” statement is used with the “DISABLE TRIGGER” clause. We need to specify the name of the trigger associated…

In Postgres, users can manipulate the triggers by altering, enabling, disabling, creating, or dropping a trigger. In this post, we’ll specifically talk about enabling a trigger in Postgres. We can enable a trigger or multiple triggers that are linked with a table. When we want to enable only one trigger we will have to specify its name; while if we want to enable all the triggers associated with a table we will simply use **ALL**.

##  **How to Enable a Trigger in PostgreSQL?**

We can enable triggers associated with the table by using the **ALTER TABLE ENABLE TRIGGER** command. The basic syntax for this command is:
    
    
    ALTER TABLE tab_name
    ENABLE TRIGGER trig_name |  ALL;

The name of that table to which the trigger is associated is written after the ALTER TABLE statement. After ENABLE TRIGGER, the name of the trigger that needs to be activated/enabled is written. In case you want to enable multiple triggers linked with the table you can use the ALL keyword.

 **Example:**

We will enable the trigger “status_update” from table “project_status” in the query below:
    
    
    ALTER TABLE project_status  
    ENABLE TRIGGER status_update;

The output proves the successful alteration of the table:

A similar thing can be done by this query:
    
    
    ALTER TABLE project_status  
    ENABLE TRIGGER ALL;

## 

##  **Conclusion**

To enable a trigger in PostgreSQL, the “ALTER TABLE” statement is used with the “DISABLE TRIGGER” clause. We need to specify the name of the trigger associated with a particular table in case of enabling one trigger. In case of enabling all the triggers related to a database table, we can simply use the **ALL** keyword.

---
[View this page online](https://www.commandprompt.com/education/how-to-enable-a-trigger-in-postgresql/)

---

# How to List Triggers in PostgreSQL Database

> In PostgreSQL, different methods are used to list all the triggers associated with a database, such as &quot;pg_trigger catalog&quot;, &quot;psql&quot; command, and SQL queries.

Triggers are the functions that are fired/invoked when a certain specified event occurs. Sometimes we need to list the triggers in PostgreSQL to know which triggers and how many triggers are linked/associated to a table. In this article, we will look at the methods to list down all the triggers in our database and also list all the triggers related to a database.

##  **How to List Triggers in PostgreSQL Database**

There are three ways to list down triggers in PostgreSQL. These methods are:

● Method: 1 - Using SQL queries.

● Method: 2 - Using psql.

● Method: 3 - Using pg_trigger catalog.

Let’s learn about all 3 of these methods one by one.

 **Method 1: Using SQL Queries**

To list all the triggers associated with a database, we need to refer to “event_object_table”. This is the table where the triggers are defined. We also need to refer to the “[i](<https://www.postgresql.org/docs/current/information-schema.html>)[nformation_schema](<https://www.postgresql.org/docs/current/information-schema.html>)”, which provides us with information about our schema and tables or simply our current database. We can access some information about our tables and their metadata through _information_schema._ We will get information about triggers from the information schema. The query will look like this:
    
    
    SELECT event_object_table AS tab_name ,trigger_name 
     FROM information_schema.triggers 
     GROUP BY tab_name,   trigger_name 
     ORDER BY tab_name,trigger_name ;

This query will give us information about all the triggers in our database along with their associated tables. Currently, my database contains only three tables that have triggers so this will be the output of the above query:

  
Now if we want to list the triggers associated with a specific table, we will just have to add a where statement to specify the name of that particular table. The query will be customized like this:
    
    
    SELECT event_object_table AS tab_name ,trigger_name  
     FROM information_schema.triggers 
     WHERE event_object_table ='project_status' 
     GROUP BY tab_name , trigger_name 
     ORDER BY tab_name,trigger_name;

This query will give us all the triggers associated with the table ”project_status”. In my case, it had only one trigger so only one was enlisted in the output.

  
This was all about the first method, in the second method we will see how can we do the same task using psql.

 **  
Method 2: Using psql**

We can also get the list of triggers associated with a table using psql. We have also discussed this method before on the topic of “Alter triggers”. let’s have a brief look at this topic.

We can view all the triggers associated with a table by running the **\dS** command in psql tool. The following are the steps:

 **Step 1:**

First of all, open **psql** in your local system. We will be connecting to our database where we want to create a table. Enter your password when it asks for “ _Password for user postgres_ ”. you will see the following:

 **  
Step 2:**

Now write the command as “ **\dS your table name** ”. In my case, it is “\dS project_status”. So this will give all the triggers related to the table.

You can see on the very last line, that is the trigger linked to this table.

 **Method 3: Using pg_trigger Catalog**

The third and last method for getting the list of triggers associated with a specific table is using pg_trigger catalog. “[ _Pg_trigger catalog_](<https://www.postgresql.org/docs/current/catalog-pg-trigger.html>) _”_ keeps and stores triggers on the tables. To get the triggers for a table using the pg_trigger catalog we write the following query:
    
    
    SELECT 
      tgname AS trig_name
     FROM 
      pg_trigger
     WHERE
      tgrelid = 'project_status'::regclass
     ORDER BY
      trig_name;

“tgname” is the trigger name. ”tgrelid” refers to the table the trigger is on and the name of the table needs to be specified after that. The output of the query gives the triggers associated with the table ”project_status”.

  
These are the three ways we can list the triggers for our database tables.

##  **Conclusion**

In this blog post, we have enlisted 3 ways to list the triggers in our database. In the first method by using the **SQL queries** we can list the triggers associated with any table. The second method was using the **psql command** and lastly, we saw the method to list the triggers using the **pg_trigger catalog**. All these methods help us in getting the triggers.

---
[View this page online](https://www.commandprompt.com/education/how-to-list-triggers-in-postgresql-database/)

---

# How to Drop a Trigger in PostgreSQL

> In PostgreSQL, a trigger can be dropped from the table by specifying the name of the trigger and the name of the table to which it is associated.

Triggers are the functions that are fired/invoked when a certain specified event occurs. In Postgres, we can manipulate the triggers using different commands, such as CREATE TRIGGER, DROP TRIGGER, etc. Users can enable, disable, alter, create, or drop a trigger according to their needs.

In this article, we will particularly talk about dropping a trigger from the table, which means deleting a trigger that is associated with the table.

##  **How to Drop a Trigger in PostgreSQL?**

In PostgreSQL, we use the DROP TRIGGER statement to remove a trigger from a database table. Below given is the basic syntax for this particular statement.
    
    
    DROP TRIGGER [IF EXISTS] trig_name 
    ON tab_name [ CASCADE | RESTRICT ];

In the above syntax:

  * After the DROP TRIGGER statement, specify the name of the trigger that you want to drop,
  *  **IF EXIST** is a condition that drops a trigger only in a condition if it exists. Note that if we want to delete a trigger that does not exist, it will result in an error. To overcome this problematic situation we use the IF EXIST statement. When we want to drop a trigger by using the IF EXIST statement, and if that trigger is not present it would simply raise a notice rather than throwing an error.
  * We need to write the table name after the ON command.
  * The CASCADE option is used if we also want to drop the objects that depend on the trigger automatically. It will also delete the object that depends on the objects depending on the triggers.
  * Or else we use the RESTRICT statement. The RESTRICT statement restricts dropping the objects that depend on triggers. By default, the DROP TRIGGER statement in PostgreSQL used the RESTRICT statement.



Here one thing to be remembered is that the trigger names are not limited to the tables so we can write the syntax simply as:
    
    
    DROP TRIGGER trig_name;

 **Example**

Let’s consider an example of the database table possessing the status of the projects being developed in a software house. Let's suppose the query for the table is as follows:

 **Step 1: Create a table**

First, we will be creating a table named "project_status".
    
    
    DROP TABLE IF EXISTS project_status;
    
    CREATE TABLE project_status(
     id INT GENERATED ALWAYS AS IDENTITY,
       proj_name TEXT NOT NULL,
       proj_status TEXT NOT NULL,
       managed_by TEXT NOT NULL,
       PRIMARY KEY(id)
    );

And insert these values into the table.
    
    
    INSERT INTO project_status( proj_name, proj_status ,managed_by )
     VALUES ('Game app', 'In progress', 'John'),
          ('Chat application', 'Completed', 'Williams'),
               ('Online Food ordering App', 'tested', 'sarah');

The table is successfully created and the values are inserted in the table.

 **  
Step 2: Create a Trigger Function**

We will now write a query for the creation of the trigger function.
    
    
    CREATE OR REPLACE FUNCTION change_status()
     RETURNS TRIGGER 
     LANGUAGE PLPGSQL
     AS
    $$
    BEGIN
     IF NEW.proj_status<> OLD.proj_status THEN
       RAISE NOTICE 'The project status was updated';
     END IF;
    
     RETURN NEW;
    END;
    $$

The query is working as the function returns a trigger. The OLD keyword refers to the status of a row, i.e. proj_status in this case, before the triggering event has occurred. The NEW keyword refers to the status of a row after the triggering event. So what the code actually does is, it says that if the proj_status (which is a row in the table) before and after the trigger event (that is” update” in this case we will have a look at it) are not equal( **< >** ) then it will raise notice that “The project status was updated”.

 **Step 3: Create a Trigger**

We will now be binding the trigger to the table. Consider the following query:
    
    
    CREATE TRIGGER change_status
     BEFORE UPDATE
     ON project_status
     FOR EACH ROW
     EXECUTE PROCEDURE change_status();

The trigger is created with the name “change_status” and it is specified that the trigger needs to be executed before the update command. The trigger has to be fired on the table”project_status” on each row. After EXECUTE PROCEDURE we write the trigger function declared above.

The trigger is successfully created:

 **  
Step 4: Fire the Trigger**

To bring the trigger in action we will update a value from the table. Consider the case, if we update the status of the project with ID 1 from “in Progress” to “completed” we will write the following query:
    
    
    UPDATE project_status
    SET proj_status = 'Completed'
    WHERE ID = 1;
    
    SELECT * FROM project_status;
    

The project status of the project with ID number 1 has been successfully updated:

Now go to the tables of your respective database in the side panel. And within the table, you are currently working with, you will see your triggers. Now if your recently created trigger should be present there. If not refresh the table by right-clicking on it. Your trigger can be seen there if it is created.

  
In the above side panel image, we can clearly see that the created trigger is present under the triggers category. Which simply means, the trigger has been created.

 **Step 5: Drop Trigger**

Now we will see if the drop trigger command works or not. Following will be the query for our considered case:
    
    
    DROP TRIGGER change_status
    ON project_status;

The trigger is successfully dropped using the above query:

  
We can also verify this from the side panel. Refresh your table to check for changes.

  
You will observe that there would be no trigger that you have dropped from the table.

 **Conclusion**

We can drop a trigger from the table by specifying the name of the trigger and the name of the table to which it is associated. Moreover, there are other keywords that are also used such as the IF EXISTS keyword that would drop the trigger if it exists if it is not then it will just raise a notice. CASCADE will drop the object related to that trigger whereas RESTRICT will avoid dropping objects.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-trigger-in-postgresql/)

---

# How to Disable a Trigger in PostgreSQL

> In PostgreSQL, the &quot;ALTER TABLE&quot; with the &quot;DISABLE TRIGGER&quot; clause is used to disable a trigger. We need to specify the name of the trigger associated with a p…

In PostgreSQL, we can manipulate the triggers. We can alter a trigger, enable and disable a trigger, and create or drop a trigger in Postgres. In this post, we will specifically learn and talk about disabling a trigger in Postgres. We can disable a trigger or multiple triggers associated/linked with a table.

 **How to Disable a Trigger in PostgreSQL?**

When we want to disable only one trigger we will have to specify its name and if we have to disable all the triggers associated with a table we will simply use ALL. When we disable a trigger, it still exists in our database. But when the operation associated with that trigger occurs, the trigger is not fired.

We can disable triggers associated/linked with the table by using the **ALTER TABLE DISABLE TRIGGER** command. The basic syntax for this command is:
    
    
    ALTER TABLE tab_name
    DISABLE TRIGGER trig_name |  ALL;

The name of that table to which the trigger is associated is written after the ALTER TABLE statement. After DISABLE TRIGGER, the name of the trigger that needs to be deactivated/disabled is written. In case you want to deactivate/disable multiple triggers linked with the table you can use the ALL keyword.

 **Example:**

We will disable the trigger “status_update” from table “project_status” in the query below:
    
    
    ALTER TABLE project_status  
    DISABLE TRIGGER status_update;

The output will ensure that the trigger has been deactivated:

  
A similar thing can be done by this query:
    
    
    ALTER TABLE project_status  
    DISABLE TRIGGER ALL;

The output for both the queries is same:

 **  
Conclusion:**

In PostgreSQL, the "ALTER TABLE" with the "DISABLE TRIGGER" clause is used to disable a trigger. We need to specify the name of the trigger associated with a particular table in case of disabling one trigger. In case of disabling all the triggers related to a database table, we can simply use the **ALL** keyword.

---
[View this page online](https://www.commandprompt.com/education/how-to-disable-a-trigger-in-postgresql/)

---

# What Do make_timestamp() and make_timestamptz() Functions do in PostgreSQL?

> In PostgreSQL, we use the make_timestamp() and make_timestamptz() functions to show the timestamps. Both functions give errors when the input parameters have s…

To show the timestamps we use the make_timestamp() and make_timestamptz() functions. The make_timestamp() function returns the timestamp without the timezone according to the input values and the make_timestamptz() function returns the timestamp with the time zone according to the parameters passed into the function. Both functions give errors when the input parameters have some issue maybe due to the wrong data type or due to out-of-range parameters.

This article will show how the make_timestamp() and make_timestamptz() functions work. Let’s get started.

 **What Do make_timestamp and make_timestamptz() Functions do in PostgreSQL?**

What these functions have in common is that they take parameters as input, make_timestamp() takes 6 parameters while make_timestamptz() takes 7 parameters of which 6 are required and one is optional, and then returns a value with the specific data type. The return type of value in the case of the make_timestamp() function is the simple timestamp without a time zone and in the case of the make_timestamptz() function is a timestamp with a time zone.

Let's discuss the make_timestamp() function first.

 **The make_timestamp() Function in PostgreSQL**

The make_timestamp() function manipulates the parameter it takes and converts it into a timestamp without a time zone. These parameters are 6 in number: Year, Month, Day, Hour, Minute, and Second. Remember that the sequence of these parameters has to be the exactly same otherwise, this could cause an error. The basic syntax for this function is:
    
    
    make_timestamp(Year INT, Month INT, Day INT, Hour INT, Minute INT, Second DOUBLE PRECISION);

All these parameters are required and the type of all of them should be **“Integer”** except second. The “second” parameter has to be of **DOUBLE PRECISION** data type.

Let’s move towards an example to see how this function works

 **Example**

Consider the following query as an example:
    
    
    SELECT make_timestamp(2023, 8, 24, 11, 31, 17.43);

The function in the above query will convert the parameters into a proper timestamp format as follows:

In the above output, you can see that the returned type of the function is a **timestamp without a time zone**. We can verify it by using the “pg_typeof()” function. The “pg_typeof()” function takes an argument and returns us the data type of that argument.

The query will look like this:
    
    
    SELECT pg_typeof(make_timestamp(2023, 8, 24, 11, 31, 17.43));

The output of the above query will clearly show the returned type:

  
So the make_timestamp() function always returns the value having data type **“timestamp without time zone”**.

Consider another example in which we will intentionally replace the value of a month parameter greater than 12 let's say it is 21. Let's see how will the query respond to this case.
    
    
    SELECT make_timestamp(2023, 21, 24, 11, 31, 17.43);

When we execute this query, the output will be:

  
The query gives an **“out of range”** error. This is because the value of the parameter month is more than 12 as the month in a year can not be greater than 12. The same case will happen to the other values.

 **Special case**

As we have discussed above, the data type of each parameter should be INT and for the second it should be DOUBLE PRECISION. According to PostgreSQL documentation, it should be INT and DOUBLE PRECISION but there is a special case. If we pass the arguments in strings this also seems to work without any issue as soon as the values are in their proper ranges. This may be because they can be implicitly converted into integers. Let’s see an example of this special case.
    
    
    SELECT make_timestamp('2023', '8', '24', '11', '31', '17.43');

By executing the above query we will get:

  
This means that under this condition the query also works properly.

But you have to make sure about one thing, the arguments must be valid to be converted into the INT. For example, if we execute the following query:
    
    
    SELECT make_timestamp('2023', 'August', '24', '11', '31', '17.43');

It will give an error that:

This is because the “August” is not valid and can not be converted into an integer lately.

That was all about make_timestamp() function. Now we will move towards the make_timestamptz() function.

 **The make_timestamptz() Function in PostgreSQL**

The make_timestamptz() function also works almost the same as make_timestamp(). It manipulates the parameter it takes into the timestamp with the time zone. These parameters are 7 in number: **year, month, day, hour, min, sec,** and **timezone text**. Remember that the sequence of these parameters has to be the exactly same otherwise, this could cause an error. The basic syntax for this function is:
    
    
    make_timestamp(Year INT, Month INT, Day INT, Hour INT, Minute INT, Second DOUBLE PRECISION, [ timezone text ]);

Note that, the first 6 parameters are required but the last parameter i.e. timezone text is optional. If this text is not passed, the current time zone is used.

All the parameter types should be “Integer” while for a second it has to be a “ **DOUBLE PRECISION** ”. The return value of the query is a **timestamp with time zone**.

Now let's move towards an example.

 **Example**

Consider the following query as an example:
    
    
    SELECT make_timestamptz(2023, 8, 24, 11, 44, 16.46,'Indian/Mauritius');

The function in the above query will convert the parameter into a proper timestamp with Indian timezone format as follows:

  
In the above output, you can see that the returned type of the function is **time with time zone**. We can verify it by using the “pg_typeof()” function.
    
    
    SELECT pg_typeof(make_timestamptz(2023, 8, 24, 11, 44, 16.46));

The output of the above query will clearly show the returned type:

  
Consider another example in which we will intentionally replace the value of a sec parameter greater than 60 let's say it is 78.45. Let's see how will the query respond to this case.
    
    
    SELECT make_timestamptz(2023, 8, 24, 11, 44, 78.45,'Indian/Mauritius');

When we execute this query, the output will be:

  
The query gives an **“out of range”** error. This is because the value of parameter sec is more than 60 as the seconds in a minute can not be greater than 60. The same case will happen to the other values as well.

 **Special case**

Similar to the make_timestamp() function, this function also has a special case. As we have discussed above, the data type of all parameters should be INT and for the second it is DOUBLE PRECISION. According to PostgreSQL documentation, they should be INT and DOUBLE PRECISION but there is a special case. If we pass the arguments in strings this also seems to work without any issue as soon as the values are in their proper range. Let’s see an example of this special case.
    
    
    SELECT make_timestamptz('2023', '8', '24', '11', '50', '18.45');

By executing the above query we will get:

  
This means that under this condition the query also works properly. But if any of the arguments exceeds its range, it will give the out-of-range error. Here you can also notice one thing I haven’t specified any timezone, so it has taken the indian timezone because currently it is the indian timezone.

 **Conclusion**

There are many functions in PostgreSQL used to manipulate the time. The functions make_timestamp() and make_timestamptz() are significant among those and are used to get the timestamps without and with the time zones respectively.

---
[View this page online](https://www.commandprompt.com/education/what-do-make_timestamp-and-make_timestamptz-functions-do-in-postgresql/)

---

# How to Create a Trigger in PostgreSQL

> Triggers are useful in many ways such as keeping an audit for changes and transactions, applying the business rules, and validating the user input data.

PostgreSQL trigger functions are similar to regular **user-defined functions**. They are invoked when a particular database event (for example INSERT, UPDATE, DELETE) occurs. Triggers do not take any argument or parameters and return a value having a type **trigger**.

##  **What are Triggers in Postgres?**

Triggers are set to take action usually in the following cases:

  * Before taking some action on the row, such as checking constraint and INSERT, UPDATE, and DELETE actions are taken.
  * After completion of some actions, such as checking constraints and INSERT, UPDATE, and DELETE actions have been completed.
  * In spite of any action on a row such as INSERT, UPDATE, and DELETE actions on a view.



###  **Types of Triggers**

There are basically two types of triggers:  


● **Row Level Triggers**

A trigger created as **FOR EACH ROW** is fired once for each row which is getting modified by the operation.

● **Statement Level Trigger**

A trigger marked as **FOR EACH STATEMENT** is fired once for each statement or transaction regardless of how many rows are modified.

 **Example**

If a database contains 2000 rows, and we are applying the UPDATE command to update the records. Now if we use the **FOR EACH ROW** command, it will fire 2000 times, once for each updated row. But if we use FOR EACH STATEMENT, it will be fired only one time regardless of how many rows have been updated.

Let's learn how triggers are created in PostgreSQL.

##  **How to Create a Trigger in PostgreSQL?**

Following are the steps that we need to follow to create a trigger in Postgresql:

  1. First, We create a “trigger function” using the CREATE FUNCTION command.
  2. Second, we use the CREATE TRIGGER statement to connect/bind the trigger function to the table.



 **Creating Trigger Function**

Create a "trigger function" as the initial step. A trigger function is basically defined by the user. This function does not need any argument to be passed into it and it returns the value having a data type trigger. The trigger function is created using the CREATE FUNCTION command.

The following code illustrates the syntax for creating a trigger function:
    
    
    CREATE FUNCTION trig_function() 
     RETURNS TRIGGER 
     LANGUAGE PLPGSQL 
     AS $$ 
     BEGIN 
      -- code for trigger
     END; $$

In the above syntax, the language used to create the trigger function is PL/pgSQL but we can create it using any of the languages supported by PostgreSQL.

The trigger function gets the information about its calling event through TriggerData, which contains some set of local variables. For example, the words “OLD” and “NEW” refer to the status of the row. The OLD keyword refers to the status of the row, i.e. proj_status in this case, before the triggering event has occurred. The NEW keyword refers to the status of the row after the triggering event.

 **Binding Trigger Function to the Table**

After creating the trigger function, we can attach it to one or multiple triggering operations such as UPDATE, INSERT, and DELETE for the table. We do this by querying the CREATE TRIGGER command. Let's have a look at its syntax:
    
    
    CREATE TRIGGER trig_name 
      {BEFORE | AFTER |INSTEAD OF} { event_name }
      ON tab_name
      [FOR [EACH] { ROW | STATEMENT }]
      EXECUTE PROCEDURE trig_function

In the above syntax:

● trig_name specifies the name of the trigger which we have to specify after the keyword TRIGGER.

● {BEFORE | AFTER |INSTEAD OF} specify the time of trigger execution.

● Event_name is the name of the event/operation that is to be triggered such as UPDATE, INSERT, and DELETE.

● Tab_name gives the name of the table on which the trigger is to be executed/fired.

● [FOR [EACH] { ROW | STATEMENT }] specifies the type of trigger and we have already discussed the types of triggers in the above section.

● EXECUTE PROCEDURE is followed by the trigger function that is to be executed when a trigger is fired.

 **Example:**

Let’s consider an example of the database table possessing the status of the projects being developed in a software house. Let's suppose the query for the table is as follows:
    
    
    DROP TABLE IF EXISTS project_status; 
    CREATE TABLE project_status(
      id INT GENERATED ALWAYS AS IDENTITY,
      proj_name TEXT NOT NULL,
      proj_status TEXT NOT NULL,
      managed_by TEXT NOT NULL,
      PRIMARY KEY(id)
       );

Now insert values to the table:
    
    
    INSERT INTO project_status( proj_name, proj_status ,managed_by )
      VALUES ('Game app', 'In progress', 'John'),
        ('Chat application', 'Completed', 'Williams'),
      ('Online Food ordering App', 'tested', 'sarah');

The table is given as:

  
Now consider the case if we want to change the status of the project and log these manipulations in the other table called “project_audits”:
    
    
    CREATE TABLE project_audits (
      id INT GENERATED ALWAYS AS IDENTITY,
      proj_status VARCHAR(225) NOT NULL,
      updated_on TIMESTAMP(6) NOT NULL
       );

Now we will be creating a trigger function called, change_status. The function returns a trigger. The syntax would look like this:
    
    
    CREATE OR REPLACE FUNCTION change_status()
      RETURNS TRIGGER 
      LANGUAGE PLPGSQL
      AS
       $$
     BEGIN
      IF NEW.proj_status<> OLD.proj_status THEN
       INSERT INTO   project_audits(proj_status,updated_on)
       VALUES(OLD.proj_status,now());
      END IF;
     RETURN NEW;
     END;
       $$

Here we can see two keywords i.e. **OLD** and **NEW**. The OLD keyword refers to the status of the row, i.e. proj_status in this case, before the triggering event has occurred. The NEW keyword refers to the status of the row after the triggering event.

So what the code actually does is, it says that if the proj_status (which is a row in the table) before and after the trigger event (that is "update” in this case we will have a look at it) are not equal( **< >** ) then insert two columns into the “project_audits” table that is proj_status and updated_on, having the values old value of proj_status and the current time respectively.

The function has been created:

  
Next we have to bind the trigger function to the table so we will write the following syntax:
    
    
    CREATE TRIGGER change_status
      BEFORE UPDATE
      ON project_status
      FOR EACH ROW
      EXECUTE PROCEDURE change_status();

The trigger is created with the name “change_status” and it is specified that the trigger needs to be executed before the update command. The trigger has to be fired on the table”project_status” on each row. After EXECUTE PROCEDURE we write the trigger function declared above.

The trigger is successfully created:

If we update the status of the project with ID 1 from “in Progress” to “completed” we will write the following query:
    
    
    UPDATE project_status
     SET proj_status = 'Completed'
     WHERE ID = 1;
    SELECT * FROM project_status;

The project status of the project with ID number 1 has been successfully updated:

  
As seen in the above output, the status of the project has been updated. Now he will have to verify whether the change has also been reflected in the “project_audits” table or not.
    
    
    SELECT * FROM project_audits;

The query results in

  
This means that our trigger event has worked correctly.

 **Benefits of Trigger**

Triggers are useful in many ways. Some of them are enlisted below:

● Triggers can be used for audit purposes. We can get the record of every transaction as we have seen a similar case in the example above.

● Triggers can handle errors related to the DB.

● Triggers are defined once and can be reused throughout an application.

● Triggers can counteract any invalid data exchange. They are usually used for validating input data.

 **Conclusion**

Triggers are useful in many ways such as keeping an audit for changes and transactions, applying the business rules, and validating the user input data. This function also assists in duplicating the data to several files which results in data consistency. We first need to create a function that is basically the trigger function and knows what to do when a trigger is fired. Then we create the trigger and bind it to the table. This is how triggers work.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-trigger-in-postgresql/)

---

# How to Alter a Trigger in PostgreSQL

> A trigger can be altered in PostgreSQL by using the ALTER TRIGGER command. We can rename the trigger and then verify if the change in name has occurred or not.

In Postgres, we can manipulate the triggers. We can alter a trigger, enable and disable a trigger, create a trigger, or drop a trigger. In this article, we will specifically learn about altering a trigger in Postgres. There are several statements that are commonly used to manipulate the triggers in Postgres and the ALTER statement is one of them. ALTER TRIGGER command is used to rename an existing trigger.

##  **How to Alter a Trigger in PostgreSQL?**

To alter a trigger, the ALTER TRIGGER command is used. The basic syntax for the ALTER command in PostgreSQL is given as
    
    
    ALTER TRIGGER trig_name
     ON tab_name 
     RENAME TO updated_name;

The ALTER TRIGGER is followed by the name of that trigger that is to be altered. ON is followed by the table name to which that trigger is associated. Lastly, the RENAME TO clause is followed by the new or updated name we want to have for that trigger.

 **Example**

Let’s consider an example of the database table possessing the status of the projects being developed in a software house. Let's suppose the query for the table is as follows:
    
    
    DROP TABLE IF EXISTS project_status; 
    CREATE TABLE project_status(
      id INT GENERATED ALWAYS AS IDENTITY,
      proj_name TEXT NOT NULL,
      proj_status TEXT NOT NULL,
      managed_by TEXT NOT NULL,
      PRIMARY KEY(id)
       );

Now insert values to the table:
    
    
    INSERT INTO project_status( proj_name, proj_status ,managed_by )
      VALUES ('Game app', 'In progress', 'John'),
        ('Chat application', 'Completed', 'Williams'),
      ('Online Food ordering App', 'tested', 'sarah');

The table is given as:

  
Now consider the case if we want to change the status of the project and log the changes in another table called “project_audits”:
    
    
    CREATE TABLE project_audits (
      id INT GENERATED ALWAYS AS IDENTITY,
      proj_status VARCHAR(40) NOT NULL,
      updated_on TIMESTAMP(6) NOT NULL
       );

Now create a trigger function called, change_status. The function returns a trigger. The syntax would look like this:
    
    
    CREATE OR REPLACE FUNCTION change_status()
      RETURNS TRIGGER 
      LANGUAGE PLPGSQL
      AS
       $$
     BEGIN
      IF NEW.proj_status<> OLD.proj_status THEN
       RAISE NOTICE 'The project status was updated';
      END IF;
     RETURN NEW;
     END;
       $$

Here we can see two keywords i.e. **OLD** and **NEW**. The OLD keyword refers to the state of the row, i.e. proj_status in this case, before the triggering event has occurred. The NEW keyword refers to the state of the row after the triggering event. So what the code actually does is, it says that if the proj_status (which is a row in the table) before and after the trigger event (that is” update” in this case we will have a look at it) are not equal( **< >** ) then it will raise notice that “The project status was updated”.

The function has been created:

  
Now we have to bind the trigger function to the table so we will write the following syntax:
    
    
    CREATE TRIGGER change_status
      BEFORE UPDATE
      ON project_status
      FOR EACH ROW
      EXECUTE PROCEDURE change_status();

The trigger is created with the name “change_status” and it is specified that the trigger needs to be executed before the update command. The trigger has to be fired on the table”project_status” on each row. After EXECUTE PROCEDURE we write the trigger function declared above.

The trigger is successfully created:

  
If we update the status of the project with ID 1 from “in Progress” to “completed” we will write the following query:
    
    
    UPDATE project_status
     SET proj_status = 'Completed'
     WHERE ID = 1;
     SELECT * FROM project_status;

The project status of the project with ID number 1 has been successfully updated:

  
As seen in the above output, the result of the query is as we expected. Now we will alter the trigger. The syntax will look like this:
    
    
    ALTER TRIGGER change_status
     ON project_status
     RENAME TO status_update;

The ALTER TRIGGER command was followed by the name of the trigger i.e. change_status which is associated with the table project_status and we have renamed it to “status_update”. The trigger has been successfully altered.

 **  
View Triggers in psql**

We can view all the triggers associated with a table by running the **\dS** command in the psql tool. For this, open **psql** in your local system. We will be connecting to our database where we want to create a table. Enter your password when it asks for “ _Password for user postgres_ ”. You will see the following:

  
Now write the command as “ **\dS your table name** ”. In my case, it is “\dS project_status”. So this will give all the triggers related to the table.

  
In the very last line, you can see the trigger we have just altered. So this means that the trigger has been altered and it is the only trigger that is associated with this particular table.

 **Conclusion**

A trigger can be altered in PostgreSQL by using the ALTER TRIGGER command. We can rename the trigger and then check whether the change in name has occurred or not by running some command in the psql shell. This Postgres blog has demonstrated the process of altering a trigger in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-alter-a-trigger-in-postgresql/)

---

# How to Use date_bin() Function in PostgreSQL

> The date_bin() function is used to truncate a specified timestamp into another timestamp using an interval based on the original timestamps.

In PostgreSQL, there are many functions that are being used to manipulate the date and time. One of the most important and commonly used functions is the date_bin() function. This function truncates the timestamp specified to the beginning of the nearest interval specified as an argument. The interval, origin timestamp, and the source timestamp are specified in the function as arguments.

In this article, we will have a deep look into the functioning of the date_bin() function.

 **How to Use date_bin() Function in PostgreSQL?**

The date_bin() function enables us to “bin” the specified timestamp into given intervals in order to align it with the origin. The basic syntax of the function is given as:
    
    
    date_bin(Stride INTERVAL, Source TIMESTAMP, Origin TIMESTAMP);

In the above syntax:

  * The stride is the time interval. For example; if the stride is “10 minutes” it means that we will be using 10 minutes as our time interval. So there will be 6 time points for 10 minutes i.e. 0 min,10 min,20 min, 30 min,40 min, and 50 min.
  * The source timestamp is the timestamp that we will be processing and working with.
  * The third argument is the origin. If the timestamp of the origin contains the time points, we will use that time point as an offset for the source timestamp to truncate. We will cater to all these concepts with examples so it will be more understandable.
  * The data type of Stride is **INTERVAL** , and the source and origin is **TIMESTAMP**. The function returns a "TIMESTAMP without time zone" data type value.



Let us expand on the subject with some examples.

 **Examples**

Consider the query below as an example to make the topic more clear:
    
    
    SELECT date_bin('10 minutes', TIMESTAMP '2023-08-29 10:34:19', TIMESTAMP '2000-05-01');

In the above query:

● The stride or the interval is specified as “10 minutes”.

● The timestamp that needs to be processed is “2023-08-29 10:34:19”.

● And lastly, the origin timestamp is “2000-05-01”.

Now we'll try to figure out how the query will work.

The stride/interval is “10 minutes” which means that the time points for this interval will be 0 mins,10 mins, 20 mins, 30 mins, 40 mins, and 50 mins. You can see that after 50 mins it will return to 0 mins then 10 min then 20 mins and so on. It means that the time points will remain the same for every hour and every day.

The same time points are repeated every hour hence every day. The same will be the time points every hour and in fact every day between “2000-05-01” to “2023-08-29 10:00:00”. Now we will see the time points from 10:00:00 onwards are; 10:10:00, 10:20:00, 10:30:00, 10:40:00, and so on.

So to truncate the source timestamp we basically look for the closest time point before the given source timestamp time. So in the above case, the closest time point before the “10:34:19” timestamp to truncate on is “10:30:00”. So the query will return it as output along with the date like this:

How it works:

This was a simple case with no time part in the origin timestamp. Now if there is a time part in the origin timestamp the scenario will be slightly different.

In case there is a time part in the origin timestamp, the basic functioning of the date_bin() function remains the same just an offset is added to the interval. The offset means that the interval will start from a specific time that is specified in the origin timestamp. Let's consider the following query to discuss this particular case:
    
    
    SELECT date_bin('10 minutes', TIMESTAMP '2023-08-29 10:34:19', TIMESTAMP '2000-05-01 00:05:02');

In this case, a time part is added to the origin timestamp which is ”00:05:02”. This means that the intervals will start from “00:05:02” i.e. 05:02, 15:02, 25:02, 35:02, 45:02, and 55:02 for every hour and every day between “2000-05-01” to “2023-08-29 10:00:00”. Now we will see the time points from 10:05:02 onwards are; 10:15:02, 10:25:02, 10:35:02, 10:45:02, and so on. So to truncate the source timestamp we basically look for the closest time point before the given source timestamp time. So in the above case, the closest time point before the “10:34:19” timestamp to truncate on is “10:25:02”.

The query will return it as output along with the date like this:

This is the basic working of the date_bin() function.

 **Conclusion**

The date_bin() function is used to truncate a specified timestamp into another timestamp using an interval based on the original timestamps. The interval, origin timestamp, and the source timestamp are specified in the function as arguments.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-date_bin-function-in-postgresql/)

---

# How the Exp() Function Works in PostgreSQL

> The Exp() function in Postgresql takes a numeric value as an input and returns a value having a Numeric data type or specifically DOUBLE PRECISION.

In PostgreSQL, the **exp() function** finds the natural constant "e" raised to the power that is specified. The power is passed into the function as an argument. The number is a numeric value that can be positive, negative, zero, decimal, or an integer. The function will return the exponential value of the number you specify.

In this article, we will learn about how the exp() function works in PostgreSQL.

##  **How to Use Exp() Function in PostgreSQL?**

The Exp() function in Postgresql takes a numeric value as an input and returns a value having a Numeric data type or specifically **DOUBLE PRECISION**. The basic syntax for the function is:
    
    
    Exp(Numeric_Value);

The function returns a **NULL** if the numeric values passed as an argument are NULL. It will throw an error when the value passed is of some other data type than numeric.

Let’s move toward an example that will clearly elaborate on the concept.

 **Example**

The simple query for the Exp() function is given below:
    
    
    SELECT
      exp(10) AS "exp of 10",
      exp(9) AS "exp of 9",
      exp(8) AS "exp of 8",
      exp(7) AS "exp of 7",
      exp(6) AS "exp of 6";

The output of the given query will be the additional columns having the values of the exp(values) like this:

  
In the above output, we can clearly see that the returned data type of this function is DOUBLE PRECISION. So this was all about the Exp() function.

##  **Conclusion**

The Exp() function finds the exponential value of the specified power. This numeric value needs to be passed into the function. It may contain positive, negative, zero, decimal, or integer values. The function returns the exponentiation of a number that is specified as an argument and that value will have DOUBLE PRECISION data type.

---
[View this page online](https://www.commandprompt.com/education/how-the-exp-function-works-in-postgresql/)

---

# How to Use cbrt() Function PostgreSQL

> The cbrt() function in PostgreSQL takes a numeric value as an input and returns a value having DOUBLE PRECISION data type.

The **cbrt() function** finds the cube root of a number in PostgreSQL. The specified number is passed into the function as an argument. The number is a numeric value that can be positive, negative, zero, decimal, or an integer. The function will return the cube root of the given number.

In this article, we will learn about how the cbrt() function works in PostgreSQL.

##  **How to Use cbrt() Function in PostgreSQL?**

The cbrt() function in PostgreSQL takes a numeric value as an input and returns a value having **DOUBLE PRECISION** data type. The basic syntax for the function is:
    
    
    cbrt(Numeric_Value);

The function returns a NULL if the numeric values passed as an argument are NULL. The cbrt() function will throw an error if the value passed as an argument is of some other data type than numeric.

Let’s see the example of the functioning of this function.

 **Example**

The simple query for the cbrt() function is given below:
    
    
    SELECT
        cbrt(1) AS "cube root of 1",
        cbrt(64) AS "cube root of 64",
        cbrt(-343) AS "cube root of -343",
        cbrt(2.194) AS "cube root of 2.194";

The output of the given query will be the additional columns having the values of the cube roots like this:

  
In the above output, we can clearly see that the returned data type of this function is DOUBLE PRECISION. So this was all about cbrt() function.

##  **Conclusion**

The cbrt() function is used to find the cube root of a numeric value. This numeric value needs to be passed into the function. It may contain positive, negative, zero, decimal, or integer values. The cbrt() function gives the cube root of the argument value and that return value will have DOUBLE PRECISION data type.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-cbrt-function-postgresql/)

---

# Exception Handling in PostgreSQL

> Exceptions are unexpected issues that we encounter while executing a program code. These disturb and sometimes abort the normal functioning of the program.

**Exceptions** are the unexpected issues that we encounter when executing a program code and it disturbs the functioning of a program. Exceptions can take place due to many reasons including; device failure, wrong user input, insufficient memory for execution of a program or an application, error in code, device failure, division by zero and returning undefined values, network connection issues, etc.

To effectively handle these issues exception handling is done so that the program runs normally and the flow of the system is not disturbed. Exception handling basically prevents the program or system from crashing.

##  **How to Handle Exceptions in PostgreSQL?**

In PostgreSQL, exceptions are handled using PL/pgSQL, which is a procedural language. PL/pgSQL provides thorough mechanisms to catch and handle the exceptions that are likely to be encountered in the database during the execution.

When an exception occurs in a block, PostgreSQL terminates the execution of the block and its related transition.

 **Note:** Block is basically a collection of program statements, which are written in a BEGIN-END block structure in PL/pgSQL.

The basic syntax for exception handling in PostgreSQL is:
    
    
    BEGIN
    -- Write your Code here
    EXCEPTION
    WHEN exception_type1 THEN
    -- Write code for Exception handling 
    WHEN exception_type2 THEN
    -- Code for second Exception handling
    END;

In the above code:

  * The BEGIN and END indicate the opening and closing of the block.
  * Within the BEGIN and END blocks, we can write our code/program.
  * If we want to handle exceptions, we will have to add another section in the block. This section is indicated by the **EXCEPTION** keyword.
  * After writing this keyword, we will have to specify the situation with the **WHEN** keyword which extends the exception type.
  *  **WHEN** keyword is followed by a **THEN** keyword which will include the exception handling code.
  * The EXCEPTION keyword will work as if we encounter a specific type of exception during the execution, then the program will handle it in this way(specified in the exception handling code).
  * This thing repeats for all the possible exceptions that are likely to interrupt our execution. And we have discussed the exception types above.



Let's move toward the example, which will make the concept of exception handling more clear.  


 **Example: Understanding Exception Handling in Postgres**

We will take an example where the program is heading towards the division by zero situation. Let’s consider the following code to understand how exceptions are handled in Postgres:
    
    
    DO
       $$
     DECLARE 
      exp_variable int;
     BEGIN
      SELECT 1/0 INTO exp_variable;
     END;
       $$
       language plpgsql;

A variable _exp_variable_ is declared under the DECLARE statement. Under the BEGIN clause, we are basically selecting 1/0 and assigning it to the result variable. The output for the given query will be:

  
So the above query returns an exception. We need to handle this exception. For that, we will add an EXCEPTION statement to it, in order to handle it effectively.
    
    
    DO
       $$
     DECLARE 
      exp_variable int;
     BEGIN
      SELECT 1/0 INTO exp_variable;
     --   exception example based on SQL ERROR CODE
      EXCEPTION
      WHEN division_by_zero THEN
      exp_variable := NULL;
      RAISE NOTICE 'Exception   has been handled';
     END;
       $$
       language plpgsql;

This will result in:

  
Similarly, we can write handling code for as many exceptions that are expected to occur and can terminate the normal functioning of our program.

##  **Conclusion**

Exceptions are unexpected issues that we encounter while executing a program code. These disturb and sometimes abort the normal functioning of the program. That's why we need to cater to these exceptions and handle them properly. For that, we write some exception-handling code under the keyword “EXCEPTION”. We write the exception-handling code for all the possible exceptions that are likely to interrupt the execution.

---
[View this page online](https://www.commandprompt.com/education/exception-handling-in-postgresql/)

---

# How to Get Records From the Last 24 Hours in PostgreSQL

> To get records from the last 24 hours in Postgres, execute the &quot;SELECT * &quot; command and set a condition to subtract &quot;24 hours&quot; from the current DateTime.

Sometimes we need to get our past records from the PostgreSQL database. These records are usually used for crucial purposes such as for analysis, reporting, etc. This data seems to be very beneficial for the e-commerce platforms to track sales of their products and to understand their activity in the market.

In this article, we will learn how to fetch table records from the last 24 hours in Postgres.

##  **How to Get/Fetch Table Data From the Last 24 Hours in Postgres?**

We can get our data records from the last 24 hours by using the now() function and specifying the interval for which we want to retrieve the data.

 **Example: Getting Records From Last 24 Hours in Postgres**

Let’s suppose we had the following database table named “store_sales_details”:
    
    
    SELECT * FROM store_sales_details;

  
Now if we want to get sales of the last 24 hours, we will have to run the following query:
    
    
    SELECT * from store_sales_details
     WHERE Time_and_date_of_order > now() - interval '24 hours';

In the above query:

\- We used a PostgreSQL function “ **NOW()** ”. This function gets the current DateTime at that instance.

\- Another clause used is the “ **INTERVAL** ” clause. This clause is used to select the rows where the “order_data” falls in the past 24 hours.

\- The entire query will certainly retrieve all the data that has been inserted into the database over the past 24 hours. The resulting output is given below:

  
That’s all about fetching records from the last 24 hours in PostgreSQL.

##  **Conclusion**

To retrieve records from the last 24 hours in PostgreSQL, execute the "SELECT * " command and set a condition to subtract "24 hours" from the current DateTime. Use the Postgres’ NOW() function to get the current DateTime at that instance. The fetched records can be used to analyze the sales and gain more insights. This write-up has explained a detailed guide on getting records from the last 24 hours in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-records-from-the-last-24-hours-in-postgresql/)

---

# How to Use ASSERT Statement in PostgreSQL

> PostgreSQL provides an ASSERT statement for inserting debugging checks for the program. The ASSERT statement provides a condition to the program.

PostgreSQL provides an **ASSERT** statement to insert necessary debugging checks in the PL/pgSQL program. It is very crucial to take out the logical errors from the code in order to retain the normal functioning of the code. For this purpose, the ASSERT statement serves as a savior. It can also help us debug the errors related to the written code. Let's see how the assertion statement is useful.

##  **How to Use ASSERT Statement in PostgreSQL?**

ASSERT statement in PostgreSQL allows us to add some debugging checks to the code. Basically, through an ASSERT statement, a condition is imposed at a certain place in the code. If the code satisfies that condition, the program continues to run normally but if it fails the condition, it will throw an assertion error.

  
The basic syntax for the ASSERT statement is illustrated below:
    
    
    ASSERT condition [, message];

The following are the main components of the above ASSERT query:  


 **Condition**

The condition in the above syntax always returns a Boolean value. If the condition returns true, the program continues to run normally, ASSERT does nothing. If the condition returns false or null, the ASSERT statement will throw an ASSERT_FAILURE error.

 **Message**

The message part is completely optional. In case, this message is not passed into the ASSERT statement, by default the statement will consider it an “assertion failed” error message when the condition fails. But if this message is specified, the ASSERT statement will show that message.

 **Note** : Please note that the assert statement is meant to be used for detecting bugs and logical errors in a code. It is not for reporting common and ordinary issues and error messages. To report error messages RAISE statement is used.

 **Disable/enable Assertion Testing**

By default, the assertion configuration testing is ON. But we can disable the assertion testing if we want to this can be done if we go to the “plpgsql.check_asserts” parameter and set it to OFF. Then the ASSERT statement will stop functioning.

Let’s see how an ASSERT statement works using an example.

 **Example**

Let's consider the table of the data of the candidates that are appearing in the entrance test of a university for higher education. The table contains 4 columns and multiple entries.

  
Now we will use the ASSERT statement on the table to see if the table “test_scores” has entries in it or not.
    
    
    DO $$
     DECLARE 
      candidate_count integer;
     BEGIN
      SELECT COUNT(*)
      INTO candidate_count
      FROM test_scores;
      
      ASSERT candidate_count > 0,   'Candidates not found, check the test_score table';
       END$$;

In this query, we have declared a variable “candidate_count”, this variable is used to keep the count of the number of candidates. In the ASSERT statement, we are basically giving the condition that if candidate_count >0 then it would return nothing but if this condition becomes false, it will return the message _“Candidates not found, check the test_score table”_. In this particular case, we have many candidates on the table. So, the condition becomes true therefore the ASSERT statement returns nothing.

  
How will an ASSERT statement behave if the same query puts some different condition that becomes false? Let's see what will this case return.
    
    
    DO $$
     DECLARE 
      candidate_count integer;
     BEGIN
      SELECT COUNT(*)
      INTO candidate_count
      FROM test_scores;
      
      ASSERT candidate_count > 20, 'Candidates are less than 20';
     END$$;

The table contains only 11 candidates so the condition will become false, in this case, the message, passed in the form of a string, has to be displayed.

  
What do you think will happen if we do not pass a message in case of a false condition?

  
As expected, it gave an assertion failed error. The same happens if the message is null.

##  **Conclusion**

PostgreSQL provides an **ASSERT** statement for inserting debugging checks for the program. The ASSERT statement provides a condition to the program. If the codes satisfy that condition, the program is executed normally. However, if the program does not satisfy the condition and returns false, the ASSERT statement will raise an error with the message provided by the user. If no message is provided, it will show an "assertion failed" error, by default.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-assert-statement-in-postgresql/)

---

# How to Use Dollar-Quoted String Constants

> To insert a single quote in the text, we will have to double it up. This makes the text very complex and unreadable in case the string contains many single quo…

Dollar-quoted string constants are used to make the string constants more readable and understandable. We usually need to have a single quote in the string constants but in order to write them we will have to double them up. This makes the queries a lot more messy. To avoid this mess, we do dollar quoting.

This write-up helps us understand the use of dollar-quoted string constants in PostgreSQL.

##  **How to Use Dollar-Quoted String Constants Postgres?**

Sometimes we need to write string constants in PostgreSQL. We write these string constants like this:
    
    
    SELECT 'Hello I am Peter';

The above query returns a string constant like this:

  
These string constants may include single quotes. For example; if we need to write: “Hello, I’m Peter”. Then the query will be written as:
    
    
    SELECT 'Hello, I''m Peter';

The below snippet shows the resultant output for the given query:

  
In the above query, it is clear that if we need to insert a single quote in the text, we will have to double it up. Well, this was a simple case. The problem arises when a string contains many single quotes. Under this scenario, doubling the quotes makes it very difficult to read as well as maintain the query.

###  **Dollar-Quoted String Constants**

In PostgreSQL version 8.0 and further, dollar-quoting was introduced to make string constants more understandable and readable.

The above example will become:
    
    
    SELECT $$Hello, I'm Peter$$;

We can clearly see that the string constant becomes more readable. Output for the above query is:

  
Alternatively, we can write the generic query as:
    
    
    SELECT $tag$Hello, I'am Peter$tag$;

The output for this is the same as above.

Remember the **_tag_** in the above query is completely optional, it can contain zero or many characters like;
    
    
    SELECT $myText$Hello, I'am Peter$myText$;

This will again result in the same output.  


###  **Uses of Dollar-Quoted String Constants**

In Postgres, dollar-quoted string constants have various practical use cases and benefits:  


 **String Constants More Readable**

This technique reduces the use of doubling the single quotes wherever we need the single quote in string constants. This makes them more clear and more readable.
    
    
    SELECT '''USA'', ''CANADA'', ''CHINA'', ''ENGLAND'', ''RUSSIA''';

As in the above example, it is tiring to add these quotes again and again, and also needs to add another task to insert a correct count of quotes to make the code error-free. In short, the code reduces clarity and seems unreadable.  


 **Easy to Define Postgres Functions**

A body of Postgres function is usually defined in single quotes like;
    
    
    DO
     'declare
      student_count integer;
       begin
      select count(*) into student_count
      from Students;
      raise notice ''The number of Students: %'', student_count;
     End;';

  
This double-dollar quoting notation is easier to work with, especially in the case when quotes are used in functions. The program code becomes more readable and clear. Like in the above example there is a line:
    
    
    raise notice ''The number of Students: %'', student_count;

  
Now if we use double dollar quote representation the code becomes:
    
    
    do
       $$
     declare
      student_count integer;
     begin
      select count(*) into student_count
      from Students;
      raise notice 'The number of Students: %', student_count;
     end;
       $$

##  **Conclusion**

To insert a single quote in the text, we will have to double it up. This makes the text very complex and unreadable in case the string contains many single quotes. So the dollar-quoting came to the rescue. Dollar-quoting was introduced to make string constants more understandable, readable, and easy to manage.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-dollar-quoted-string-constants/)

---

# PostgreSQL Data Definition Language (DDL)

> The DDL(Data Definition Language) is used for creating and modifying the object structures in the database using some commands and statements.

The term **DDL** stands for **Data Definition Language**. The DDL is used for creating and modifying the structure of the objects/entities in the database using some commands and statements. These objects can include aliases, tables, sequences, tables, etc. These statements include **CREATE** , **ALTER** , **DROP** , and **TRUNCATE**.

This article will discuss the data definition commands along with suitable examples.

##  **PostgreSQL Data Definition Language (DDL)**

In PostgreSQL, the DDL commands allow us to define a database. In this write-up, we will discuss the following DDL commands:

\- Postgres CREATE Statement

\- Postgres ALTER Statement

\- Postgres TRUNCATE Statement

\- Postgres DROP Statement

Let’s get started with the CREATE Statement.

###  **CREATE Statement in Postgres**

 **CREATE** statement is used to create/form entities like databases, schema, tables, triggers, indexes, etc. The basic syntax for creating a schema is as follows:
    
    
    CREATE SCHEMA Schema_Name;

Let’s consider that we want to create a table. For this scenario, the syntax will look like this:
    
    
    CREATE TABLE <tab_name>
       (col_name_1 datatype,
       col_name_2 datatype,
       .
       .
       col_name_n datatype
       );

 **Example: Creating a New Postgres Table**

Now if we want to make a table named “students_info”, we will have to specify the name of the table, its columns, and their data types. Following would be the simple query written for this case.
    
    
    CREATE TABLE Students_Info
       (
       StudentID int,
       StudentName varchar(255),
       Address varchar(255),
       City varchar(255)
       );
    SELECT * FROM Student_Info;

This would simply create a table named **Students_Info** with columns **StudentId** , **StudentName** , **Address** , and **City** :

### 

###  **ALTER Statement in Postgres**

The **ALTER** statement is used to modify, add, or delete some already existing constraints or columns from the database table. We can add a column, drop a column, or can also change the data type of a column using the ALTER statement. The following code illustrates the syntax of how an ALTER statement is used to add a column in a Postgres tablet:
    
    
    ALTER TABLE Tab_name ADD col_name datatype;

 **Example 1: Adding a New Column to a Postgres Table**

Now if we want to add a column for the ages of the students, we will write the following query;
    
    
    ALTER TABLE students_info ADD studentAge int;

This has added another column in the table named “studentAge” with initially all the values as null. This is because we have not inserted any value in that column:

 **Example 2: Rename a Column of a Postgres Table**

Another clause named “RENAME” can be used with the ALTER statement to change the name of the table. The syntax is given below:
    
    
    ALTER TABLE   table_name1 RENAME to   new_table_name1;

For example, if we want to rename our table “students_info” to “students”, we will write the following query:
    
    
    ALTER TABLE students_info RENAME to Students;

It would give the following output.

Now if we run the following query, it would return an error that “ERROR: relation "students_info" does not exist”.
    
    
    SELECT * FROM students_info

It means that this table has been renamed to “students”. For assurance, let’s run the query for the table “students”.
    
    
    SELECT * from Students;

Following is the output table:

This means that for sure this table is renamed from "students_info" to "Students".

###  **TRUNCATE Statement in Postgres**

The TRUNCATE statement basically deletes all the data/rows from the database table but it does not delete the table (structure). The basic syntax for the query is
    
    
    TRUNCATE table table_name;

Let's suppose we want to delete all the data from the table, maybe because the data is outdated and is of no use, we will simply use the TRUNCATE statement. Following will be the syntax if we want to truncate the above-considered table:
    
    
    TRUNCATE table students_info;

This will simply delete all the data from the table as shown below.

Now if we want to get the table, we will have to run the select query:

We can clearly see that all the data from the table has been truncated.

###  **DROP Statement in Postgres**

As in the case of truncate, the whole data in the table was deleted but the existence of the table was still there. But if we want to delete the entire table what should we do? For this specific purpose, we use the DROP statement. The general syntax for the DROP statement is:
    
    
    DROP table students_info;

The output for the given query is:

Now if we want to get the resulting table after this query, we will have to run the select query:

The error proves that the “students_info” table has been successfully dropped.

##  **Conclusion**

The DDL(Data Definition Language) is used for creating and modifying the object structures in the database using some commands and statements. These statements include; **CREATE, ALTER, DROP,** and **TRUNCATE**. We have covered them with their basic syntax and practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-data-definition-language-ddl/)

---

# How to Get the First Row Per Group in PostgreSQL

> To get the first row per group in Postgres, divide the data into groups, assign a number to each row, sort the data in specific order, and retrieve the top row…

Getting the first row for each group can be of great use. This data can be used for many important purposes, especially for data analysis. For example, if we have a database table storing all the test scores for the candidates who appeared in the entrance test, by getting the first row for each group based on gender we can get the top scorer in both groups i.e. male and female.

This write-up will demonstrate the complete process of getting the first row per group in Postgres.

##  **How to Get the First Row Per Group in PostgreSQL**

To get the first row per group, we will have to divide the data into groups or partitions. That partition can be based on anything we want our categories to be.

Let’s find out how to get the frost row for every group using suitable examples.

 **Example: Getting First Row Per Group**

Let’s consider a database table, named “ **test_scores** ”, containing the data of the candidates who gave an entrance test for a university along with the scores they obtained on that test:

  
Now if we want to know who got the first position in the category of male and female we need to get the first rows of both the groups. Right? Some things are generally clear:

\- We will have to assign row numbers to the rows.

\- We will have to make partitions.

And if we see it critically, the flow will be, we will have to separate the groups based on gender(partitioning) and assign row numbers to both groups separately, in order to get the first rows from both categories.

So to get the first row per group, we will have to write the following queries:
    
    
    SELECT *,
      row_number() OVER (PARTITION BY candidate_gender ORDER BY candidate_score DESC) 
      AS Position
      FROM test_scores;

In the above query we have used:

\- **SELECT** query to select/fetch data from the table “test_score”.

\- **row_number()** function, which assigns row numbers to every row of the table.

\- **PARTITION BY** divides the table data into groups. The **PARTITION BY** clause is followed by a column name on the base of which we want to partition the data.

\- **ORDER BY** arranges the column, specify the name after it, in an order specified i.e. DESC means in descending order.

\- The query till now, orders the data in descending order, partitions it based on gender i.e. Male and female, and then gives a row number to each row in both partitions, and this row number is stored in another column named as “Position”.

 **Output**

We can see that the above table is now partitioned into 2 gender categories, and the row number has been assigned to both of the partitions separately:

  
Since we only need the first row from both categories, we will have to modify the above code slightly like this:
    
    
    SELECT * FROM(SELECT *,
      row_number() OVER (PARTITION BY candidate_gender ORDER BY candidate_score DESC) 
      AS Position
      FROM test_scores)TEMP where Position = 1;

Here we have basically specified that we need the data of row number/position 1. So the above query will give the first row per group:

 **  
Note** : To get the last row per group, the above query will be the same. The only difference will be the ordering of the data i.e. we will order the data in ascending order using ASC instead of DESC. By doing so we will get the last person on the top.

###  **Conclusion**

Getting specific data from the database tables is always of great use. This data can be used for analysis purposes. We can get the first row per group by arranging them in our preferred order, dividing them into partitions, giving each row a row number, and then retrieving the top row.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-first-row-per-group-in-postgresql/)

---

# PostgreSQL Data Manipulation Language (DML)

> Data Manipulation Language, which is basically used to modify the data in a database. The most commonly used commands are INSERT, UPDATE, and DELETE.

DML stands for **Data Manipulation Language** , which is basically used to do modifications to the database data. This modification includes adding, retrieving, and manipulating data. To do that, different commands/statements are used in PostgreSQL, such as **INSERT** , **UPDATE** , and **DELETE**.

Before moving on to the details of DML, let's find out what actually DML is.

 **PostgreSQL Data Manipulation Language (DML)**

In PostgreSQL, the DML commands allow us to modify the database’s data. This article is based on the following DML commands:

\- INSERT Command

\- UPDATE Command

\- DELETE Command

Let’s discuss them one by one.

###  **INSERT Command in PostgreSQL**

The insert command in PostgreSQL is used to add or insert rows/data into the table. The command used for inserting is **INSERT INTO**. Below is the basic syntax of insert statement:
    
    
    INSERT INTO tab_name(col1, col2, …)
    VALUES (val1, val2, …);

Now let’s suppose we want to make a “students_info” table and insert data in it. The following would be the query written for the particular example:

 **Create a Table First:**
    
    
    CREATE TABLE   Students_Info
       (
       StudentID int,
       StudentName varchar(255),
       Address varchar(255),
       City varchar(255)
       );

 **Insert Data Into it:**
    
    
    INSERT INTO students_info(studentid, studentname ,address,city)
    VALUES ( 01,'John','13th Street. 47 W 13th St' , 'New York')
    RETURNING *;

In the above syntax:

● Firstly, you have to write the name of the table(students_Info in this case) after the INSERT INTO statement, followed by a list of comma-separated column names.

● Secondly, add a comma-separated list of values, in the same order as you have specified the columns, with the VALUES statement.

This will add a row for all the data of student John provided in the values list.

  
For inserting multiple rows we will have to write the query as:
    
    
    INSERT INTO students_info(studentid, studentname ,address,city)
    VALUES ( 01,'John','13th Street. 47 W 13th St' , 'New York'),
    ( 02,'Alex','24th Street. 32 E 24th St' , 'San Diego'),
    ( 03,'Peter','6th Street. 23 W 6th St' , 'San Francisco')
    RETURNING *;

The above code will create the following table in the database:

 **  
NOTE:** A **RETURNING** clause is sometimes also used with the Insert command, but this is completely optional. “ **RETURNING *”** is used to return the whole inserted row.

###  **UPDATE Command in PostgreSQL**

The UPDATE command in PostgreSQL modifies or updates the pre-existing data in a database. The command used for updating is **UPDATE**. To update the value of any pre-existing row, the following would be the required information:

  1. The name of the table and the column that needs to be updated.
  2. The updated value of the column.
  3. And the condition where the update would take place.



Below is the basic syntax of the update statement:
    
    
    UPDATE tab_name
    SET col1 = updated_value,
    col2 = updated_value,
    WHERE cond;

Now considering the case if we have written the wrong city for the student John, in the same example we discussed above, we would want to change his city to Chicago. The following would be the query written for this case:

UPDATE students_info

SET city = 'Chicago'

WHERE studentid = 1

RETURNING *;

This will update the row of “City” from a pre-existing value to Chicago where the roll number of the student is 1.

  
Note that the WHERE clause is totally optional. If this is not present, then all the rows of the table will be updated.

###  **DELETE Command in PostgreSQL**

Till now we have learned to add and update values in the table but what if we want to delete data from a table? So here comes the use of the **DELETE** clause. We can delete row/rows from a table that are no longer of any use to us by this statement. The DELETE FROM keyword is used to delete the data. To delete a row we need to specify two things:

  1. Specify the name of the table (after the keyword) from which that data needs to be deleted.
  2. Specify the condition after the WHERE clause to show which rows from the table to delete.


    
    
    DELETE FROM tab_name
    WHERE cond;

In the same example discussed above, if the student Alex withdraws his admission from the school, we’ll want to remove his record from the students' table. In this case, the DELETE FROM query is used. The query structure for this particular example will be:
    
    
    DELETE FROM students_info
    WHERE studentid = 2
    RETURNING *;

In the above example, the row in the students' table that has roll number 2 will be deleted. Remember that here the WHERE clause is completely optional and if it is not written, the statement will delete all the data/rows in the table.

Another important thing that is to be noticed here is that if we use the optional “RETURNING” clause with the DELETE statement it will always return the row/rows that is/are deleted. So following is the output for the above-mentioned query:

 **Conclusion**

The Data Manipulation Language is very useful at times when we want to modify data in the database. These modifications may include the **INSERT** , the **UPDATE,** and the **DELETE** statements. INSERT statement inserts data into the table, UPDATE statement updates the old values in a table with the updated ones and DELETE statement deletes the data that is no longer of our use.

---
[View this page online](https://www.commandprompt.com/education/postgresql-data-manipulation-language-dml/)

---

# Postgresql: INSERT INTO ... (SELECT * ...)

> INSERT INTO SELECT is a very useful statement in PostgreSQL which allows us to select or copy some data from one table and insert it into another.

PostgreSQL offers many useful statements that are used to deal with the database tables effectively. One of the most crucial and frequently used statements is **INSERT INTO SELECT**. It performs two operations in one go, i.e., “fetch the data from one table” and insert the fetched data into the targeted table. Let’s have a look at how this statement works in PostgreSQL.

##  **PostgreSQL: INSERT INTO ... (SELECT * ...)**

The INSERT INTO SELECT command selects some specified data from one table and inserts/pastes it into another one. Now there are two **importan** t things that are to be noticed:

  * First, the table/target table where the columns are being copied remains unchanged.
  * Second, the datatype of columns of both the source and target tables should be the same.



We can use the following syntax of the INSERT INTO SELECT statement to select and insert the data from one table to another:
    
    
    INSERT INTO tab_2
    SELECT * FROM tab_1
    WHERE cond;

The name of the table in which we want to insert/paste the data is written after the **INSERT INTO** command. **SELECT** statement is followed by the name of the table from which we want to copy/select data. We can also use the optional **WHERE** clause followed by the condition to copy/insert the data based on a specified condition.

If we want to select/copy some columns (partial data) from a table and insert them into another, the above syntax will become:
    
    
    INSERT INTO table_2 (col1, col2, col3, ...)
    SELECT col1, col2, col3, ...
    FROM table_1
    WHERE cond;

  * Table_2 is the table where the data is being copied means the target table.
  * Table_1 is the source table from where the data is being copied.



 **Example 1: Understanding INSERT INTO SELECT**

Let’s discuss the concept with the help of an example so that it becomes more clear:

 **Step 1: Create Table 1 and Insert Some Data Into it**

Create a table named students_info with columns StudentId, StudentName, Address, and City.
    
    
    CREATE TABLE Students_Info
    (
    StudentID int,
    StudentName varchar(255),
    Address varchar(255),
    City varchar(255)
    );

A new table will be created like this:

Now insert data in the newly created “Students_Info” table:
    
    
    INSERT INTO Students_info(studentid, studentname ,address,city)
    VALUES ( 01,'John','13th Street. 47 W 13th St' , 'New York'),
     ( 02,'Alex','24th Street. 32 E 24th St' , 'San Diego'),
     ( 03,'Peter','6th Street. 23 W 6th St' , 'San Francisco')
    RETURNING *;

The data is successfully inserted in the table like this:

 **Step 2: Create Second Table**

Now create another table named “attendance_list”. The attendance list will only contain two columns i.e. studentid and studentname:
    
    
    CREATE TABLE attendence_list
    (
    StudentID int,
    StudentName int
    );

A table will be created:

 **Step 3: Insert Data From Students_info to Attendence_list**

Now we will use the INSERT INTO SELECT statement to select data i.e. the “studentId column” and the “studentName column” from the students_info table to the attendence_list table. The data of rows that are specified is being copied and inserted:
    
    
    INSERT INTO attendence_list(StudentId,StudentName)
    SELECT StudentId,StudentName
    FROM students_info;
    SELECT * FROM attendence_list;

The output will show that the data from table students_info is copied to attendence_list for the two columns i.e. studentId and studentName. Below attached is the screenshot of the query:

 **Example 2: INSERT INTO SELECT Statement With WHERE Clause**

Now if we want to copy only data of those students who have studentId >2 (maybe to place them in another section), we will make use of the WHERE clause as follows:
    
    
    INSERT INTO attendence_list(StudentId,StudentName)
    SELECT StudentId,StudentName FROM students_info
    WHERE students_info.studentid>2;
    
    SELECT * FROM attendence_list;

The output table would return all the data or students having studentsId >2, copied for the Students_info table. The output will look like this:

 **Example 3: Incompatible Column Type Error**

One thing is to take notice that the datatypes of columns of both tables must be the same. Let’s suppose I change the data type of studentName from varchar to int(which is not practically possible but just to illustrate this concept let's assume this) in the attendent_list table, the INSERT INTO SELECT will not work. Instead, it will give an error. Now let's do it practically:
    
    
    CREATE TABLE attendence_list
    (
    StudentID int,
    StudentName int
    )
    SELECT * FROM attendence_list;

A table is created as it is normally created:

Now try to copy data from students_info to attendence_list, let's see what would happen:
    
    
    INSERT INTO attendence_list(StudentId,StudentName)
    SELECT StudentId,StudentName FROM students_info;
    
    SELECT * FROM attendence_list;

The output for the above query is:

As expected, this query gave us an error so we need to have the same datatype of columns in both the tables.

##  **Conclusion**

INSERT INTO SELECT is a very useful statement in PostgreSQL which allows us to select or copy some data from one table and insert it into another. This technique saves time from manually inserting all the values again. So if we have an already existing table, we can copy the data from that table to another given that the data type of columns of both the tables i.e. source and the target are the same.

---
[View this page online](https://www.commandprompt.com/education/postgresql-insert-into-select/)

---

# RANK() versus DENSE_RANK() in Postgres: What is the Difference?

> Rank() and DENSE_RANK() are the functions used to rank the data. Both functions have some functionality in common and some differences are also there.

PostgreSQL provides built-in functions that aid in assigning rankings to table rows. Among these functions, the most commonly and frequently used functions are **RANK()** and **DENSE_RANK()**. These functions assign sequential ranks, with both functions assigning an equal rank to identical data elements. The difference in approach comes after assigning the same ranks to the elements.

Let's discuss the details of both functions and see how they are different.  


 **RANK() Vs DENSE_RANK() in Postgres: What is the Difference?**

RANK() and DENSE_RANK() functions are ranking functions. They both rank the data according to order and assign the same rank to the same elements in the table. Let's see how they both particularly work.

 **RANK()**

The RANK() function allocates those elements with the same rank, which are identical. The rank of the next element will be the current value of rank plus the number of times the previous element repeated.

The syntax for the RANK() function is illustrated below:
    
    
    RANK() OVER ( [PARTITION BY partition_expression, ... ] ORDER BY sort_expression [ASC | DESC], ... )

 **DENSE_RANK()**

DENSE_RANK() function gives the same rank to those elements which are the same. The rank of the next element will be the next consecutive value to the previous rank.

The basic syntax of DENSE_RANK() function is:
    
    
    DENSE_RANK() OVER ([PARTITION BY partition_expression, ... ] ORDER BY sort_expression [ASC | DESC], ... )

Let’s discuss the examples so that the syntax and the differences in both are much clearer.  


 **Example 1: RANK() Vs DENSE_RANK() in Postgres**

Consider the table showing the scores of the candidates appearing in an entry test of a university. The table contains columns for id, name, gender, and score.

  
Now we will apply the RANK() and DENSE_RANK() functions to the above-given table. The query will be written as follows:
    
    
    SELECT Candidate_ID, Candidate_Name, candidate_Score,
      RANK() OVER(ORDER BY candidate_Score DESC) AS _Rank,
      DENSE_RANK() OVER(ORDER BY candidate_Score DESC) AS _denseRank
     FROM test_scores;

In the above code:

● The SELECT statement is followed by the column names that are to be selected from the _test_scores_ table.

● ORDER BY clause in both cases is necessary in order to sort our data. This sorting can be in ascending or descending order. We can decide the type of sorting as per our use case requirements. Here in our case, this order needs to be in descending order so that the candidate with the highest marks gets the first rank and so on. Here we ordered the column _candidate_Score_ in descending order.

● Lastly, we have applied the RANK() and DENSE_RANK() functions on the ordered data and stored the rank in the columns: _Rank and _denseRank in the table respectively.

The output of the above query is:

  
In the above output, we can clearly see the difference between the two functions. Let's analyze both one by one.

In the case of the **RANK() function** , every(same) element is assigned the same rank. But the pattern to be noticed is the very next rank after the same rank assignment. When rank gives the same rank to one or many elements the next element’s rank is calculated as: The current value of rank plus number of times the previous element repeated.

For example in the table given above, the score 89 is a single element so the rank assigned to it is 1. The next value is 82, all the 82’s will be assigned rank 2. Here notice the 82 is repeated 3 times. So the rank of the next element will be calculated as:

  
The rank of the next element, that is, 75 is 5. And 75 is again repeated 2 times so the rank of the next element 72 is 7(i.e. 5+2). 72 occurs once so the rank for the next element (69) is 8. 69 is again duplicated so the rank for both of the 69s is 8 and the rank for the next element is 10(i.e. 8+2). The last two elements occur once so both will be assigned rank 10 and 11 respectively.

In the case of the **DENSE_RANK()** function, every (same) element is assigned the same rank. The rank assigned to the next element will be the next consecutive value to the rank. This is simple. Just analyze the example. The dense rank for 89 will be 1. The dense rank for the next element(82) will be 2. 82 occurs 3 times so all 82s will be given rank 2 but this thing will not affect the rank of the next element. The rank for the next element will still be the consecutive rank i.e. 3. And this way the dense rank works.

 **Example 2: Comparing RANK() and DENSE_RANK() Functions With PARTITION BY in Postgres**

Another important thing that we can do is rank the data by partitioning it under some conditions. For example; in the above-considered example, we can partition the data based on gender and then rank it. This thing can be done if we use the **PARTITION BY** clause with these ranking functions. This clause is completely optional as we have seen in the above example, however, if the data is not partitioned using the PARTITIONED BY clause these queries will consider the whole data as one partition. Let's see how it works.

The above query is written as:
    
    
    SELECT Candidate_ID, Candidate_Name,Candidate_Gender, candidate_Score,
      RANK() OVER(
       PARTITION BY Candidate_Gender
       ORDER BY candidate_Score DESC) AS _Rank,
      DENSE_RANK() OVER(
       PARTITION BY Candidate_Gender
       ORDER BY candidate_Score DESC) AS _denseRank
     FROM test_scores;

You will see the clear partitioning based on gender and will observe the ranking patterns in the output of the above query:

  
The ranking functions have ranked the data according to the partitions formed based on gender.

 **Conclusion** :

Rank() and DENSE_RANK() are the functions used to rank the data. Both functions have some functionality in common and some differences are also there. We can use the PARTITION BY clause with these functions and this clause is a completely optional clause. It partitions the data into parts on the basis of some attribute and then ranks these segments using ranking functions according to their respective partitions. If the PARTITION BY clause is not present, these functions consider the data as one partition by default.

---
[View this page online](https://www.commandprompt.com/education/rank-versus-dense_rank-in-postgres-what-is-the-difference/)

---

# Array Operators in PostgreSQL

> Array operators are used to perform different operations on arrays. These operators are used for comparison, containment, overlapping, and concatenation.

There are many operators that can be applied to arrays. These operators are used for comparison, containment, overlapping, and concatenation. All of these operations have some unique functionality. 

This article covers the following operators:

● The comparison operators

● The containment operators

● The overlap operator

● The concatenation operator.

##  **Array Operators in PostgreSQL**

Each array operator serves a unique purpose in the program. Let’s dive into the details of each operator.

###  **The Comparison Operators**

These operators are used to draw a comparison between two arrays. These operators are of two types based on the comparison, which are, equality and ordering.

#### ● **Equality Operator**

There are two equality operators, “equal to” and “not equal to”. These equality operators perform element-by-element comparisons and return a **boolean** value, that can either be true or false.

In the case of the “ **equal to”** operator:

● If the query returns “ **t** ” which means **true** after the operator is executed on it, it means that the elements of both the arrays are same.

● If the query returns “ **f** ” which means **false** after the operator is executed on it, it means that the elements of both arrays are not the same.

The case is the opposite for “ **not equal to** ”:

● If the query returns “ **t** ” which means **true** after the operator is executed on it, it means that the elements of both arrays are not the same.

● If the query returns “ **f** ” which means **false** after the operator is executed on it, it means that the elements of both arrays are the same.

Now let’s move towards an example so that the concept is more clear:
    
    
    SELECT ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] = ARRAY['Katherine', 'Alex'] As is_equal;

What do you think will the query return? Let's see.

The output is **“f” which** means false. As we have discussed, the equality operators compare array elements, element by element. So if we see elements of both the arrays are not equal i.e. “Williams” is not equal to “Katherine”.

Now if we place the “not equal to” operator between them. It should return “t” because both arrays are not equal.
    
    
    SELECT ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] <> ARRAY['Katherine', 'Alex'] As not_equal;

The output is “ **t** ”.

Which means both arrays are not equal to each other.

#### ● **Ordering Operator**

These operators include less than, greater than, less than equal to, and greater than equal to. Following are the queries and their outputs showing how these operators work.
    
    
    SELECT ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] > ARRAY['Katherine', 'Alex'] As greater_than,
     ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] < ARRAY['Katherine', 'Alex'] As less_than,
     ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] >= ARRAY['Katherine', 'Alex'] As   greaterthan_equalto,
     ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] <= ARRAY['Katherine', 'Alex'] As   lessthan_equalto;

###  **The Containment Operators**

The containment operators check whether one array contains elements of another or not. These operators include **“@ >”** and **“ <@”** operators. The “@>” operator checks whether the right array is contained in the left array while the “<@” operator checks whether the left array contains the right one. If they do the queries will return **“t”**.

Let's have a look at an example of the containment operator so that we have a better understanding.
    
    
    SELECT ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] @> ARRAY['Katherine', 'Alex'] As l_contains_r;

The query above returns the following output:

And it is clear that the elements of the array on the right side are contained by the array on the left side which is why the query returned true.

Now if we add the “ **< @”** operator between both arrays it should return false because the right array does not contain all the elements of the left array.
    
    
    SELECT ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] <@ ARRAY['Katherine', 'Alex'] As r_contains_l;

Executing the above query gives false:

This was all about the containment operators.

###  **The Overlap Operator**

The overlap operator is used to find out if both the arrays, operated under this operator, have elements in common or not. In Postgres, the overlap operator is denoted as a **“ &&”** sign.

Let’s execute the same example for the overlap operator.
    
    
    SELECT ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] && ARRAY['Katherine', 'Alex'] As overlap;

So we can clearly see that these arrays have elements in common so the query should return **“t”**.

This was all about the overlap operator. Next, we will move toward the concatenation operator.

###  **The Concatenation Operator**

The concatenation operator is denoted by **”||”.** Concatenation links and joins both arrays together. Other than array-to-array concatenation, this operator provides element-to-array and array-to-element concatenation.

We will look at the examples one by one
    
    
    SELECT ARRAY['Williams', 'Alex', 'Peter', 'Katherine'] || ARRAY['Katherine', 'Alex'] As concat;

This is an example of array-to-array concatenation. Let’s see its output:

The resulting array is a long array that is made by joining the elements of both arrays.

Now consider another case for the array-to-element and element-to-array concatenation.
    
    
    SELECT ARRAY[1,2,3] || 4 As concat;

The above query will result in the following output:

Now we will write a query for the element-to-array concatenation:
    
    
    SELECT 4 || ARRAY[1,2,3] As concat;

This will append the element at the start of the array as follows:

So this is how the concatenation operator works.

##  **Conclusion**

We have seen the array operators above in detail. Array operators perform different operations on arrays. These operators are used for comparison, containment, overlapping, and concatenation. The arrays can operate equality, ordering, containment, overlap, and concatenation operators on them.

---
[View this page online](https://www.commandprompt.com/education/array-operators-in-postgresql/)

---

# How to Find Factorial of a Number in PostgreSQL

> To find the factorial of a number in PostgreSQL, we use the FACTORIAL() function that takes a number as an input and returns the value of its factorial.

In Postgres, the factorial of a number can be found by using a built-in function that is **FACTORIAL()**. A number is passed into the function, the FACTORIAL() function will return the factorial of that number. In the previous versions of PostgreSQL, the factorial can also be found using the **“!”** and **“!!”** operators. But these operators are now not supported in PostgreSQL 14 and onwards. Let’s find out the method to find the factorial of a number in PostgreSQL.

##  **How to Find Factorial of a Number in PostgreSQL**

To find the factorial of the number in PostgreSQL, we use the **FACTORIAL()** function that takes a number as an input and returns the value of its factorial. Here is a simple query where we are returning the factorial value of 8:
    
    
    SELECT FACTORIAL(8);

The output of the query will give the factorial value of 8 which is 40320.

Let's see how it works with a table column. Firstly, we will create a table using the CREATE TABLE command and then we will insert some values in it. The query for this task will be:
    
    
    CREATE TABLE factorial_example(number int);
     INSERT INTO factorial_example(number)
     VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

This query will create the table and insert values in it. This will result in the following table:

Now let’s write the query for finding the factorial and insert the returned value of the FACTORIAL() function in another column. The query will be:
    
    
    SELECT *, FACTORIAL(number) AS Factorial_of_number FROM factorial_example;

We have passed a column named “number” into the FACTORIAL() function. The query will return the table with an extended row of respective factorials of the numbers:

So, we can see a column “factorial_of_number” returning the factorials. This is the method to find the factorial of any number in PostgreSQL.

###  **Conclusion**

To find the factorial of a number in Postgresql, the FACTORIAL() function is used. This function takes the number as a parameter and returns the value of its factorial. Before Postgres 14, some operators like ”!” and “!!” were also used but these operators are now not supported by current versions of Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-factorial-of-a-number-in-postgresql/)

---

# ENUM_RANGE() Function in PostgreSQL

> ENUM_RANGE() is a built-in function in Postgres to manipulate the data having Enum data type. This function returns an array containing all the enumerators for…

PostgreSQL provides many built-in functions to manipulate the data having Enum data type. These functions include **ENUM_FIRST()** , **ENUM_LAST()** , and **ENUM_RANGE()**. Each of the functions serves a specific purpose, such as retrieving the first enumerator, last enumerator, etc.

This blog post will explain the working of the ENUM_RANGE() function in PostgreSQL.

##  **ENUM Functions in PostgreSQL**

Postgres offers the following functions to deal with the enumerated data:

● **ENUM_FIRST()** \- This function returns the first enumerator of an enum type.

● **ENUM_LAST()** \- This function gives the last enumerator of an enum type.

● **ENUM_RANGE()** \- This function returns an array containing all the enumerators for the enum type in the same order as defined.

##  **What Does the ENUM_RANGE() Function Do in PostgreSQL?**

 **ENUM_RANGE()** is a built-in function in PostgreSQL that returns an array containing all the enumerators for the enum type in the same order as defined. The basic syntax for ENUM_RANGE() is given below:

enum_range(en_value ENUM);

Or if we write the detailed syntax for the function, it will be:

enum_range(en_range_start ENUM, en_range_end ENUM);

These **parameters** in the ENUM_RANGE() functions are mandatory to pass. Let's discuss the parameters one by one:

● **en_value** \- It is the enumeration value that is usually null.

● **en_range_start** \- It is the starting value of the enumeration range.

● **en_range_end** \- It is the ending/last value of the enumeration range.

 **Note** : Here one thing is to notice that the **en_range_start** and **en_range_end** both should have the same enum type. And they can have a NULL value.

###  **What Does ENUM_RANGE() Function Return?**

The ENUM_RANGE() function can return all the values or can also return a range of values in an enum.

If only one parameter is passed into the ENUM_RANGE() function, as written in the first syntax, it will give all the enumeration values in the particular enum type.

In the case of two parameters, these two parameters i.e. **en_range_start** and **en_range_end** will determine the range of the returned values. If the **en_range_start** is NULL then the range of the returning value will automatically be considered to start from the first enumeration value. If the **en_range_end** is NULL then the range of the returning value will automatically be considered till the end of the enumeration values. If both are NULL all the enumeration values will be returned.

Let’s see these cases one by one using an example so that they are more clear.

 **Example:**

First of all, we need to create an enum type. Let’s consider it the name of the planets in the solar system. We will name the Enum as Solar_System:
    
    
    CREATE TYPE Solar_System AS ENUM (
      'Mercury',
      'Venus',
      'Earth',
      'Mars',
      'Jupiter',
      'Saturn',
      'Uranus',
      'Neptune',
      'Pluto'
       );

By running the above query we will see that the Enum type has been created:

Let's consider the cases for the different variations in the syntax of the enums and their values to evaluate the output.

###  **Case 1: One Parameter - NULL**

Now let's consider the first case, the case of passing only one parameter in the function and that is set to be NULL. We will write the query as:
    
    
    SELECT enum_range(null::solar_system);

We can see that passing NULL as one parameter outputs the whole enumeration values.

###  **Case 2: One Parameter - Non-null**

Now if we pass a non-null value as a parameter.
    
    
    SELECT enum_range('Mercury'::solar_system),
      enum_range('Venus'::solar_system),
      enum_range('Earth'::solar_system),
      enum_range('Mars'::solar_system),
      enum_range('Jupiter'::solar_system),
      enum_range('Saturn'::solar_system),
      enum_range('Uranus'::solar_system),
      enum_range('Neptune'::solar_system),
      enum_range('Pluto'::solar_system);

It will return all the enumerations.

Each query will result in all the enumeration values. So, the names of 9 planets will be returned 8 times. Now let's move to the two-parameter cases.

###  **Case 3: Two parameters - Both Parameters are Non-null**

Let's consider the case where both the parameters i.e. **en_range_start** and **en_range_end** are non-null. It would give all the enum values between the range. Let's consider the following query:
    
    
    SELECT enum_range('Earth'::solar_system,'Uranus'::solar_system);

The output for this query is as expected. It has returned all the enum values between the value “Earth” and “Uranus”.

###  **Case 4: Two Parameter - “en_range_start” is NULL**

Now let's consider only the first parameter i.e. **en_range_start** is NULL. The query will be written as follows:
    
    
    SELECT enum_range(NULL::solar_system,'Saturn'::solar_system);

The output for the above query will be the enum values starting from the start till the ”Saturn”. The output looks like this:

###  **Case 5: Two Parameter - “en_range_end” is NULL**

Now let's consider only the first parameter i.e. **en_range_end** is NULL. The query will be written as follows:
    
    
    SELECT enum_range('Venus'::solar_system, NULL::solar_system);

The output for the above query will be the enum values starting from the ”Venus” till the end. The output looks like this:

###  **Case 6: Two parameters - Both Parameters are NULL**

Now let’s see what happens if both the parameters are NULL. Execute the below query to find out:
    
    
    SELECT enum_range(NULL::solar_system, NULL::solar_system);

We can clearly see that if both parameters are set to NULL, it will result in all the enumeration values:

So, this is all about the working of the ENUM_RANGE() in Postgres.

 **Conclusion**

ENUM_RANGE() is a built-in function in Postgres to manipulate the data having Enum data type. This function returns an array containing all the enumerators for the enum type in the same order as defined. In this blog, we have learned about the details of the parameters and return values with examples.

---
[View this page online](https://www.commandprompt.com/education/enum_range-function-in-postgresql/)

---

# What is an Enum in PostgreSQL?

> Enums are useful data types in Postgres that make it much easier to query, sort, and maintain the data and eventually improve data integrity.

Postgres enum (enumerated types) is an important data type used to store the predefined list of values in the columns. They make it easier to query and sort the data and implement good standards of data integrity. It is important to keep enums maintained and organized to avoid probable issues.

This write-up will explain what is an enum and how it works in PostgreSQL.

##  **What is an Enum in PostgreSQL?**

Enums are a very powerful feature of Postgresql that allows us to store some predefined set of values in the column. In order to use an enum in a table, we have to define it first and create the type of enum first. We can also define multiple values of the enum type to use it in the table. In Postgres, the **CREATE TYPE** command is used to create enums. The syntax to create an enum is illustrated below:
    
    
    CREATE TYPE nameOf_enumType (valueOf_enumType1, valueOf_enumType2, valueOf_enumType3, ..., valueOf_enumTypeN);

The CREATE TYPE is followed by the name of the enum type which is followed by the list of values of enum types.

 **Syntax**

Consider the example of project status, we can create an enum named “project_status” with the following syntax:
    
    
    CREATE TYPE project_status as enum('In progress', 'Completed', 'tested', 'Cancelled');

We can also **create a table using an enum type** using the following syntax:
    
    
    Create table nameOf_table (nameOf_column1 datatype, nameOf_column2 enumtype, nameOf_column3 datatype, ..., nameOf_columnN datatype);

To **insert** a value of the enum data type **c** olumn we use the given syntax:
    
    
    INSERT INTO nameOf_table (nameOf_column1, name0f_enumtype_column2, nameOf_column3, ...,   name0f_columnN) values (value1, valueOf_enumtype, value2, value3, ...., ValueN);

We will understand all of the syntaxes thoroughly through examples.

##  **How Does Postgres Enum Work?**

We will now discuss the working of enum in Postgres. The basic principle is that if we want to use an enum type, we will need to create it first. Without creating an enum type we won’t be able to use it in the table, instead, we will get an error.

Let’s consider the same example of project status to demonstrate the concept. Consider the following query:
    
    
    CREATE TABLE project_status(Name text, Status enumType, Managed_by text);

In the above query:

  * We have created a table where an enum type is used.
  * The name of the table is “ _project_status_ ”, which is followed by the list of column names with their datatypes.
  * The first and last column name is “ _name”_ and “ _managed_by”_ respectively and the datatype is text.
  * The second column named “ _status”_ has data type enumType. Now can you make a guess about what the output of this query should be? Will it return a table with 3 columns?



No, it won’t. The reason for this is, that whenever we need to use an enum type we have to create it first.

 **Output**

We can clearly see that we haven’t created the enum type. So now have a look at the output for the query:

We can see that the output is an error, clearly saying that we have not created enumType. Now let’s create an enum type with the following query:
    
    
    CREATE TYPE enumType AS ENUM ('In progress', 'Completed', 'tested', 'Cancelled');

The output ensures the successful creation of enumType:

Now if we again create the table as in the first query, what do you think, will it create the table? Or will it still return an error? The answer is “yes”, a table will be created as follows:

So, we can see that the table is created with the 3 columns “ _name”, “status”_ , and “ _managed_by”_ with their data types text, enumType, and text respectively.

We will now insert some values into the table”project_status”:
    
    
    INSERT INTO project_status VALUES ('Game app', 'In progress', 'John');
     INSERT INTO project_status VALUES ('Chat application', 'Completed', 'Williams');
     INSERT INTO project_status VALUES ('Online Food ordering App', 'tested', 'sarah');
     SELECT * FROM   project_status;

This is what the INSERT query returns:

##  **Enum Functions in PostgreSQL**

There are various methods and operations that we can apply on enums while querying data:

● **enum_first()** \- This function returns the first enumerator of an enum type.

● **enum_last()** \- This function gives the last enumerator of an enum type.

● **enum_range()** \- This function returns an array containing all the enumerators for the enum type in the same order as defined.

##  **Drawbacks of Enums in PostgreSQL**

Another important fact about enums is that enums are not flexible at all. They do not possess the ability to be altered once they are created. In short, the enums are fixed in nature. This fact can sometimes be a downside of an enum if we want to add or delete a value from the enum type.

Also, if we want the value of an enum data type to be changed, we will have to create a new enum type, shift the data to that newly created enum type, and then we will have to update/change the reference to that old enum type. Which is a quite hectic and time-consuming task

 **Conclusion**

Enums are useful data types in Postgres that make it much easier to query, sort, and maintain the data and eventually improve data integrity. We can use enum types anywhere after creating the enum type. Despite the fact that enums help in maintaining data integrity, we should also consider the fact that enums do have some limitations. so we always have to choose the data type that fulfills our needs completely.

---
[View this page online](https://www.commandprompt.com/education/what-is-an-enum-in-postgresql/)

---

# pglogical Rediscovered: A Fresh Approach to Logical Replication for Ultra-high Availability

> by Hari KiranAugust 22, 2023Data replication is an essential aspect of modern database management systems, ensuring data availability, fault tolerance, and sca…

**by Hari Kiran**

 **August 22, 2023**

Data replication is an essential aspect of modern database management systems, ensuring data availability, fault tolerance, and scalability. In the PostgreSQL world, a groundbreaking extension called Spock has emerged, transforming the way multi-active replication is handled. Spock, based on the pglogical logical replication tool, brings in a host of new features, including conflict resolution and avoidance, asynchronous replication, and more. In this blog post, we'll explore the powerful capabilities that Spock, part of the [pgEdge Platform](<https://www.pgedge.com/products/pgedge-platform>), offers and how it addresses the challenges faced by developers and database administrators. We'll also delve into Spock’s new architecture, multi-master capabilities, security features, and the promise of ultrahigh availability.

To set the groundwork, let's review a few of the top features of pglogical:

  *  **Logical Replication:** Allows selective replication of specific tables, enabling more flexible and efficient data synchronization between databases.
  *  **Bi-Directional Replication (BDR):** Unlike PSR, pglogical supports bi-directional replication, allowing changes to flow in both directions between source and target databases. However, without conflict resolution, this can be highly error-prone and questions the data integrity.
  *  **Replication Filtering:** This allows you to apply filtering rules to determine which data changes should be replicated, providing flexibility in data synchronization.
  *  **No Dependency on Physical Replication:** Operates independently of the physical replication mechanisms, allowing greater flexibility and compatibility with different PostgreSQL setups and versions.



## pgEdge Spock - A Leap Forward for pglogical and Multi-Active Replication for Postgres

 **Asynchronous Multi-Active Replication:**

One of the key features that set Spock apart is its support for asynchronous multi-active replication. Unlike pglogical, Spock allows multiple nodes to accept writes simultaneously. This feature boosts performance and enhances fault tolerance and scalability, providing an optimal solution for demanding environments.

 **Conflict-Free Delta-Apply Columns:**

Handling conflicts is a crucial aspect of multi-active replication. Spock introduces conflict-free delta-apply columns, an innovative mechanism that ensures smooth and efficient conflict resolution, and handles columns that hold numeric information. With this approach, Spock will resolve to the true numeric value, significantly reducing the chances of conflicts arising in the first place, and thereby enhancing data consistency and integrity. With this approach, Spock significantly reduces the chances of conflicts arising in the first place, thereby enhancing data consistency and integrity. As I eluded before, this is one of the features dearly missed in pglogical replication.

 **Advanced Conflict Resolution with Better Error Handling:**

In scenarios where conflicts do occur, Spock doesn't disappoint. It offers a robust conflict resolution mechanism that intelligently resolves conflicts without compromising data quality. Moreover, Spock comes with improved error handling, making it easier for developers and administrators to identify and address any issues that might arise during the replication process.

 **Enhanced Management, Monitoring Stats, and Integration:**

Managing a replicated database system can be challenging. Spock simplifies this process by providing enhanced management and monitoring statistics. 

For reference, the following Spock metadata tables are used for real-time conflict tracking by pgEdge Cloud, a fully managed cloud service running in multiple regions across AWS, Azure, or Google Cloud.

\- spock.conflict_tracker

\- spock.resolutions

\- spock.local_sync_status

\- spock.queue

\- spock.lag_tracker

One of our early-stage customers operates a highly scalable web platform with users from the US and EU regions. To provide a seamless experience, they have deployed the multi-active replication architecture using PostgreSQL with Spock. This allows them to distribute read and write operations across multiple database nodes, ensuring high availability and optimal performance. Additionally, it leverages Spock's advanced conflict resolution capabilities, so Spock intelligently identifies conflicting changes and applies sophisticated algorithms to resolve conflicts automatically.

These detailed insights into replication status and performance help their analysts make informed decisions, ensuring a smooth and efficient operation. Additionally, Spock seamlessly integrates with existing PostgreSQL tools like Prometheus, enhancing the overall management experience.

 **Performance, Stability, and Networking Stress Testing:**

Spock has been undergoing rigorous performance, stability, and networking stress testing, making it a robust and reliable solution for critical deployments. Spock boasts efficient streaming of large transactions and handling distributed transactions.

 **Replication of Partitioned Tables for Geo-Sharding Support:**

With the increasing demand for geographically distributed applications, Spock's support for the replication of partitioned tables comes as a game-changer. This feature enables developers to implement geo-sharding, distributing data across different geographical locations while maintaining data consistency and minimizing latency.

 **Linking Database to a Country of Residence with Configurable PII Rules:**

For businesses dealing with sensitive data and privacy regulations, Spock offers a unique advantage. Users can link specific databases to a country of residence, ensuring that Personally Identifiable Information (PII) is kept within the specified region to comply with data residency requirements. Configurable PII rules (part of the `spock.pii` metadata table) provides additional flexibility to tailor data storage policies to meet compliance needs.

## Conclusion and where to learn more

Spock's introduction is a pglogical renaissance, and elevates PostgreSQL availability to 99.99% - the 4 9’s (now a de-facto requirement). This also heralds a new era in multi-active replication for PostgreSQL. With its support for asynchronous replication, advanced conflict resolution, and enhanced monitoring capabilities, Spock empowers developers and administrators to build highly available and scalable database architectures. Spock's stress-tested performance and support for partitioned tables offer a reliable solution for modern applications with geographically distributed data requirements. Moreover, Spock's compliance features, such as linking databases to countries of residence and configurable PII rules, ensure data privacy and regulatory compliance. For anyone seeking to elevate their database replication capabilities, Spock is undoubtedly a leap forward in the Postgres world. Check out a feature comparison [here](<https://www.pgedge.com/products/product-comparison>).

To learn more and see a live demo, [join the webinar](<https://us02web.zoom.us/webinar/register/WN_nPvKgVOJQ56_3r-dGXv10Q?utm_campaign=Postgres16%20Webinar&utm_source=hs_email&utm_medium=email&_hsenc=p2ANqtz-_noRnYnlCC3ubAO0a_XFUdTdNCZHvKwIo7asrkn4Z_JWp04BfGPLY9l_VbDRtKOENqX0NX#/registration>) _Enhancing pgLogical with Multi-Master Features_ on August 30th at 11 AM ET featuring database expert and Postgres veterans Ahsan Hadi and Cady Motyka.

About the Author

Hari Kiran is a seasoned Database Engineer with nearly 17 years of experience in multiple domains of the IT industry, including healthcare, banking, project & portfolio management, and CRM. He is passionate about PostgreSQL and has helped customers across various geographies with database administration, enterprise implementations, security and hardening, backup and recovery, and performance tuning. Hari has worked at companies such as GE, EDB, Oracle, Optum, and 2ndQuadrant. He is also a regular speaker at PostgreSQL conferences like FOSSASIA Summit, PGConf India/ASIA and PGConf Down Under in Australia.

---
[View this page online](https://www.commandprompt.com/education/pglogical-rediscovered-a-fresh-approach-to-logical-replication-for-ultra-high-availability/)

---

# How to Use Postgres Docker Official Image

> To use Postgres image in Docker, run Postgres container using this image. For Docker compose file, define services in compose file and run Postgres container.

**PostgreSQL** is a well-known and free-to-use relational database system that offers many features and options for data management. The **Postgres Docker Image** is an official Docker image offered by the PostgreSQL community and maintained on Docker Hub. It enables users to easily set up and run a PostgreSQL database server within a Docker container.

This article will illustrate:

\- How to Use Official Postgres Image in Docker?

\- How to Use Official Postgres Image in Docker Compose File?

 **How to Use Official Postgres Image in Docker?**

To use the official Postgres image in Docker, first, download the Postgres image from the cloud repository (Docker Hub) in the local system utilizing the “ **docker pull postgres** ” command. Then, run the Postgres container by executing the “ **docker run -d --name postgresCont -p 5432:5432 -e POSTGRES_PASSWORD=pass123 postgres** ” command. Lastly, verify the running container.

Try out the given-below steps to understand it better.

 **Step 1: Navigate to Docker Hub**

Redirect to [Docker Hub](<https://hub.docker.com/>), and sign in or sign up to a Docker Hub account by providing the required email/username and password:

 **Step 2: Search for Postgres Docker Image**

In the search box, search for the Postgres image and open it:

 **Step 3: Copy the “pull” Command**

Copy the below-highlighted pull command of the Postgres image:

Moreover, users can also download the Postgres image with the specific tag:

 **Step 4: Pull/Download Postgres Docker Image**

Run the copied command in the specific Windows terminal to download the Docker image:
    
    
    docker   pull postgres

By doing that the Postgres Docker image has been downloaded.

 **Step 5: Verify Download Image**

List all the docker images to ensure that the Postgres image has been downloaded:
    
    
    docker images

It can be noticed that the official “ **Postgres** ” image has been downloaded successfully.

 **Step 6: Run Postgres Container Using Postgres Image**

To create and run the Postgres container using the Postgres image, utilize the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command:
    
    
    docker run -d --name postgresCont -p 5432:5432 -e POSTGRES_PASSWORD=pass123 postgres

Here:

\- “ **-d** ” flag specifies that the container should execute in the background.

\- “ **\--name** ” option is used to assign the name for the container i.e. “ **postgresCont** ”.

\- “ **-p** ” assigns the port for the container i.e. “ **5432:5432** ”.

\- “ **-e POSTGRES_PASSWORD** ” configures the password to be “ **pass123** ”.

\- “ **postgres** ” is the official Docker image:

This command has built and started the Postgres container.

 **Step 7: Verify Executing Container**

Ensure that the Postgres container is built and currently executing via the below-provided command:
    
    
    docker ps

As you can see the “ **PostgresCont** ” container is efficiently executing.

 **How to Use Official Postgres Image in Docker Compose File?**

To use the Postgres image in Docker compose file, first, make a “ **docker-compose.yml** ” file in the Visual Studio Code and specify the desired services in it. Then, build and execute the Postgres container using the “ **docker-compose up -d** ” command.

Explore the provided steps to gain a clearer understanding.

 **Step 1: Make Docker Compose File**

Create a “ **docker-compose.yml** ” file in the Visual Studio Code and define the desired services in it. For instance, we have specified the following services:
    
    
    version:   '3.8'
       services:
      postgres_db:
      image: postgres:latest
      container_name: PostgresCont 
      restart: always
      environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres123
      ports:
      - '5432:5432'
      volumes:
      - postgres_db:/var/lib/postgresql/data
       volumes:
      postgres_db:
      driver: local

 **Step 2: Run the Postgres Container**

Execute the given command to start the Postgres services defined in the Docker compose file:
    
    
    docker-compose up -d

The above command has created and started the Postgres container.

 **Step 3: Verification**

List the running containers to ensure that the Postgres container is executing:
    
    
    docker ps

It can be observed that the “ **PostgresCont** ” container is successfully executing.

 **Conclusion**

The official Postgres Docker Image can be used in Docker and Docker compose files. To use the Postgres image in Docker, download the Postgres image from the cloud repository. Then, run the Postgres container using the Postgres image and verify the running container. To use the Postgres image in Docker compose file, make a “ **docker-compose.yml** ” file in the Visual Studio Code and define the desired services in it. Then, start the compose service to build and execute the Postgres container. This article has illustrated the method of using the official Postgres Docker image.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-postgres-docker-official-image/)

---

# How to Use the LAST_VALUE() Function in PostgreSQL?

> LAST_VALUE() is one of the Window functions in Postgres that retrieves the last value in the sorted partition/window of a result set.

PostgreSQL offers several built-in functions known as window functions that allow us to do calculations across the current row. These functions are used to perform various operations, such as calculating cumulative sums, assigning row rankings within partitions, accessing rows before or after the current row, and so on.

This write demonstrates how to use LAST_VALUE Function in Postgres using the following outlines:

\- Applying LAST_VALUE() Function Over a Particular Table

\- Applying LAST_VALUE() Function Over Table Partitions

 **How to Use the LAST_VALUE() Function in PostgreSQL?**

PostgreSQL offers several built-in window functions with different functionalities. **LAST_VALUE()** is one of them that retrieves the last value in the sorted partition/window of a result set.
    
    
    LAST_VALUE (exp)
    OVER (
    [PARTITION BY partition_col_list]
    [ORDER BY order_col_list]
    );

Here,

\- “exp” represents an expression that can be any valid column, expression, or subquery. It must retrieve a single value.

\- “ **[PARTITION BY partition_col_list]** ” is an optional clause that splits the result set into partitions based on columns specified in “ **partition_col_list** ”. However, if you don't use it, the stated function will consider the entire result set as one partition.

 **Sample Table**

Let’s fetch the data of a sample table named “student_details” using the following statement:
    
    
    SELECT * FROM student_details;

 **Example 1: Applying LAST_VALUE() Function Over Entire Table**

In this example, we will apply the **LAST_VALUE()** function on the “student_details” table:
    
    
    SELECT st_id, st_name, st_gender, st_grade,
    LAST_VALUE(st_name) 
    OVER(
    ORDER BY st_grade
    RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) FROM student_details;

In the above code snippet:

\- The PARTITION BY Clause is skipped, so the LAST_VALUE() function will consider the entire table as one partition.

\- Each partition will be sorted in default (ascending) order based on the “st_grade” column.

\- The LAST_VALUE() function will pick the last value from the “st_name” column.

\- The RANGE BETWEEN clause is used to define the window frame related to the current row in every single partition:

The output demonstrates that LAST_VALUE() selects a value from the last row of the sorted table.

 **Example 2: Applying LAST_VALUE() Function Over Table Partitions**

In this example, we will apply the **LAST_VALUE()** function on the table’s partition instead of the entire result set:
    
    
    SELECT st_id, st_name, st_gender, st_grade,
    LAST_VALUE(st_name) 
    OVER(
    PARTITION BY st_gender 
    ORDER BY st_grade
    RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) 
    FROM student_details;

In the above code snippet:

\- Partitions are created based on the “st_gender” column.

\- Each partition will be sorted based on the “st_grade” column.

\- The LAST_VALUE() function will pick the last value from the “st_name” column while staying within its associated partition:

The output demonstrates that the LAST_VALUE() function selects a value from the last row based on its partitions.

 **Conclusion**

 **LAST_VALUE()** is one of the Window functions in Postgres that retrieves the last value in the sorted partition/window of a result set. The LAST_VALUE() function picks the last value from the selected column while staying within its associated partition. If the PARTITION BY Clause is skipped/ignored, the LAST_VALUE() function will consider the entire table as one partition. This write-up has demonstrated various use cases of the LAST_VALUE() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-last_value-function-in-postgresql/)

---

# PostgreSQL JSONB_SET() Function

> JSONB_SET() accepts a new value, a JSONB value, and a path as arguments, and inserts the new value at the specified path within the targeted JSONB value.

In PostgreSQL, various built-in functions are used to deal with the JSON and JSONB data efficiently, such as TO_JSONB(), JSONB_ARRAY_ELEMENTS(), JSONB_BUILD_ARRAY(), and many more. Among them, the most frequently used function is **JSONB_SET()** which inserts or updates the given value at the specified path.

This write-up will guide you on using the JSONB_SET() function in PostgreSQL using practical examples.

 **PostgreSQL JSONB_SET() Function**

JSONB_SET() is a predefined JSON function that accepts a new value, a JSONB value to insert/replace the new value into, and the targeted path. As a result, it inserts/replaces the “new value” in the targeted JSONB value at the specified path.

 **Syntax**

Check out the below-stated syntax for the PostgreSQL’s JSONB_SET() function:
    
    
    JSONB_SET(
    target_val JSONB, 
    path TEXT[], 
    new_val JSONB[, create_if_missing BOOLEAN]
    )

 **Parameters**

Here is the parameter’s description that will help you understand JSONB_SET() function better:

\- The “ **target_val** ” represents a JSONB value to insert/replace the new value into.

\- The “path” parameter represents a text array where new values ​​will be inserted.

\- The “ **new_val** ” represents a value to be inserted/replaced.

Let’s implement the JSONB_SET() function practically.

 **Example 1: Using JSONB_SET() Function on JSON Arrays**

The following example illustrates the use of the JSONB_SET() function on JSON Arrays:
    
    
    SELECT JSONB_SET('[100, 200, 125, 250, 120]', '{2}', '"Joseph"');

The above code will insert “Joseph” at the second index of the specified array:

The output demonstrates that the specified function successfully replaces the array element at the second index with "Joseph".

 **Example 2: Using JSONB_SET() Function on JSON Object**

The following example illustrates the use of the JSONB_SET() function on JSON Object:
    
    
    SELECT JSONB_SET('{"Joseph": 100}', '{Joseph}', '"250"');

The output demonstrates that the stated function successfully updated the object’s value to "250".

 **Example 3: Using JSONB_SET() Function to Insert New Field in JSON Object**

The below example demonstrates the use of the JSONB_SET() function to insert a new field in JSON Object:
    
    
    SELECT JSONB_SET('{"Joseph": 100}', '{Seth}', '250');

A path that does not already exist in the JSON object will be inserted as a new field:

A new field has been successfully inserted into the selected JSON object.

 **Example 4: Disable Default Insertion in JSON Object**

You can disable the default insertion in JSON objects by using the "false" parameter value, as shown in the following example:
    
    
    SELECT JSONB_SET('{"Joseph": 100}', '{Seth}', '250', FALSE);

From the output, it can be clearly seen that this time JSONB_SET() doesn't insert the specified value into the JSON object.

 **Conclusion**

JSONB_SET() is a predefined JSON function that accepts a new value, a JSONB value to insert/replace the new value into, and the targeted path. As a result, it inserts/replaces the “new value” in the targeted JSONB value at the specified path. A path that does not already exist in the JSON object will be inserted as a new field. However, users can disable the default insertion in JSON objects by using the "false" parameter value. This write-up has demonstrated various use cases of the JSONB_SET() function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-jsonb_set-function/)

---

# How to Use the FIRST_VALUE() Function in PostgreSQL

> FIRST_VALUE() is one of the Window functions in Postgres that retrieves the first value in the sorted partition of a result set.

PostgreSQL provides various window functions that help us in performing calculations across the rows related to the current row. These functions serve various benefits/functionalities such as computing cumulative sums, assigning ranks to the rows within the partitions, and so on.

This write demonstrates how to use FIRST_VALUE Function in Postgres using the following outlines:

\- Applying FIRST_VALUE() Function Over a Particular Table

\- Applying FIRST_VALUE() Function Over Table Partitions

 **How to Use the FIRST_VALUE() Function in PostgreSQL?**

PostgreSQL offers several built-in window functions with different functionalities. **FIRST_VALUE()** is one of them that retrieves the first value in the sorted partition/window of a result set.
    
    
    FIRST_VALUE (exp)
    OVER (
    [PARTITION BY partition_col_list]
    [ORDER BY order_col_list]
    );

Here,

\- “exp” represents an expression that can be any valid column, expression, or subquery. It must retrieve a single value.

\- “ **[PARTITION BY partition_col_list]** ” is an optional clause that splits the result set into partitions based on columns specified in “ **partition_col_list** ”. However, if you don't use it, the stated function will consider the entire result set as one partition.

 **Sample Table**

Let’s fetch the data of a sample table named “student_details” using the following statement:
    
    
    SELECT * FROM student_details;

 **Example 1: Applying FIRST_VALUE() Function Over Entire Table**

In this example, we will apply the **FIRST_VALUE()** function on the “student_details” table:
    
    
    SELECT st_id, st_name, st_gender, st_grade,
    FIRST_VALUE(st_name) 
    OVER(
    ORDER BY st_grade
    ) 
    FROM student_details;

In the above code snippet:

\- The PARTITION BY Clause is skipped, so the FIRST_VALUE() function will consider the entire table as one partition.

\- Each partition will be sorted in default (ascending) order based on the “st_grade” column.

\- The FIRST_VALUE() function will pick the first value from the “st_name” column:

The output demonstrates that FIRST_VALUE() selects a value from the first row of the sorted table.

 **Example 2: Applying FIRST_VALUE() Function Over Table Partitions**

In this example, we will apply the **FIRST_VALUE()** function on the table’s partition instead of the entire result set:
    
    
    SELECT st_id, st_name, st_gender, st_grade,
    FIRST_VALUE(st_name) 
    OVER(
    PARTITION BY st_gender 
    ORDER BY st_grade
    ) ;
    FROM student_details;

In the above code snippet:

\- Partitions are created based on the “st_gender” column.

\- Each partition will be sorted based on the “st_grade” column.

\- The FIRST_VALUE() function will pick the first value from the “st_name” column while staying within its associated partition:

The output demonstrates that the FIRST_VALUE() function selects a value from the first row based on its partitions.

 **Conclusion**

 **FIRST_VALUE()** is one of the Window functions in Postgres that retrieves the first value in the sorted partition/window of a result set. The FIRST_VALUE() function picks the first value from the selected column while staying within its associated partition. If the PARTITION BY Clause is skipped/ignored, the FIRST_VALUE() function will consider the entire table as one partition. This write-up has demonstrated various use cases of the FIRST_VALUE() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-first_value-function-in-postgresql/)

---

# How to Use in JSONB_ARRAY_LENGTH() Function in PostgreSQL

> In PostgreSQL, a built-in function named “JSONB_ARRAY_LENGTH()” is used to determine the length of a JSONB array.

PostgreSQL provides a **JSON** array data type that helps us store ordered collections in JSON format. While **JSONB** arrays store the data in “ **JSON Binary** ” format. In PostgreSQL, various built-in functions are used to deal with the JSON and JSONB data efficiently. One such function is **JSONB_ARRAY_LENGTH()** which retrieves the length of the given JSONB array.

This post illustrates a comprehensive guide to finding the length of the given JSONB array.

 **How to Use in JSONB_ARRAY_LENGTH() Function in PostgreSQL**

In Postgres, a built-in function named “ **JSONB_ARRAY_LENGTH()** ” is used to calculate/determine the length of a JSONB array. The retrieved length represents the total number of elements in that particular JSONB array.

 **Syntax**

Use the below-stated syntax to retrieve the length of a JSON array using the JSON_ARRAY_LENGTH() function:
    
    
    JSON_ARRAY_LENGTH(array JSON);

 **Parameters**

The stated function accepts a single argument “array” that represents a JSONB array.

 **Return Value**

The stated function retrieves the length of the given JSONB array.

 **Return Type**

It retrieves an **INTEGER** value which indicates the length of the specified JSONB array.

 **Example 1: Finding the Length of a JSONB Array in Postgres**

The below code snippet demonstrates the use of the JSONB_ARRAY_LENGTH() function in PostgreSQL:
    
    
    SELECT JSONB_ARRAY_LENGTH('["John", "Joseph", "Mike", ["Stephen", "Seth"]]');

The stated function retrieves the length of the specified array:

 **Example 2: Finding the Length of a JSONB Column in PostgreSQL**

Let’s set up a sample table with the following structure:
    
    
    CREATE TABLE emp_table_1 (
    emp_id SERIAL PRIMARY KEY,
    emp_data JSONB
    );

Now execute the following query to insert new records into the “emp_table”:
    
    
    INSERT INTO emp_table(emp_data) 
    VALUES
    ('[100, 120, 30, 210, 1]'),
    ('["John", "Joseph", "Mike", "Johnson", "Miller"]'),
    ('[{"e_name": "John", "e_age": 28},
    {"e_name": "Johnson", "e_age": 32},
    {"e_name": "Joseph", "e_age": 27}]')
    RETURNING *;

The desired records have been successfully inserted into the “emp_table”:

Now we will use the JSONB_ARRAY_LENGTH() function to find the length of the “emp_data” column:
    
    
    SELECT emp_data, 
    JSONB_ARRAY_LENGTH(emp_data)
    FROM emp_table;

The stated function successfully retrieves the length of the given JSONB array:

That’s all about finding the length of a JSONB array in PostgreSQL.

 **Conclusion**

In PostgreSQL, a built-in function named “ **JSONB_ARRAY_LENGTH()** ” is used to determine the length of a JSONB array. The retrieved length represents the total number of elements in that particular JSONB array. The stated function accepts a single argument “array” which must be a JSONB array. This post has illustrated the working of the JSONB_ARRAY_LENGTH() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-in-jsonb_array_length-function-in-postgres/)

---

# How to Get the Type of a JSON Value in PostgreSQL

> JSON_TYPEOF() is a built-in JSON function that accepts any valid SQL value and retrieves its data type in text format.

" **JavaScript Object Notation** ", popularly known as **JSON** is a data type in Postgres for storing data in “key-value” pairs format. The JSON can hold/store data of any valid data type, such as INT, TEXT, Boolean, etc. Therefore, while working with JSON data, determining the data type is a crucial task that helps us avoid data ambiguity. For this purpose, the JSON_TYPEOF() function is used in Postgres.

This write-up will guide you on using the JSON_TYPEOF() function in PostgreSQL using practical examples.

 **How to Get the Type of a JSON Value in PostgreSQL?**

JSON_TYPEOF() is a built-in JSON function that accepts any valid SQL value and retrieves its data type in text format.

 **Syntax**

Follow the below-provided syntax to implement JSON_TYPEOF() function in PostgreSQL:
    
    
    JSON_TYPEOF(value);

Replace “value” with any valid SQL value of your choice.

 **Example 1: Using JSON_TYPEOF() on SQL Values**

The following example illustrates the basic usage of the JSON_TYPEOF() function in PostgreSQL:
    
    
    SELECT
    JSON_TYPEOF('"Commandprompt"'),
    JSON_TYPEOF('true'),
    JSON_TYPEOF('false'),
    JSON_TYPEOF('121415'),
    JSON_TYPEOF('1214.15'),
    JSON_TYPEOF('"121415"'),
    JSON_TYPEOF('[11, 21,31]'),
    JSON_TYPEOF('{"num":100}'),
    JSON_TYPEOF('null');

The above piece of code will retrieve the following output:

The output confirms the **JSON_TYPEOF()** function successfully retrieves the data type of each value passed to it as an argument.

 **Example 2: Using JSON_TYPEOF() on NULL Values**

Consider the below-provided code to learn how the JSON_TYPEOF() deals with the NULL values:
    
    
    SELECT JSON_TYPEOF(NULL);

The output snippet shows that passing a NULL value to the JSON_TYPEOF() retrieves “null” in the output:

Alternatively, you can verify the return value of the NULL value using the “IS NULL” operator, as follows:
    
    
    SELECT json_typeof(NULL) IS NULL;

The “True” value in the output shows that the type of the NULL value is “null”:

That’s all about using the JSON_TYPOF() function in PostgreSQL.

 **Conclusion**

JSON_TYPEOF() is a built-in JSON function that accepts any valid SQL value and retrieves its data type in text format. Use the “JSON_TYPEOF(value);” syntax to get the type of a JSON object. Replace “value” with any valid SQL value of your choice. This post has demonstrated a practical guide on different use cases of the JSON_TYPEOF() function in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-type-of-a-json-value-in-postgresql/)

---

# What Does the TO_JSONB() Function Do in PostgreSQL

> In PostgreSQL, the TO_JSONB() is a built-in JSON function that accepts any SQL value as an argument and converts it to JSONB format.

" **JavaScript Object Notation** ", popularly known as **JSON** is a data type in Postgres for storing data in “key-value” pairs format. While **JSONB** or “ **JSON BINARY** ” is a data type that stores data in binary format. Postgres offers various inbuilt functions and operators to work with JSON and JSONB data efficiently.

This write-up will guide you on using the TO_JSONB() function in PostgreSQL using practical examples.

 **What Does the TO_JSONB() Function Do in PostgreSQL?**

TO_JSONB() is a built-in JSON function that accepts any valid SQL value and converts it into JSONB format. Follow the below-provided syntax to implement TO_JSONB() function in PostgreSQL:
    
    
    TO_JSONB(value);

Here, the “value” can be any valid SQL value.

Let’s implement this function practically!

 **Example 1: Using TO_JSONB() on SQL Values**

The following example illustrates the basic usage of the TO_JSONB() function in PostgreSQL:
    
    
    SELECT
    TO_JSONB(510),
    TO_JSONB(13.52),
    TO_JSONB('Command Prompt'::text),
    TO_JSONB(True),
    TO_JSONB(False);

In this example, we passed an integer, a floating point value, a text value, and a couple of BOOLEAN values to the TO_JSONB() function. Consequently, the stated function converts all the values into JSONB format:

The provided values have been successfully converted into JSONB type.

 **Example 2: Using TO_JSONB() on Arrays**

This example demonstrates the use of TO_JSONB() function on the arrays’ data:
    
    
    SELECT TO_JSONB(ARRAY[[110, 102], [113, 410], [131, 103]]);

The given array has been successfully converted into JSONB format.

 **Example 3: Using TO_JSONB() on Composite Types**

In the following example, the JSONB() function is used on the composite type values:
    
    
    SELECT TO_JSONB(ROW(110, 102, 'Joseph', 25, 'Joseph is an Author'));

\- First, we utilized the “ROW” expression to construct a composite type.

\- The composite type value contains five elements.

\- After that, the TO_JSONB() is utilized on the composite type data.

The output shows that the composite type has been successfully converted into JSONB type:

That’s all about converting any SQL value to JSONB form.

 **Conclusion**

In PostgreSQL, the TO_JSONB() is a built-in JSON function that accepts any SQL value as an argument and converts it to JSONB format. To use TO_JSONB() in Postgres, use the “TO_JSONB(value);” syntax. Where the “value” can be any valid SQL value. This post has demonstrated a practical guide on different use cases of the TO_JSONB() function in Postgres.

---
[View this page online](https://www.commandprompt.com/education/what-does-the-to_jsonb-function-do-in-postgresql/)

---

# How ROW_TO_JSON() Function works in PostgreSQL

> In PostgreSQL, the ROW_TO_JSON() is a built-in JSON function that accepts any valid SQL composite type value and converts it into a JSON object.

" **JavaScript Object Notation** ", popularly known as **JSON** is a process of storing data in “key-value” pairs format. JSON is easy for humans to read/understand and is generally utilized for communication between servers and clients. Postgres offers many useful functions and operators to work with JSON data, such as TO_JSON(), **ROW_TO_JSON()** , ARRAY_TO_JSON, and many more.

This write-up will guide you on using the ROW_TO_JSON() function in PostgreSQL using practical examples.

 **How Does the ROW_TO_JSON() Function Work in PostgreSQL?**

ROW_TO_JSON() is a built-in JSON function that accepts any valid SQL composite type value and converts it into a JSON object.

 **Syntax**

Below is the PostgreSQL ROW_TO_JSON() function's syntax:
    
    
    ROW_TO_JSON(row RECORD, pretty BOOLEAN);

 **Parameters**

The “row” is a mandatory parameter that must be a value of type composite. While “pretty” is an optional parameter that beautifies the retrieved result of the ROW_TO_JSON() function.

Let’s implement this function practically!

 **Example 1: Using ROW_TO_JSON() on Composite Types**

The following example illustrates the use of the ROW_TO_JSON() function on composite type values :
    
    
    SELECT ROW_TO_JSON(ROW(110, 102, 'Joseph', 25, 'Joseph is an Author'));

Here in the above code:

\- We utilized the “ROW” expression to construct a composite type.

\- The composite type value contains five elements.

\- After that, the ROW_TO_JSON() is utilized on the composite type data.

\- The ROW_TO_JSON() function auto-generates keys for the JSON object in “fn” format, where “n = 1, 2, 3, …”.

The output shows that the composite type has been successfully converted into a JSON object:

 **Example 2: Using ROW_TO_JSON() With pretty Parameter**

Pass the Boolean “true” as a pretty argument to beautify the converted JSON object:
    
    
    SELECT ROW_TO_JSON(ROW(110, 102, 'Joseph', 25, 'Joseph is an Author'), true);

That’s all about converting any SQL value to JSON Object.

 **Conclusion**

In PostgreSQL, the ROW_TO_JSON() is a built-in JSON function that accepts any valid SQL composite type value and converts it into a JSON object. To use ROW_TO_JSON() in Postgres, use the “ROW_TO_JSON(row RECORD, pretty BOOLEAN);” syntax. Where the “row” is a mandatory parameter that must be a value of type composite. While “pretty” is an optional parameter that beautifies the retrieved result of the ROW_TO_JSON() function. This post has demonstrated a practical guide on different use cases of the ROW_TO_JSON() function in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-row_to_json-function-works-in-postgresql/)

---

# How Does the TO_JSON() Function Work in PostgreSQL?

> In PostgreSQL, the TO_JSON() is a built-in JSON function that accepts any SQL value as an argument and converts it to JSON format.

**JSON** or " **JavaScript Object Notation** " is a process of storing data in “key-value” pairs format. It's easy for humans to read/understand and is often used for communication between servers and clients. Postgres has native support for JSON starting from version 9.2 and onward releases. Postgres offers many useful functions and operators to work with JSON data efficiently.

This write-up will guide you on using the TO_JSON() function in PostgreSQL using practical examples.

 **How Does the TO_JSON() Function Work in PostgreSQL?**

TO_JSON() is a built-in JSON function that accepts any valid SQL value and converts it into JSON format. Below is the PostgreSQL TO_JSON() function's syntax:
    
    
    TO_JSON(value);

Here, the “value” can be any valid SQL value.

Let’s implement this function practically!

 **Example 1: Using TO_JSON() on SQL Values**

The following example illustrates the basic usage of the TO_JSON() function in PostgreSQL:
    
    
    SELECT
    TO_JSON(510),
    TO_JSON(13.52),
    TO_JSON('Command Prompt'::text),
    TO_JSON(True),
    TO_JSON(False);

In this example, we passed an integer, a floating point value, a text value, and a couple of BOOLEAN values to the TO_JSON() function. Consequently, the stated function converts all the values into JSON format:

The provided values have been successfully converted into JSON type.

 **Example 2: Using TO_JSON() on Arrays**

This example demonstrates the use of TO_JSON() function on the arrays’ data:
    
    
    SELECT TO_JSON(ARRAY[[110, 102], [113, 410], [131, 103]]);

The given array has been successfully converted into JSON format.

 **Example 3: Using TO_JSON() on Composite Types**

In the following example, we utilized the “ROW” expression to construct a composite type. The composite type value contains five elements. After that, the TO_JSON() is utilized on the composite type data:
    
    
    SELECT TO_JSON(ROW(110, 102, 'Joseph', 25, 'Joseph is an Author'));

The output shows that the composite type has been successfully converted into JSON type:

That’s all about converting any SQL value to JSON form.

 **Conclusion**

In PostgreSQL, the TO_JSON() is a built-in JSON function that accepts any SQL value as an argument and converts it to JSON format. To use TO_JSON() in Postgres, use the “TO_JSON(value);” syntax. Where the “value” can be any valid SQL value. This post has demonstrated a practical guide on different use cases of the TO_JSON() function in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-does-the-to_json-function-work-in-postgresql/)

---

# How to Use CUME_DIST Function in PostgreSQL

> In PostgreSQL, the CUME_DIST() function retrieves the cumulative distribution of a value for the given set of values.

While working with databases, users may need to make a report that shows the very best or worst percentage of values from a set of data. For example, a user may want to calculate the top 1% of products with the highest or lowest revenue. For this purpose, Postgres offers a very convenient function named **CUME_DIST()** that can help us deal with such scenarios.

This write demonstrates how to use CUME_DIST Function in Postgres using the following outlines:

\- Applying CUME_DIST() Function Over a Particular Table

\- Applying CUME_DIST() Function Over a Table Partitions

 **How to Use CUME_DIST Function in PostgreSQL?**

 **CUME_DIST()** is one of the popularly used **Window** functions in Postgres that retrieves the cumulative distribution of a value for the given set of values.

Check the following syntax that will help you understand how to use **CUME_DIST()** function in Postgres:
    
    
    CUME_DIST()
    OVER (
    [PARTITION BY partition_col_list]
    [ORDER BY order_col_list]
    )

In the above syntax:

\- " **OVER** " is a keyword that shows the starting point of the window function's operation. It tells the stated window function which rows to consider for its calculations.

\- “ **[PARTITION BY partition_col_list]** ” is an optional clause that splits the result set into partitions based on columns specified in “ **partition_col_list** ”.

\- Once the result set is divided into partitions, then the specified window function will be applied separately to each partition. However, if you omit this clause, the whole table/result set will be considered as a single partition.

\- The **ORDER BY** is an optional clause that can be used within the CUME_DIST() function to arrange the rows within each partition.

\- The stated function retrieves a double precision value in the following range: “ **0 < CUME_DIST() <= 1**”

Let’s set up a sample table and practically implement the CUME_DIST() function on that table.

 **Sample Table**

Let’s begin with creating a sample table named “transaction_details” that keeps the revenue details:
    
    
    CREATE TABLE transaction_details(
    person_name TEXT NOT NULL,
    year SMALLINT CHECK (year > 0),
    transaction_amount DECIMAL(10,2) CHECK (transaction_amount >= 0),
    PRIMARY KEY (person_name, year)
    );

Once the desired table is created, insert some new records into it using the following query:
    
    
    INSERT INTO transaction_details(person_name, year, transaction_amount)
    VALUES ('Alexa', 2021, 150000),
    ('Joseph', 2020, 95000),
    ('Daniel', 2021, 135000),
    ('Anna', 2022, 125000),
    ('Stephan', 2023, 180000),
    ('Alex', 2021, 250000),
    ('Joe', 2021, 90000);

Let’s fetch the transaction_details table to confirm the inserted data:
    
    
    SELECT * FROM transaction_details;

 **Example 1: Applying CUME_DIST() Function Over a Particular Table**

In this example, we will apply the **CUME_DIST()** function on the “transaction_details” table:
    
    
    SELECT person_name, year, transaction_amount,
    CUME_DIST() OVER (
    ORDER BY transaction_amount
    ) 
    FROM transaction_details
    WHERE year = 2021

The output demonstrates that in the year 2021, the transaction amount of 75% of people was less than or equal to “150000”.

 **Example 2: Applying CUME_DIST() Function Over a Table Partition**

In this example, we will apply the CUME_DIST() function on the table’s partition instead of the entire result set:
    
    
    SELECT person_name, year, transaction_amount,
    CUME_DIST() OVER (
    PARTITION BY DESC year
    ORDER BY transaction_amount
    ) 
    FROM transaction_details

The output snippet depicts that the given result set has been divided into partitions (with respect to year), and the CUME_DIST() function has been successfully implemented over each partition:

That’s all about the CUME_DIST() function in Postgres.

 **Conclusion**

In PostgreSQL, the **CUME_DIST()** function retrieves the cumulative distribution of a value for the given set of values. The PARTITION BY and ORDER BY clauses can be used with the CUME_DIST() function to split the result set into partitions and to sort the partition/result set, respectively. Moreover, the stated function can be applied over an entire result set or a specific partition depending upon the user's needs. This post has explained how to use the CUME_DIST() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-cume_dist-function-in-postgresql/)

---

# What Does ENUM_LAST() Function Do in PostgreSQL?

> The ENUM_LAST() is a built-in function in Postgres that retrieves the last value of the enum specified by the parameter.

PostgreSQL offers various built-in functions to manipulate the Enums data efficiently, such as ENUM_FIRST(), **ENUM_LAST()** , and ENUM_RANGE(). All these functions serve a specific purpose. For instance, the ENUM_FIRST() function retrieves the first value of the enum, the ENUM_LAST() function retrieves the last value of the enum, and ENUM_RANGE() retrieves the enumeration values within the specified range.

This post will illustrate the working of the ENUM_LAST() function using practical examples.

 **What Does ENUM_LAST() Function Do in PostgreSQL?**

The **ENUM_LAST()** is a built-in function in Postgres that retrieves the last value of the enum specified by the parameter. Use the below-provided syntax to apply the ENUM_LAST() function on the enum type:
    
    
    ENUM_LAST(enum_value ENUM);

Here, enum_val is a mandatory parameter that represents an enumeration value.

 **Example: Using ENUM_FIRST() in Postgres**

First, let’s create an enum type named “example_enum” using the below-provided statement:
    
    
    CREATE TYPE example_enum AS ENUM (
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec'
    );

In the above code snippet, we utilized the CREATE TYPE to create an enum type that contains month names of the year:

Now, we will invoke the ENUM_LAST on the example_enum to get the last enum value of “example_enum”:
    
    
    SELECT ENUM_LAST(null::example_enum);

The output shows that the ENUM_LAST() successfully retrieves the last enum value of the example_enum:

In the following code snippet, we will pass all enumeration values ​​of type example_enum to the ENUM_LAST() function. As a result, the stated function will retrieve the following output:
    
    
    SELECT ENUM_LAST('Jan'::example_enum),
    ENUM_LAST('Feb'::example_enum),
    ENUM_LAST('Mar'::example_enum),
    ENUM_LAST('Apr'::example_enum),
    ENUM_LAST('May'::example_enum),
    ENUM_LAST('Jun'::example_enum),
    ENUM_LAST('Jul'::example_enum),
    ENUM_LAST('Aug'::example_enum),
    ENUM_LAST('Sep'::example_enum),
    ENUM_LAST('Oct'::example_enum),
    ENUM_LAST('Nov'::example_enum),
    ENUM_LAST('Dec'::example_enum);

The output shows that the ENUM_LAST() function retrieves the last enumeration value:

This is how the ENUM_LAST() function works in Postgres.

 **Conclusion**

The **ENUM_LAST()** is a built-in function in Postgres that retrieves the last value of the enum specified by the parameter. It accepts a mandatory parameter “enum_val” that represents an enumeration value and retrieves the last value of the selected enum. This blog post demonstrated the use of the ENUM_LAST() function in PostgreSQL using practical examples.

---
[View this page online](https://www.commandprompt.com/education/what-does-enum_last-function-do-in-postgresql/)

---

# How to Use ENUM_FIRST() Function in PostgreSQL

> The ENUM_FIRST() is a built-in function in Postgres that retrieves the first value of the enum specified by the parameter.

PostgreSQL supports a custom data type known as “ENUM” that is used to define a fixed set of values for the table's column. Enums provide a secure and reliable way of controlling what data can be inserted into a table's column. PostgreSQL offers various built-in functions that help us manipulate the Enums data efficiently.

This post will illustrate the working of the ENUM_FIRST() function using practical examples.

 **How to Use ENUM_FIRST() Function in PostgreSQL?**

The **ENUM_FIRST()** is a built-in function in Postgres that retrieves the first value of the enum specified by the parameter. Use the below-provided syntax to apply the ENUM_FIRST() function on the enum type:
    
    
    ENUM_FIRST(enum_value ENUM);

Here, enum_val is a mandatory parameter that represents an enumeration value.

 **Example: Using ENUM_FIRST() in Postgres**

First, let’s create an enum type named “example_enum” using the below-provided statement:
    
    
    CREATE TYPE example_enum AS ENUM (
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec'
    );

In the above code snippet, we utilized the CREATE TYPE to create an enum type that contains month names of the year:

Now, we will invoke the ENUM_FIRST on the example_enum to get the first enum value of “example_enum”:
    
    
    SELECT ENUM_FIRST(null::example_enum);

The output shows that the ENUM_FIRST() successfully retrieves the first enum value of the example_enum:

In the following code snippet, we will pass all enumeration values ​​of type example_enum to the ENUM_FIRST() function. As a result, the stated function will retrieve the following output:
    
    
    SELECT ENUM_FIRST('Jan'::example_enum),
    ENUM_FIRST('Feb'::example_enum),
    ENUM_FIRST('Mar'::example_enum),
    ENUM_FIRST('Apr'::example_enum),
    ENUM_FIRST('May'::example_enum),
    ENUM_FIRST('Jun'::example_enum),
    ENUM_FIRST('Jul'::example_enum),
    ENUM_FIRST('Aug'::example_enum),
    ENUM_FIRST('Sep'::example_enum),
    ENUM_FIRST('Oct'::example_enum),
    ENUM_FIRST('Nov'::example_enum),
    ENUM_FIRST('Dec'::example_enum);

The output shows that the ENUM_FIRST() function retrieves the first enumeration value:

This is how the ENUM_FIRST() function works in Postgres.

 **Conclusion**

The **ENUM_FIRST()** is a built-in function in Postgres that retrieves the first value of the enum specified by the parameter. It accepts a mandatory parameter “enum_val” that represents an enumeration value and retrieves the first value of the selected enum. This blog post demonstrated the use of the ENUM_FIRST() function in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-enum_first-function-in-postgresql/)

---

# How Does the JSON_BUILD_OBJECT() Function Work in PostgreSQL

> The JSON_BUILD_OBJECT() function is used to create and retrieve a JSON object from a variadic parameter list of key-value pairs.

In PostgreSQL, **JSON_BUILD_OBJECT** () is a built-in function that creates a JSON object using a list of key-value pairs provided as arguments. Each argument in the list is evaluated, with keys converted to text and values converted into JSONB values using the TO_JSONB() function. However, the specified number of arguments must be even; otherwise, PostgreSQL will throw an error.

This post will demonstrate the basic syntax and several use cases of the JSON_BUILD_OBJECT() function in Postgres.

 **How Does the JSON_BUILD_OBJECT() Function Work in PostgreSQL?**

The JSON_BUILD_OBJECT() function is used to create and retrieve a JSON object from a variadic parameter list of key-value pairs. Use the below-stated syntax to build a new JSON Object from the specified values:
    
    
    JSON_BUILD_OBJECT(VARIADIC values);

It accepts mandatory argument “values” that can be of any data type.

 **Example 1: Using JSON_BUILD_OBJECT()**

This example demonstrates the usage of the PostgreSQL JSON_BUILD_OBJECT() function to create a new JSON object from the given values:
    
    
    SELECT JSON_BUILD_OBJECT(100, 'Johnson', FALSE, row(20, 'h', TRUE), 'Num', 117);

Here in the above snippet:

\- Six parameters/values are passed to the JSON_BUILD_OBJECT() function.

\- Here, “100”, “FALSE”, and “Num” are the keys, and “Johnson”, “row(20, 'h', TRUE)”, and “117” are their respective values.

The stated function converts the provided parameters into keys and values as follows:

\- 100 represents a key, which is transformed into 100.

\- Johnson is the corresponding value of the key 100, which is converted into 100.

\- FALSE represents a key, which is converted into FALSE.

\- “row(20, 'h', TRUE)” represents the value of the key FALSE which is converted into {"f1":20,"f2":"h","f3":true}.

\- Num indicates a key that is converted into “Num”.

\- 117 is the corresponding value of the key “Num”.

\- After that, the JSON_BUILD_OBJECT() function joins all the key-value pairs and retrieves them as a JSONB object:

 **Example 2: ERROR: Argument List Must Have Even Number of Elements**

An error will occur if a user passes an odd number of arguments. The error message will indicate that the argument list must contain an even number of elements:
    
    
    SELECT JSON_BUILD_OBJECT(100, 'Johnson', FALSE, row(20, 'h', TRUE), 'Num');

That’s all about using the JSON_BUILD_OBJECT() function in PostgreSQL.

 **Conclusion**

The JSON_BUILD_OBJECT() function is used to create and retrieve a JSON object from a variadic parameter list of key-value pairs. Each argument in the list is evaluated, with keys converted to text and values converted into JSONB values using the TO_JSONB() function. This write-up has demonstrated the complete process of using the JSON_BUILD_OBJECT() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-does-the-json_build_object-function-work-in-postgresql/)

---

# How to Use JSON_BUILD_ARRAY() Function in PostgreSQL

> The JSON_BUILD_ARRAY() is a built-in JSON function that creates and retrieves a JSON array of different types from a variadic parameter list.

PostgreSQL's JSON array data type stores ordered collections in JSON format and is similar to standard arrays in programming. Postgres offers various built-in JSON functions for efficient data manipulation, such as ARRAY_TO_JSON(), **JSON_BUILD_ARRAY()** , JSON_ARRAY_LENGTH(), and more.

This post will demonstrate the basic syntax and several use cases of the JSON_BUILD_ARRAY() function in Postgres.

 **How to Use JSON_BUILD_ARRAY() Function in PostgreSQL?**

The JSON_BUILD_ARRAY() is a built-in JSON function that creates and retrieves a JSON array of different types from a variadic parameter list.

 **Syntax**

Use the below-stated syntax to build a new JSON array from the specified values:
    
    
    JSON_BUILD_ARRAY(VARIADIC values);

 **Parameters**

The stated function accepts a VARIADIC argument list. It can accept n number of parameters of any data type.

 **Return Value**

It retrieves a heterogeneous JSON array.

 **Example 1: Using JSON_BUILD_ARRAY()**

This example demonstrates the usage of the PostgreSQL JSON_BUILD_ARRAY() function to create a new array from the given values:
    
    
    SELECT JSON_BUILD_ARRAY(100, 'Johnson', FALSE, row(20, 'h', TRUE), 272);

Here in the above snippet:

\- Five parameters/values are passed to the JSON_BUILD_ARRAY() function.

\- The stated function converts the provided parameters into JSON values. For this purpose, the JSON_BUILD_ARRAY() function internally utilizes the TO_JSON() function.

\- TO_JSON(100) retrieve 100.

\- TO_JSON(Johnson) retrieves Johnson.

\- TO_JSON(FALSE) retrieves FALSE.

\- TO_JSON(row(20, 'h', TRUE)) retrieve {"f1":20,"f2":"h","f3":true}.

\- TO_JSON(272) retrieve 272.

\- After that, the JSON_BUILD_ARRAY() function joins the parameter values and retrieves them as an ARRAY:

The output snippet demonstrates that a JSON array has been created from the given values.

 **Conclusion**

The JSON_BUILD_ARRAY() is a built-in JSON function that creates and retrieves a JSON array of different types from a variadic parameter list. The stated function accepts a VARIADIC argument list. It can accept n number of parameters of any data type. It retrieves a heterogeneous JSON array. This write-up has demonstrated the working of the JSON_BUILD_ARRAY() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-json_build_array-function-in-postgresql/)

---

# How to Use the ARRAY_TO_JSON() Function in PostgreSQL

> The array_to_json() is a built-in JSON function that accepts a SQL array as an argument and converts it into a JSON array.

In PostgreSQL, the **JSON** array data type is used to store ordered collections in JSON format. It is similar to standard arrays in programming. PostgreSQL offers several built-in JSON functions to manipulate JSON data efficiently, such as **ARRAY_TO_JSON()** , JSON_ARRAY_ELEMENTS(), JSON_ARRAY_LENGTH(), and many more.

This post illustrates the basic syntax and working of the ARRAY_TO_JSON() function in Postgres using practical examples.

 **How to Use the ARRAY_TO_JSON() Function in PostgreSQL?**

The array_to_json() is a built-in JSON function that accepts a SQL array as an argument and converts it into a JSON array.

 **Syntax**

Use the below-stated syntax to retrieve a converted JSON array from the specified SQL array:
    
    
    ARRAY_TO_JSON(array ARRAY, pretty BOOLEAN);

 **Parameters**

The stated function accepts a mandatory argument “array” that represents an SQL array. Moreover, it can accept an optional argument “pretty” to beautify the resultant JSON ARRAY.

 **Return Value**

It retrieves a JSON array.

 **Example 1: Using ARRAY_TO_JSON()**

This example demonstrates the usage of the PostgreSQL array_to_json() function to convert the given SQL array into a JSON array:
    
    
    SELECT ARRAY_TO_JSON('{100, 12, 53, -1, 24}'::int[]) AS converted_json_array;

The specified array has been successfully converted into a JSON array:

 **Example 2: Using ARRAY_TO_JSON() on Multidimensional Array**

This example illustrates the usage of the PostgreSQL array_to_json() function on a multi-dimensional array:
    
    
    SELECT ARRAY_TO_JSON('{{"John", "Joseph"}, 
     {"Henry", "Anna"}}'::TEXT[]) AS converted_json_array;

The specified array has been successfully converted into a JSON array:

 **Example 3: Using ARRAY_TO_JSON() With Pretty Parameter**

This example uses the true value for the “pretty” parameter to beautify the resultant JSON ARRAY.
    
    
    SELECT ARRAY_TO_JSON('{{"John", "Joseph"}, 
     {"Henry", "Anna"}}'::TEXT[], pretty) AS converted_json_array;

The output snippet demonstrates that the converted array has been beautified successfully:

That was all about the ARRAY_TO_JSON() function in Postgres.

 **Conclusion**

The array_to_json() is a built-in JSON function that accepts a SQL array as an argument and converts it into a JSON array. The stated function accepts a mandatory argument “array” that represents an SQL array and an optional argument “pretty” to beautify the resultant JSON ARRAY. It retrieves a JSON array. This post has illustrated several use cases of the ARRAY_TO_JSON() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-array_to_json-function-in-postgresql/)

---

# How to Exit Postgres' Command Line Utility (SQL Shell)

> In PostgreSQL, various methods are used to exit the Postgres command line utility, such as the “\q” or “\quit” commands, and “CTRL + C”, “CTRL + D”, or “CTRL +…

Various command line utilities have different exit conventions, which makes it difficult to recall/remember the exact command needed to exit them. When it comes to Postgres, it provides a default command line interface, known as “SQL Shell” or “psql”. This interface enables users to perform database operations using different commands and meta-commands.

One of the most convenient ways of exiting the Postgres command line utility is by executing one of these special meta-commands. Moreover, if a user forgets the meta-command he can use the “\?” to get help regarding available meta-commands.

This post will illustrate the several methods to exit from Postgres’ command line utility.

 **How to Exit Postgres ' Command Line Utility (SQL Shell)?**

Use one of the below-exhibited methods to exit the Postgres command line utility:

\- Using \q  
\- Using \quit  
\- Using CTRL + C  
\- Using CTRL + D (Linux)  
\- Using CTRL + Z (Windows)

Let’s start with “\q”.

 **How to Exit Postgres ' Command Line Utility (SQL Shell) Using \q?**

SQL Shell or psql supports a meta-command named “\q” that helps us quit the Postgres command line utility. Here is the practical demonstration of the stated meta-command:
    
    
    \q

Executing the “\q” meta-command will ask you to press any key:

Pressing any keyboard key will close the SQL Shell.

 **How to Exit Postgres ' Command Line Utility (SQL Shell) Using \quit?**

Alternatively, users can execute the “\quit” meta-command to exit/quit the Postgres command line utility. Here is the practical implementation of the stated meta-command:
    
    
    \quit

Press any keyboard key to exit the SQL Shell:

 **How to Exit Postgres ' Command Line Utility (SQL Shell) Using CTRL + C?**

The “CTRL + C” is the shortcut key for exiting the Postgres command line utility. For a better understanding of the given shortcut key, check out the below-given snippet:
    
    
    CTRL + C

Press Y and hit ENTER to terminate the Postgres’ command line utility:

 **How to Exit Postgres ' Command Line Utility (SQL Shell) Using CTRL + D?**

In the Linux operating system, the CTRL + D is a shortcut key that allows us to exit from the Postgres command line utility. Check out the below-given steps for a profound understanding of the stated shortcut key:

 **Step 1: Access Postgres From Terminal**

Launch the terminal, and use the following “sudo” command to access the Postgres command line utility:
    
    
    sudo -u postgres psql

 **Step 2: Access Postgres From Terminal**

Now hit the “ **CTRL + D** ” shortcut key on the keyboard to exit the Postgres command line utility:
    
    
    CTRL + D

The output snippet shows pressing the CTRL + D shortcut key exited us from the Postgres command line utility:

 **How to Exit Postgres ' Command Line Utility (SQL Shell) Using CTRL + Z?**

In the Windows operating system, the CTRL + Z is a shortcut key that helps us exit from the Postgres command line utility. Go through the below-provided steps to find out how this shortcut key works:

 **Step 1: Access Postgres From CMD**

Launch the CMD, and use the cd command to get into the Postgres bin directory:
    
    
    cd \Program Files\PostgreSQL\15\bin

 **Step 2: Connect to Postgres**

Now use the below-stated psql command to connect to the Postgres:
    
    
    psql -U postgres

 **Step 3: Exit Postgres Command Line Utility**

Now type in the “ **CTRL + Z** ” shortcut key on the keyboard and hit the ENTER button to exit the Postgres command line utility:
    
    
    CTRL + Z

The output snippet shows that we have successfully exited the Postgres command line utility:

That’s all about exiting the Command Line Utility (SQL Shell).

 **Conclusion**

In PostgreSQL, various methods are used to exit the Postgres command line utility, such as the “\q” or “\quit” commands, and “CTRL + C”, “CTRL + D”, or “CTRL + Z” shortcut keys. The most convenient way of exiting the Postgres command line utility is to execute the “\q” or “\quit” meta-commands. This post has illustrated several methods for exiting the Postgres command line utility, i.e., SQL Shell or psql.

---
[View this page online](https://www.commandprompt.com/education/how-to-exit-postgres-command-line-utility-sql-shell/)

---

# How to Include Multiple Postgres Databases in a Single Docker Container

> To include multiple PostgreSQL databases in Docker container, continuously run the “CREATE DATABASE &lt;database-name&gt;” command with different database names.

**PostgreSQL** is a well-known relational DBMS that can be used in Docker to easily create and manage the PostgreSQL database without installing it on the local host machine. Sometimes, users work on a project that requires multiple Postgres databases for various reasons. In this situation, they can include various Postgres databases in a single container.

This write-up will demonstrate the procedure to include various PostgreSQL databases in a single Docker container.

 **How to Include Multiple Postgres Databases in a Single Docker Container?**

To include multiple PostgreSQL databases in a single Docker container, follow the given-provided steps:

\- Download Postgres Docker Image  
\- Create and Run the Postgres Container  
\- Interact With Executing Container  
\- Establish a Connection With a Database Server  
\- Create Multiple PostgreSQL Database in Docker Container  
\- Display All Available Databases

 **Step 1: Download Postgres Docker Image**

Run the below-listed “ **docker pull** ” command in Windows PowerShell to download the official Postgres image from the cloud repository (Docker Hub) to the local system:
    
    
    docker pull postgres

 **Step 2: Create and Run Postgres Container**

Build and run the Postgres container by utilizing the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command:
    
    
    docker run -d --name postgresCont -p 5432:5432 -e POSTGRES_PASSWORD=pass123 postgres

Here:

\- “ **-d** ” flag specifies that the container should execute in the background.  
\- “ **\--name** ” option assigns the container’s name, i.e., “ **postgresCont** ”.  
\- “ **-p** ” assigns the port for the container i.e. “ **5432:5432** ”.  
\- “ **-e POSTGRES_PASSWORD** ” configures the password to be “ **pass123** ”.  
\- “ **postgres** ” is the official Docker image:

By doing that, the Postgres container has been created and started.

 **Step 3: Interact With Executing Container**

Type out the “ **docker exec -it <cont-name> bash**” command and specify the executing Postgres container name to open the shell within it:
    
    
    docker exec -it postgresCont bash

Subsequently, the “ **PostgresCont** ” container has been accessed and now we can execute commands in it.

 **Step 4: Establish a Connection With Database Server**

To make a connection with the Postgres Database Server, execute the “psql” command along with the hostname and user name:
    
    
    psql -h localhost -U postgres

As you can see, the SQL shell has been started successfully where we can run PostgreSQL queries and psql commands.

 **Step 5: Create Multiple PostgreSQL Database in Docker Container**

Now, create a new Postgres database by executing the “ **CREATE DATABASE** ” command along with the database name. For instance, we are creating a database named “ **tsl_employee** ”:
    
    
    CREATE DATABASE tsl_employee;

The below output indicates that the specified database has been created:

Continuously repeat this step to create multiple Postgres Databases and specify different names for each new database as you can see in the below screenshot:

Upon doing so, multiple databases have been created.

 **Step 6: Display All Available Databases**

To list all the databases, execute the “ **\l** ” command:
    
    
     \l

In the below screenshot, six databases can be seen in a single container:

We have successfully included multiple Postgres databases in a single Docker container.

 **Conclusion**

To include various Postgres databases in a single Docker container, first, download the Postgres Docker image. Then, create and run the Postgres container via the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command. Next, interact with the executing container and establish a connection with a database server using the “ **psql -h localhost -U postgres** ” command.

After that, create multiple PostgreSQL databases in a single Docker container by continuously executing the “ **CREATE DATABASE <database-name>**” command with different names for each new database. Lastly, display all the available databases. This write-up has demonstrated the procedure to include multiple Postgres databases in a single Docker container.

---
[View this page online](https://www.commandprompt.com/education/how-to-include-multiple-postgres-databases-in-a-single-docker-container/)

---

# How to Do Table Inheritance in PostgreSQL

> In PostgreSQL, the “table inheritance” allows us to create a hierarchy of tables, where one table(child) can inherit the structure and properties of another (p…

Inheritance is a very common task in programming, and this concept is also used in the PostgreSQL database. PostgreSQL allows its users to inherit specific features of one table into another table. This concept is referred to as “ **Table inheritance** ” in Postgres. It is useful when dealing with multiple tables that share similar attributes.

This post will illustrate a detailed guide on inheriting attributes of one table to another.

 **How to Do Table Inheritance in PostgreSQL?**

In PostgreSQL, the “table inheritance” allows us to create a hierarchy of tables, where one table(child) can inherit the structure and properties of another (parent) table. To perform table inheritance in PostgreSQL, you simply need to use the " **INHERITS** " keyword.

 **Example 1: Apply Table Inheritance in PostgreSQL**

First, create a parent table named “emp” with the following structure:
    
    
    CREATE TABLE emp (
    e_id SERIAL PRIMARY KEY,
    e_name TEXT,
    e_sal INT
    );

The parent table has been successfully created with the desired columns:

Now, create another table named “author” and make it a child of the “emp” table:
    
    
    CREATE TABLE author (
    e_bonus INT
    )INHERITS (emp);

The INHERITS clause is used along with the parent table’s name to create table inheritance:

Let’s create another table named “developer” and make it a child of the “emp” table as well:
    
    
    CREATE TABLE developer(
    dev_bonus INT
    )INHERITS (emp);

Now execute the following INSERT INTO command to insert a new record into the child tables, i.e., author and developer:
    
    
    INSERT INTO author (e_name, e_sal, e_bonus)
    VALUES ('John', 25000, 12000);

Execute the same query to insert a new record into the developer table:
    
    
    INSERT INTO developer (e_name, e_sal, dev_bonus)
    VALUES ('Joseph', 35000, 5000);

Now, execute the following “SELECT *” command to see how the TABLE INHERITANCE work in Postgres:
    
    
    SELECT * FROM emp;

The above command fetches the data from the parent table, the parent table includes the records of both child tables:

Now, run the “SELECT *” command with the “author” to see its records individually:
    
    
    SELECT * FROM author;

The above command fetches the data from the selected child table:

Similarly, the SELECT query can be used with any other child table to fetch its record individually:
    
    
    SELECT * FROM developer;

The above-stated command fetches the records from the developer table:

 **Example 2: Remove Table Inheritance in PostgreSQL**

Use the ALTER TABLE command with the “NO INHERIT” clause to remove the inheritance from the selected table. In the following example, the inheritance is detached from the author table:
    
    
    ALTER TABLE author
    NO INHERIT emp;

That’s all about applying or removing table inheritance in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “table inheritance” allows us to create a hierarchy of tables, where one table(child) can inherit the structure and properties of another (parent) table. To perform table inheritance in PostgreSQL, the " **INHERITS** " keyword is used while inheriting the parent table. To remove the inheritance from a specific table, use the ALTER TABLE command with the “NO INHERIT” clause. This post has illustrated how to apply or remove table inheritance in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-do-table-inheritance-in-postgresql/)

---

# How to Add or Remove a UNIQUE Constraint on Multiple Columns of a Postgres Table

> In PostgreSQL, the “UNIQUE” keyword is used with the CREATE TABLE or ALTER TABLE commands to add a unique constraint on single/multiple columns of a new or an …

The **UNIQUE** constraint is a popularly used concept in PostgreSQL that helps us keep data precise, clean, and organized. It ensures the uniqueness/originality of the table records or values. By using the UNIQUE constraint on single or multiple columns, users can make sure that each value in those columns is unique and not repeated.

This post illustrates a comprehensive knowledge of adding or removing unique constraints from multiple columns.

 **How to Add a UNIQUE Constraint on Multiple Columns of a Postgres Table**

Postgres enables its users to add/create a UNIQUE Constraint on multiple columns of a Postgres table while table creation. For this purpose, all you have to do is, follow the syntax provided below:
    
    
    CREATE TABLE name_of_table(
    col_name_1 data_type,
    col_name_2 data_type,
    col_name_3 data_type,
    …
    col_name_N data_type,
    UNIQUE (col_name_1, col_name_2, …)
    );

Here, in the above-stated syntax:

\- “ **col_name_1, col_name_2, …, col_name_N** ” are the table columns to be created.  
\- data_type represents any valid Postgres data type, such as INT, TEXT, VARCHAR, etc.  
\- UNIQUE is a keyword that is used to apply the UNIQUE constraint on the table’s columns.  
\- The “col_name_1, col_name_2, …” that are enclosed within a set of parentheses represent the columns on which the unique constraint will be applied.

 **Example: Applying Unique Constraint on Multiple Columns**

Let’s create a “ **cp_employee** ” table and insert the unique constraint on a couple of its columns:
    
    
    CREATE TABLE cp_employee(
    emp_id INT,
    emp_name TEXT,
    emp_email VARCHAR,
    UNIQUE (emp_id, emp_email)
    );

The following snippet indicates that the “cp_employee” table has been created with the desired columns:

The UNIQUE constraint has been successfully applied to the “emp_id” and “emp_email” columns of the “cp_employee” table.

Let’s insert a couple of records to the newly created “cp_employee” table using the following command:
    
    
    INSERT INTO cp_employee(emp_id, emp_name, emp_email)
    VALUES (1, 'Joseph', 'joseph@abc.com'),
    (2, 'Henry', 'henry@abc.com');

The output snippet shows that two records have been successfully inserted into the “cp_employee” table:

Now let’s try to insert a duplicate record into the “cp_employee” table and see how the UNIQUE constraint deals with that particular situation:
    
    
    INSERT INTO cp_employee(emp_id, emp_name, emp_email)
    VALUES (1, 'Joseph', 'joseph@abc.com');

Inserting a duplicate record throws an error which indicates that the duplicate key value violates the unique constraint:

 **How to Add a UNIQUE Constraint on Multiple Columns of an Existing Postgres Table?**

Use the below-provided syntax to add/set a UNIQUE constraint on various columns of an existing PostgreSQL table:
    
    
    ALTER TABLE name_of_table
    ADD CONSTRAINT constraint_name UNIQUE (col_name_1, col_name_2, …);

Here, in the above-stated syntax:

\- “name_of_table” indicates an existing table that needs to be altered.  
\- “ADD CONSTRAINT” is a clause that applies uniqueness to the desired table columns.  
\- The “col_name_1, col_name_2, …” that are enclosed within a set of parentheses represent the columns on which the unique constraint will be applied.

 **Example: Applying UNIQUE Constraint on Existing Table**

We have an already existing table named “emp_info” having the following structure:
    
    
    \d emp_info;

Suppose we have to apply a UNIQUE constraint on the “emp_id” and “emp_name” columns. For that purpose, we will execute the ALTER TABLE command with the UNIQUE constraint as follows:
    
    
    ALTER TABLE emp_info
    ADD CONSTRAINT unique_constraints UNIQUE (emp_id, emp_name);

The selected table has been successfully altered:

Users can confirm the table alteration by executing the below-provided command:
    
    
    \d emp_info;

From the output, it is clear that the UNIQUE CONSTRAINT has been successfully applied to the selected columns.

 **How to Remove/DROP a UNIQUE Constraint From Multiple Columns of a PostgreSQL Table**

PostgreSQL uses the ALTER TABLE command with the DROP CONSTRAINT clause to remove/drop the uniqueness from single or multiple columns:
    
    
    ALTER TABLE name_of_table
    DROP CONSTRAINT name_of_constraint;

Replace the “name_of_table” with the desired table name and “name_of_constraint” with the constraint names that need to be removed.

 **Example: Removing Unique Constraint From Multiple Columns**

Let’s use the DROP CONSTRAINT clause with the selected constraint name to remove it from the “cp_employee” table:
    
    
    ALTER TABLE name_of_table
    DROP CONSTRAINT unique_constraints;

The unique constraint has been successfully removed from the multiple columns:

Execute the “\d” command with the table name to confirm the constraint deletion:
    
    
    \d emp_info;

The output indicates that the unique constraint has been successfully removed from the selected columns:

That’s all about adding or removing unique constraints on multiple columns of a PostgreSQL table.

 **Conclusion**

In PostgreSQL, the “UNIQUE” keyword is used with the CREATE TABLE or ALTER TABLE commands to add a unique constraint on single/multiple columns of a new or an already existing Postgres table. Moreover, PostgreSQL uses the ALTER TABLE command with the DROP CONSTRAINT clause to remove the uniqueness from single or multiple columns of the selected table. This post has illustrated how to add or remove UNIQUE constraints from multiple columns of a particular table.

---
[View this page online](https://www.commandprompt.com/education/how-to-add-or-remove-a-unique-constraint-on-multiple-columns-of-a-postgres-table/)

---

# How to Use the DENSE_RANK() Function in PostgreSQL

> The DENSE_RANK() function assigns a rank to each row of a partition based on the specified sorting order. It starts ranking from 1 for the first row and increa…

PostgreSQL offers several window functions with different functionalities. **DENSE_RANK()** is one such function that assigns a unique ranking to each row of a partition without leaving any gaps in the ranking order. It assigns consecutive/sequential ranks to the rows, even if they have the same values. However, rows/records having the same values receive the equal (same) rank.

This write demonstrates how to use DENSE_RANK Function in Postgres using the following outlines:

\- Applying DENSE_RANK() Function Over a Particular Table  
\- Applying DENSE_RANK() Function Over a Table Partitions

 **How to Use the DENSE_RANK() Function in PostgreSQL**

To use DENSE_RANK() function in Postgres, all you need to do is follow the syntax provided below:
    
    
    DENSE_RANK()
    OVER (
    [PARTITION BY partition_col_list]
    [ORDER BY order_col_list]
    )

In the above syntax, “ **[PARTITION BY partition_col_list]** ” is an optional clause that splits the result set into partitions based on columns specified in “ **partition_col_list** ”. However, if you don't use it, the stated function will consider the entire result set as one partition and ranks all the rows together as one single partition.

Let’s set up a sample table and practically implement the DENSE_RANK() function on that table.

 **Sample Table**

Let’s begin with creating a sample table named “student_details” that keeps the student details:
    
    
    CREATE TABLE student_details(
    st_id INT PRIMARY KEY,
    st_name TEXT,
    st_gender CHAR,
    st_grade INT NOT NULL
    );

Once the selected table is created, insert some new records into it using the following query:
    
    
    INSERT INTO student_details(st_id, st_name, st_gender, st_grade)
    VALUES (1, 'Alexa', 'F', 1),
    (2, 'Joseph', 'M', 1),
    (3, 'Daniel', 'M', 2),
    (4, 'Anna', 'F', 1),
    (5, 'Stephan', 'M', 2),
    (6, 'Alex', 'M', 3),
    (7, 'Stephenie', 'F', 3),
    (8, 'Clarke', 'M', 3),
    (9, 'Natalia', 'F', 2),
    (10, 'Joe', 'M', 2);

Let’s fetch the “student_details” table to confirm the inserted data:
    
    
    SELECT * FROM student_details;

 **Example 1: Applying DENSE_RANK() Function Over Entire Table**

In this example, we will apply the **DENSE_RANK()** function on the “student_details” table:
    
    
    SELECT *,
    DENSE_RANK() OVER (
    ORDER BY st_grade
    ) AS dense_rank
    FROM student_details;

In the above code:

\- The PARTITION BY Clause is skipped, so the DENSE_RANK() function will consider the entire table as one partition.  
\- Each partition will be sorted in default (ascending) order based on the “st_grade” column.  
\- The DENSE_RANK() function will assign the rank to each row/record based on the st_grade column:

The output demonstrates that the same rank is assigned to the students having the same grade.

 **Example 2: Applying DENSE_RANK() Function Over Table Partitions**

In this example, we will apply the **DENSE_RANK()** function on the table’s partition instead of the entire result set:
    
    
    SELECT *,
    DENSE_RANK() OVER (
    PARTITION BY st_gender
    ORDER BY st_grade
    ) AS dense_rank
    FROM student_details;

In the above code:

\- Partitions are created based on the “st_gender” column.  
\- Each partition will be sorted based on the “st_grade” column.  
\- The DENSE_RANK() function will retrieve the rank of each row/record within its associated partition:

The output demonstrates that the ranking restarts from 1 for the new partition.

 **Conclusion**

The **DENSE_RANK()** function assigns a rank to each row of a partition based on the specified sorting order. It starts ranking from 1 for the first row and increases the rank for each subsequent row. However, rows with identical values will have the same rank. Moreover, when the stated function meets a different partition, the ranking restarts from 1 for that new partition. This write-up has demonstrated various use cases of the DENSE_RANK() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-dense_rank-function-in-postgresql/)

---

# How to Create a Postgres Database From Command Line

> PostgreSQL supports various commands to create a database from the command line, including “createdb” and “CREATE DATABASE”.

Whenever someone starts working with Postgres or any other database, one of the very first things is to learn how to **create a database**. Creating a table allows a user to perform different database operations, such as table creation, data fetching from existing tables, modifying existing tables, and many more. Therefore, PostgreSQL offers various database creation methods, including GUI-based and CLI-based options.

This write-up illustrates the Postgres database creation using the command line.

 **How to Create a Postgres Database From Command Line**

We will explain the following methods to create a Postgres database using the command line:

\- Method 1: Using SQL Shell  
\- Method 2: Using Terminal

So, let’s get started with the default Postgres CLI.

 **How to Create PostgreSQL Using SQL Shell**

Postgres provides a default command line interface, known as “SQL Shell” or “psql”. It allows users to perform database operations using different commands and meta-commands. Follow the below-exhibited steps for a profound understanding:

 **Step 1: Launch psql**

Search for “psql” in the search menu and hit the “Open” button to launch the SQL Shell:

Upon doing so, the SQL Shell will open, provide the login details, and hit the “ENTER” button to access the Postgres:

 **Step 2: Check Available/Existing Databases**

Once you are successfully connected to the “postgres” database, use the following meta-command to check the list of available/existing databases:
    
    
    \l

 **Step 3: Create a Database Using Postgres Default CLI**

Use the below-demonstrated syntax for the database creation:
    
    
    CREATE DATABASE name_of_database;

Replace the “name_of_database” with the database name to be created. For instance, in the following snippet, the CREATE DATABASE command creates a new database named “smaple_db”:
    
    
    CREATE DATABASE smaple_database;

 **Step 4: Confirm Database Creation**

Type the “\l” command and hit the ENTER Key to confirm the database creation:
    
    
    \l

The following snippet verifies the creation of the desired database:

 **How to Create PostgreSQL Using SQL Shell**

Alternatively, users can execute the “ **createdb** ” command to create a database directly from the system’s terminal. For this purpose, use the below-demonstrated syntax:
    
    
    createdb [option...] [database_name [description]]

Here, the option can be “–help”, “-D”, “-E”, “-e”, “-h”, “-I”, “-O”, “-p”, “-T”, “-U”, “-w”, or “-W”. The use of these options/parameters relies on the users’ requirements. For instance, use the “-h” to show the server’s hostname, use -D to specify tablespace for the database, use “-O” to determine who owns the database, and so on.

Follow the below-exhibited steps for a profound understanding:

 **Step 1: Access Postgres’ Bin Directory**

Launch CMD and head into the Postgres bin directory by executing the “cd” command:
    
    
    cd C:\Program Files\PostgreSQL\15\bin

Here, “15” represents the Postgres version; replace it according to the Postgres version installed on your system:

 **Step 2: Create Database**

Type the “createdb” command and hit the “Enter” button to create a new database:
    
    
    createdb -U postgres sample1_database;

Here, the “-U” option is used to specify the user name to be used for the connection:

The cursor moves to the next line without throwing any error, which indicates the successful execution of the stated command.

 **Step 3: Confirm Database Creation**

Now open the SQL Shell, type the “\l” command, and hit the ENTER Key to confirm the database creation:
    
    
    \l

The createdb command confirms the successful creation of the desired database, i.e., “sample1_database”:

That’s all about creating a Postgres database from the command line.

 **Conclusion**

PostgreSQL supports various commands to create a database from the command line, including “createdb” and “CREATE DATABASE”. For instance, executing the “CREATE DATABASE” command from SQL Shell creates a new Postgres database, while executing the “createdb” command from the system’s terminal serves the same purpose. This post has illustrated a couple of methods to create a Postgres database from the command line.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-postgres-database-from-command-line/)

---

# How to use PostgreSQL NTILE Function

> The NTILE function is used to divide the rows of the table into groups provided by the users in the argument of the function called buckets in PostgreSQL.

PostgreSQL is a database server that allows the user to manage their huge pool of data by storing it in the form of tables and accessing that later. It enables the user to fetch data from the database using the SQL queries in the PostgreSQL database. It also allows the user to compare data inside the table by dividing the rows into multiple groups or partitions.

This guide will explain the process of using the NTILE function in PostgreSQL with the help of examples.

 **PostgreSQL NTILE Function Explained With Example**

The NTILE function is used to distribute the rows of the PostgreSQL table into a specified number of groups as equal in size as the table allows. If the data rows are not divisible by the number of groups then the function divides it into different sizes. Larger groups are placed before the smaller groups and the function divides the rows according to size provided by the user.

 **Syntax**

To use the NTILE function in the PostgreSQL database, use the syntax mentioned below:
    
    
    NTILE(buckets) OVER (
       [ORDER BY sort_expression [ASC | DESC], ...]
       )

The above code block depicts:

\- The code uses the **NTILE** keyword suggesting the name of the function and **buckets** as its argument to set the number of groups for the function.  
\- The **buckets** parameter determines the number of divisions a table will be partitioned into like 2 means that the table will be divided into 2 parts and so on.  
\- The **ORDER BY** clause is used to get the order of the tables using a **column** from the table and it is mandatory for using the **NTILE** function.  
\- The **PARTITION BY** clause is the optional part of the function which can be used to get groups based on the values of the column.

 **Example 1: How to Use NTILE Function in PostgreSQL?**

To use the NTILE function in PostgreSQL, simply create a table and insert data in it and then use the following query to access data from it:
    
    
    SELECT * FROM employee;

The following screenshot displays the data from the employee table in PostgreSQL:

Use the following code to divide the table using the **NTILE** function in the PostgreSQL database:
    
    
     SELECT name, gender, salary,
      NTILE(4) 
      OVER (ORDER BY salary) 
     FROM employee
     WHERE salary >= 5000;

The above code selects columns of the table and uses the **NTILE** function with 4 **buckets** to keep the data of the table in 4 parts. The code uses a **salary** column to order the table and it only divides the employees with **salary** more than **5000** :

The above screenshot displays that there are 6 employees earning 5000 or more and the NTILE function has divided the table into 4 groups. The first two groups have 2 rows and the last 2 only contain 1 row in it as the number of rows is not divisible by 4.

 **Example 2: PARTITION BY Clause in NTILE Function From PostgreSQL**

The following code uses the PARTITION BY clause in the NTILE function to make partitions in the employee table:
    
    
    SELECT name, gender, salary,
      NTILE(4) 
      OVER(PARTITION BY gender
       ORDER BY salary) 
     FROM employee;

The following screenshot displays that the NTILE function divides the table but separately as the PARTITION BY clause has already divided it into 2 parts. The Female has 4 rows so in this case each group contains a single value but Males were 6 in number so it divides the table as it was in the first example:

That’s all about using the NTILE function in the PostgreSQL table with the help of examples.

 **Conclusion**

To use the NTILE function in PostgreSQL, simply create a table and insert data in it to use the NTILE function on it. The NTILE function is used to divide the rows of the table in the form of buckets which will be mentioned in its arguments. Each bucket contains the number of rows from the PostgreSQL table and buckets with greater rows are placed above others. This guide has explained the process of using the NTILE function in the PostgreSQL table with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-postgresql-ntile-function/)

---

# How to Use JSON_ARRAY_ELEMENTS() Function in PostgreSQL

> The JSON_ARRAY_ELEMENTS() is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of values.

PostgreSQL provides a **JSON** array data type which is similar to standard arrays in programming. It helps us store ordered collections in JSON format. JSON arrays are enclosed within square brackets “[ ]” and can have different data types like strings, objects, numbers, etc. Postgres offers several functions to work with the JSON data, and **JSON_ARRAY_ELEMENTS()** is one of them.

This post illustrates the basic syntax and working of the JSON_ARRAY_ELEMENTS() function in Postgres using practical examples.

 **How to Use JSON_ARRAY_ELEMENTS() Function in PostgreSQL?**

The JSON_ARRAY_ELEMENTS() is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of values.

 **Syntax**

Use the below-stated syntax to retrieve an expanded set of specified JSON array elements:
    
    
    JSON_ARRAY_ELEMENTS(array JSON)

 **Parameters**

The stated function accepts a single argument “array” that must be a JSON array.

 **Return Value**

An expanded set that consists of given JSON array elements.

 **Return Type**

The data type of the expanded set values will be JSON.

 **Example 1: Using JSON_ARRAY_ELEMENTS() Function**

The below code snippet demonstrates the use of the JSON_ARRAY_ELEMENTS() function in Postgres:
    
    
    SELECT JSON_ARRAY_ELEMENTS('[100, 110, 90, [120, -12], [13, 14]]');

The stated function retrieves an expanded set that consists of the specified array elements:

 **Example 2: Using JSON_ARRAY_ELEMENTS() Function as a Temp Table**

The return type of the JSON_ARRAY_ELEMENTS function is “SETOF” which allows us to utilize it as a temporary table. For this purpose, we can execute the JSON_ARRAY_ELEMENTS() function with the “SELECT *” statement as follows:
    
    
    SELECT * 
    FROM JSON_ARRAY_ELEMENTS('[100, 110, 90, [120, -12], [13, 14]]');

On successful execution of the JSON_ARRAY_ELEMENTS() function, you will get the following output:

This is how the JSON_ARRAY_ELEMENTS() function works in PostgreSQL.

 **Conclusion**

The **JSON_ARRAY_ELEMENTS()** is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of values. The return type of the JSON_ARRAY_ELEMENTS function is “SETOF” which allows us to utilize it as a temporary table. This post has demonstrated the working of the JSON_ARRAY_ELEMENTS() in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-json_array_elements-function-in-postgresql/)

---

# How to Use/Execute PostgreSQL Query in Docker Container

> To execute PostgreSQL Query in Docker container, run Postgres container and interact with it. Then, connect to database server and execute PostgreSQL commands.

**PostgreSQL** is a widely used relational DBMS that is designed for efficiently storing, handling, and retrieving large amounts of data in an organized structure. Users can use PostgreSQL in Docker to easily create and manage the PostgreSQL database without installing it on the local host machine. Moreover, users can also use and execute the PostgreSQL queries in a Docker container.

This blog will illustrate the method to use/execute PostgreSQL queries in a Docker container.

 **How to Use/Execute PostgreSQL Query in Docker Container?**

To use/execute PostgreSQL Query in Docker container, try out the below-mentioned steps:

\- Download Postgres Docker Image  
\- Build and Run the Postgres Container  
\- Interact With Executing Container  
\- Establish a Connection With a Database Server  
\- Execute PostgreSQL Queries and psql Commands

 **Step 1: Download Postgres Docker Image**

Execute the below-provided “ **docker pull** ” command in Windows PowerShell to download the official Postgres image from the cloud repository (Docker Hub) to your local system:
    
    
    docker pull postgres

 **Step 2: Build and Run Postgres Container**

Create and run the Postgres container via the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command:
    
    
    docker run -d --name postgresCont -p 5432:5432 -e POSTGRES_PASSWORD=pass123 postgres

Here:

\- “ **-d** ” flag specifies that the container should execute in the background.  
\- “ **\--name** ” option assigns the container’s name, i.e., “ **postgresCont** ”.  
\- “ **-p** ” assigns the port for the container i.e. “ **5432:5432** ”.  
\- “ **-e POSTGRES_PASSWORD** ” configures the password to be “ **pass123** ”.  
\- “ **postgres** ” is the official Docker image:

Upon doing so, the Postgres container has been created and started.

 **Step 3: Interact With Executing Container**

Write out the “ **docker exec -it <cont-name> bash**” command and specify the executing Postgres container name to open the shell within it:
    
    
    docker exec -it postgresCont bash

Subsequently, the “ **PostgresCont** ” container has been accessed and now we can run commands in it.

 **Step 4: Establish a Connection With Database Server**

Execute the “psql” command along with the hostname and user name to make a connection with the Postgres Database Server:
    
    
    psql -h localhost -U postgres

As you can see, the SQL shell has been started successfully where we can execute/run PostgreSQL queries and psql commands.

 **Step 5: Execute PostgreSQL Queries and psql Commands**

Finally, execute the psql commands in the PostgreSQL container. For instance, we are executing the “ **\l** ” command to list available databases:
    
    
    \l

The below output shows the list of available databases:

Execute another psql command, such as the “ **CREATE DATABASE** ” command along with the database name to create a database. For instance, we are creating a database named “ **tsl_employee** ”:
    
    
    CREATE DATABASE tsl_employee;

The below output indicates that the database has been created successfully:

We have successfully used/executed PostgreSQL queries in a Docker container.

 **Conclusion**

To use/execute PostgreSQL Query in Docker container, first, download the Postgres Docker image. Then, build and run the Postgres container through the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command. Next, interact with the executing container and establish a connection with a database server using the “ **psql -h localhost -U postgres** ” command. Finally, execute PostgreSQL queries and psql commands. This blog has illustrated the method to use/execute PostgreSQL queries in a Docker container.

---
[View this page online](https://www.commandprompt.com/education/how-to-useexecute-postgresql-query-in-docker-container/)

---

# How to Check if the Upper Bound of the Given Range is Inclusive or Exclusive

> In PostgreSQL, the UPPER_INC() function accepts a range or multi-range as an argument and checks if the upper bound of the specified range is included in the r…

PostgreSQL offers a variety of built-in functions that are specifically designed for working with range types. These functions assist us in dealing with ranges efficiently. For instance, the lower_inc() function informs us if the lower bound is inclusive, the **upper_inc()** function checks if the upper bound of the specified range is inclusive, the upper() function retrieves the upper bound of the function, and so on.

This post illustrates how to check if the upper bound of the specified range is included or excluded.

 **How to Check if the Upper Bound of the Given Range is Inclusive or Exclusive**

In PostgreSQL, the UPPER_INC() function accepts a range or multi-range as an argument and checks if the upper bound of the specified range is included in the range or not.

 **Syntax**

Use the below-stated syntax to execute the UPPER_INC() function on the specified range:
    
    
    UPPER_INC(range | multirange);

 **Parameters**

This function accepts a single-range or multi-range value as an argument.

 **Return Type**

The return type of the UPPER_INC() function is Boolean.

 **Return Value**

It retrieves a True or False value which shows if the upper bound of the given range is inclusive or exclusive.

 **Example 1**

This example demonstrates how to use the **UPPER_INC()** function to check if the lower bound is included in the range or not:
    
    
    SELECT UPPER_INC(numrange'[0,10]')AS upper_bound_inclusive;

The output snippet shows “true” which indicates that the upper bound is included in the range:

 **Example 2**

Let’s try out another example for a better understanding of the UPPER_INC() function in Postgres:
    
    
    SELECT UPPER_INC(numrange'[0,10)')AS upper_bound_inclusive;

The output snippet shows “false” which indicates that the upper bound is not included in the range:

 **Example 3**

In the following example, the UPPER_INC() function is applied on the range “[5, 6)”:
    
    
    SELECT UPPER_INC(numrange'(5, 6]') AS upper_bound_inclusive;

The output snippet shows that the upper bound is included in the range:

This is how the UPPER_INC() function works in PostgreSQL.

 **Conclusion**

In PostgreSQL, the UPPER_INC() function accepts a range or multi-range as an argument and checks if the upper bound of the specified range is included in the range or not. The return type of the UPPER_INC() is Boolean. It retrieves a True or False value which shows if the upper bound of the given range is inclusive or exclusive. This post has demonstrated the various use cases of the UPPER_INC() function in PostgreSQL using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-if-the-upper-bound-of-the-given-range-is-inclusive-or-exclusive/)

---

# How to Find the Length of a JSON Array in PostgreSQL?

> In PostgreSQL, a built-in function named “JSON_ARRAY_LENGTH()” is used to determine the length of a JSON array.

PostgreSQL provides a **JSON** array data type that helps us store ordered collections in JSON format. JSON arrays are similar to standard arrays in programming. They are enclosed within square brackets “[ ]” and can have different data types like strings, objects, numbers, etc. JSON arrays are optimized for PostgreSQL's database engine.

This post illustrates a comprehensive guide to finding the length of the given JSON array.

 **How to Find/Fetch the JSON Array Length in Postgres?**

In Postgres, a built-in function named “ **JSON_ARRAY_LENGTH()** ” is used to calculate/determine the length of a JSON array. The retrieved length represents the total number of elements in that particular JSON array.

 **Syntax**

Use the below-stated syntax to retrieve the length of a JSON array using the JSON_ARRAY_LENGTH() function:
    
    
    JSON_ARRAY_LENGTH(array JSON);

 **Parameters**

The stated function accepts a single argument “array” that represents a JSON array.

 **Return Value**

The stated function retrieves the length of the given JSON array.

 **Return Type**

It retrieves an **INTEGER** value which indicates the length of the specified JSON array.

 **Example 1: Finding the Length of a JSON Array in Postgres**

The below code snippet demonstrates the use of the JSON_ARRAY_LENGTH() function in PostgreSQL:
    
    
    SELECT JSON_ARRAY_LENGTH('[100, 110, 90, [120, -12]]');

The stated function retrieves the length of the specified array:

 **Example 2: Finding the Length of a JSON Column in Postgres**

Let’s set up a sample table with the following structure:
    
    
    CREATE TABLE emp_table (
    emp_id SERIAL PRIMARY KEY,
    emp_data JSON
    );

Now execute the following query to insert new records into the “emp_table”:
    
    
    INSERT INTO emp_table(emp_data) 
    VALUES
    ('[100, 120, 30, 210, 1]'),
    ('["John", "Joseph", "Mike", "Johnson", "Miller"]'),
    ('[{"e_name": "John", "e_age": 28},
    {"e_name": "Johnson", "e_age": 32},
    {"e_name": "Joseph", "e_age": 27}]');

The desired records have been successfully inserted into the “emp_table”:

Confirm the table’s content by executing the following command:
    
    
    SELECT * FROM emp_table;

Now we will use the JSON_ARRAY_LENGTH() function to find the length of the “emp_data” column:
    
    
    SELECT emp_data, 
    JSON_ARRAY_LENGTH(emp_data)
    FROM emp_table;

The stated function successfully retrieves the length of the given JSON array:

That’s all about finding the length of a JSON array in Postgres.

 **Conclusion**

In Postgres, a built-in function named “ **JSON_ARRAY_LENGTH()** ” is used to determine the length of a JSON array. The retrieved length represents the total number of elements in that particular JSON array. The stated function accepts a single argument “array” which must be a JSON array. This post has illustrated the working of the JSON_ARRAY_LENGTH() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-the-length-of-a-json-array-in-postgresql/)

---

# How to Get PostgreSQL Server Start Time

> PostgreSQL offers a built-in “pg_postmaster_start_time()” function that provides the exact timestamp when the server was initiated.

PostgreSQL provides numerous Session Functions to control, monitor, and manage individual database sessions. Session functions help us monitor session details, manage session variables, and modify session behavior dynamically. While working with a Postgres database, a common task is retrieving the session start time, which can be done by executing the built-in " **pg_postmaster_start_time()** " function.

This post demonstrates how to get PostgreSQL server start time using suitable examples.

 **How to Get PostgreSQL Server Start Time**

PostgreSQL offers a built-in “ **pg_postmaster_start_time()** ” function that provides the exact timestamp when the server was initiated.

 **Syntax**

The pg_postmaster_start_time() has a very straightforward syntax that includes a SELECT keyword followed by the function name, as shown below:
    
    
    SELECT pg_postmaster_start_time();

 **Parameters**

The “ **pg_postmaster_start_time()** ” function doesn’t accept any argument and must be executed with a set of parentheses.

 **Return Value**

It retrieves a timestamp along with associated zone information which indicates the time when the server was initiated/started.

 **Return Type**

The stated function has a return type “ **TIMESTAMPTZ** ” or “ **TIMESTAMP With Time Zone** ”.

 **Example 1: Retrieving Postgres Server Start Time**

Let’s execute the pg_postmaster_start_time
    
    
    SELECT pg_postmaster_start_time() AS server_start_time;

The stated function retrieves the server start time in the following format: “YYYY-MM-DD HH-MM-SS.MS-TZ”:

Here, “2023” represents a year, “07” shows a month, “27” indicates a day, “17” represent hours, “23” denote minutes, “20” indicate “seconds”, “46319” represent milliseconds, and “07” describe the server’s time zone.

 **Example 2: ERROR:** **column "pg_postmaster_start_time" does not exist**

The stated function must be executed with a set of parentheses, otherwise a “column "pg_postmaster_start_time" does not exist” error will occur:
    
    
    SELECT pg_postmaster_start_time;

That’s all about getting the Postgres Server start time using the pg_postmaster_start_time() function.

 **Conclusion**

PostgreSQL offers a built-in “ **pg_postmaster_start_time()** ” function that provides the exact timestamp when the server was initiated. The “ **pg_postmaster_start_time()** ” function doesn’t accept any argument and must be executed with a set of parentheses. It retrieves a timestamp along with associated zone information which indicates the time when the server was initiated/started. This write-up has illustrated a detailed guide on retrieving the Postgres Server start time using the pg_postmaster_start_time() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-postgresql-server-start-time/)

---

# PostgreSQL JSON_ARRAY_ELEMENTS VS JSON_ARRAY_ELEMENTS_TEXT

> In PostgreSQL, the JSON_ARRAY_ELEMENTS() and the JSON_ARRAY_ELEMENTS_TEXT() functions are used to expand the top-level elements of the given JSON array into a …

PostgreSQL offers several built-in JSON functions to manipulate JSON data efficiently, such as **JSON_ARRAY_ELEMENTS_TEXT(), JSON_ARRAY_ELEMENTS()** , JSON_ARRAY_LENGTH(), and many more. All these functions serve a unique purpose and have different use cases.

This write-up illustrates a detailed comparison of the JSON_ARRAY_ELEMENTS_TEXT() and the JSON_ARRAY_ELEMENTS() functions in Postgres using the following content:

\- What Does JSON_ARRAY_ELEMENTS() do in Postgres?  
\- What Does JSON_ARRAY_ELEMENTS_TEXT() do in Postgres?  
\- PostgreSQL JSON_ARRAY_ELEMENTS VS JSON_ARRAY_ELEMENTS_TEXT

 **What Does JSON_ARRAY_ELEMENTS() Do in Postgres?**

The JSON_ARRAY_ELEMENTS() is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of values. Use the below-stated syntax to retrieve an expanded set of specified JSON array elements:
    
    
    JSON_ARRAY_ELEMENTS(array JSON);

 **What Does JSON_ARRAY_ELEMENTS_TEXT() Do in Postgres?**

The JSON_ARRAY_ELEMENTS_TEXT() is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of text values. Use the below-stated syntax to retrieve an expanded set of text values from the specified JSON array:
    
    
    JSON_ARRAY_ELEMENTS_TEXT(array JSON);

 **PostgreSQL JSON_ARRAY_ELEMENTS VS JSON_ARRAY_ELEMENTS_TEXT**

Both these functions are used to expand the top-level elements of the given JSON array into a set of values. The only distinction between these functions is that the JSON_ARRAY_ELEMENTS() function retrieves the expanded values in JSON type while the JSON_ARRAY_ELEMENTS_TEXT() function retrieves the same output in TEXT type.

Here is a side-by-side practical demonstration of these methods:
    
    
    SELECT JSON_ARRAY_ELEMENTS_TEXT('[100, 110, 90, [120, -12], [13, 14]]'),
    JSON_ARRAY_ELEMENTS_TEXT('[100, 110, 90, [120, -12], [13, 14]]');

The below snippet demonstrates that both functions generate the same output, with the only distinction being their return type:

That’s all about the difference between the JSON_ARRAY_ELEMENTS() and the JSON_ARRAY_ELEMENTS_TEXT() functions in PostgreSQL.

 **Conclusion**

In PostgreSQL, the JSON_ARRAY_ELEMENTS() and the JSON_ARRAY_ELEMENTS_TEXT() functions are used to expand the top-level elements of the given JSON array into a set of values. The only distinction between these functions is that the JSON_ARRAY_ELEMENTS() function retrieves the expanded values in JSON type while the JSON_ARRAY_ELEMENTS_TEXT() function retrieves the same output in TEXT type. This write has presented the difference between JSON_ARRAY_ELEMENTS and the JSON_ARRAY_ELEMENTS_TEXT functions using a practical example.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_array_elements-vs-json_array_elements_text/)

---

# Howthe LEAD Function Works in PostgreSQL

> The LEAD is a PostgreSQL function that can be used to get the values from the following row of the table using its parameters like expression, offset, etc.

In PostgreSQL, the user can store huge data in the form of tables and access it at any moment without any change to the data. With databases and tables, the user can manage big data easily and then fetch or access it using the SQL queries on the table. Getting useful insights from the tables enables the user to make better business or other decisions based on the data available for the business.

This guide will explain the working of the LEAD function in PostgreSQL.

 **How Does the LEAD Function Work in PostgreSQL?**

The LEAD is a built-in Window function that can be used in the PostgreSQL database to get data from the following/subsequent row of the current row. It uses the offset to get data from the next rows of the table to compare the values of multiple rows within the table.

 **Syntax**

The syntax of using the LEAD function in PostgreSQL is mentioned below:
    
    
    LEAD(expression [,offset [,default_value]]) 
       OVER (
      ORDER BY sort_expression [ASC | DESC]
    )

In the above code snippets:

\- The **LEAD** keyword suggests the name of the function and is followed by the list of its arguments.  
\- The **expression** argument is used to get the name of the column on which the **LEAD** function is to be applied.  
\- The **offset** parameter of the LEAD function sets the rows to lead from the current row.  
\- The last argument is the **default_value** which is optional and used to set the values for the rows that do not have any following rows.  
\- The **LEAD** function also uses the **ORDER BY** clause to set the order of the table and the **PARTITION BY** clause is an optional clause to divide the table into smaller parts.

 **Example 1: How to Use LEAD Function?**

This code is used to get the data from the **employee** table in PostgreSQL:
    
    
    SELECT * FROM employee;

The following screenshot displays the data stored in the **employee** table to apply the **LEAD** function on it:

The following code uses the LEAD function to compare the rows from the employee table:
    
    
    SELECT name,   gender, salary, 
      LEAD(salary, 2, -1) 
      OVER (ORDER BY salary) 
      AS Lead_1
     FROM employee;

The above code block selects the **name** , **gender** , and **salary** columns from the **employee** table to apply the **LEAD** function to it. The **LEAD** function is applied on the **salary** column with the **offset** of **2** and **default_value -1**. The LEAD function is ordered by the **salary** column and the resultant column will be named “ **Lead_1** ”:

The above screenshot displays the lead_1 function containing the values from 2 rows below their current row.

 **Example 2: PARTITION BY Clause With LEAD Function**

The following code uses the **LEAD** function with **PARTITION BY** clause in the **employee** table:
    
    
    SELECT name,   gender, salary,
      LEAD(salary, 2, -1) 
      OVER (PARTITION By   gender 
       ORDER BY salary) 
      AS Lead_1
     FROM employee;

The above code uses a **gender** column to partition the table to apply the **LEAD** function on the **salary** column:

That’s all about working the LEAD() function in PostgreSQL.

 **Conclusion**

To use the LEAD function in PostgreSQL, simply create a table and insert data into it and use the LEAD function with its parameters. Use the column name of the table on which the LEAD function will be used and the offset will determine the comparison of the number of following/subsequent rows. This guide has explained the process of using the LEAD function and its working in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-lead-function-works-in-postgresql/)

---

# How to Get the Name of the Current Schema in PostgreSQL

> In PostgreSQL, the “CURRENT_SCHEMA” and “CURRENT_SCHEMAS” functions are used to get the details of the current schema.

While working with the PostgreSQL database, identifying the appropriate schema name is crucial to access and manage the objects within that schema effectively. For this purpose, PostgreSQL offers a couple of methods, such as **CURRENT_SCHEMA** , and **CURRENT_SCHEMAS**. Moreover, users can obtain a list of all schemas using various commands and metacommands.

This post illustrates how to get the name of the current schema using the below-provided content:

\- Method 1: Using CURRENT_SCHEMA  
\- Method 2: Using CURRENT_SCHEMAS  
\- Bonus Tip: Get All Schemas

 **How to Get the Name of the Current Schema in Postgres Via CURRENT_SCHEMA Function?**

 **CURRENT_SCHEMA** is a built-in Postgres function that retrieves the current schema’s name. It doesn’t accept any argument and can be executed with or without parenthesis. In the following code snippet, we execute the CURRENT_SCHEMA function with and without parenthesis:
    
    
    SELECT CURRENT_SCHEMA, CURRENT_SCHEMA();

The output shows that the current schema name is “public”:

 **How to Get the Name of the Current Schema in PostgreSQL Using CURRENT_SCHEMAS Function?**

 **CURRENT_SCHEMAS** is a built-in Postgres function that retrieves the name of all schemas available on the currently valid search path. It retrieves the schemas with respect to their priority order. It accepts a Boolean value as its argument and returns the result accordingly. Passing the Boolean value “False” means excluding the implicit patterns while specifying the “True” value means including the implicit patterns.

 **Example 1: Using CURRENT_SCHEMAS With False Value**

In the following snippet, we execute the CURRENT_SCHEMAS function with a boolean value “FALSE”:
    
    
    SELECT CURRENT_SCHEMAS(FALSE);

Here is what the CURRENT_SCHEMAS() function retrieves on successful execution:

 **Example 2: Using CURRENT_SCHEMAS With True Value**

In the following snippet, we execute the CURRENT_SCHEMAS function with a boolean value “TRUE”:
    
    
    SELECT CURRENT_SCHEMAS(TRUE);

This time the stated function will retrieve all patterns (including implicit) on the currently valid path:

 **How to Get the Name of All Schemas in PostgreSQL?**

Use the “\dn” meta-command to get the name of all schemas available in your Postgres database:
    
    
    \dn

For more details on [getting the list of schemas](<https://www.commandprompt.com/education/how-to-list-schemas-in-postgresql/>), check out the following guide.

 **Conclusion**

In PostgreSQL, the “ **CURRENT_SCHEMA** ” and “ **CURRENT_SCHEMAS** ” functions are used to get the details of the current schema. The CURRENT_SCHEMA function retrieves the name of the current schema while the CURRENT_SCHEMAS function retrieves the name of all schemas available on the currently valid search path. Moreover, the “\dn” command can be used to get the names of all available schemas. This post has elaborated on various methods to get the name of the current schema in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-name-of-the-current-schema-in-postgresql/)

---

# What Does ISEMPTY() Function Do in PostgreSQL?

> In PostgreSQL, the ISEMPTY() is an in-built range function that accepts a range or multi-range as an argument and retrieves a TRUE or FALSE value.

PostgreSQL offers various inbuilt range functions for efficient manipulation of ranges. These functions serve specific purposes related to range types. For example, the **isempty()** function checks for an empty range, **lower_inc()** checks if the lower bound is inclusive, the **lower()** function returns the lower bound of the range, and so on.

This write-up illustrates a complete guide on the usage of the ISEMPTY() function in PostgreSQL.

 **What Does ISEMPTY() Function Do in PostgreSQL?**

In PostgreSQL, the ISEMPTY() is an in-built range function that accepts a range or multi-range as an argument and retrieves a TRUE or FALSE value. The TRUE values state that the given range is empty while the FALSE value indicates that the specified range/multi-range is not empty.

 **Syntax**

Use the below-stated syntax to check if the given range/multi-range is empty or not:
    
    
    ISEMPTY(range | multirange);

 **Parameters**

The stated function accepts a single-range or multi-range value as an argument.

 **Return Value**

It retrieves a True or False value which shows if the given range is empty or not.

 **Return Type**

The return type of the stated function is Boolean.

 **Example 1**

In the following example, the ISEMPTY() function is applied to a specific range to check if it is empty or not:
    
    
    SELECT ISEMPTY('(2, 4]'::int4range);

Here in the above example,

\- The “(2, 4]” represents a range that contains the integer values between the following range “> 2” and “<= 4”.  
\- The "::int4range" is used to explicitly specify that the given range is of INTEGER data type.

The stated function retrieves “false”, which means the given range is not empty.

 **Example 2**

In the following example, the ISEMPTY() function is applied to a specific range to check if it is empty or not:
    
    
    SELECT ISEMPTY('(2, 3)'::int4range);

Here in the above example,

\- The “(2, 3)” represents a range that contains the integer values between the following range “> 2” and “<3”.  
\- The ISEMPTY() function will return true as output because there are no integer values between 2 (exclusive) and 3 (exclusive) in the specified range.

The “true” value in the output demonstrates that the specified range is empty.

 **Conclusion**

In PostgreSQL, the ISEMPTY() is an in-built range function that accepts a range or multi-range as an argument and retrieves a TRUE or FALSE value. The TRUE values state that the given range is empty while the FALSE value indicates that the specified range/multi-range is not empty. This post has illustrated a couple of use cases of the ISEMPTY() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/what-does-isempty-function-do-in-postgresql/)

---

# How to Expand a Multi Range Into a Set of Range Values in PostgreSQL

> In PostgreSQL, the UNNEST() function is used with a valid multirange type such as “int4multirange”, “tstzmultirange”, etc., to expand multi-range values into a…

PostgreSQL supports various built-in range data types that indicate a span between two different values. It lets us store and manipulate a set of values for different data types like integers, floating point numbers, dates, etc. Moreover, Postgres offers various built-in functions to work with the range types efficiently. This write-up will illustrate one such function named “UNNEST()” that expands a multi-range into a set of range values.

 **How to Expand a Multi Range Into a Set of Range Values in PostgreSQL?**

Use the **UNNEST()** function along with the “ **::int4multirange** ” type to expand multi-range integers into a set of range values in Postgres. Similarly, other range types like “tstzmultirange”, “datemultirange”, etc., can also be used with the UNNEST() function to expand the multi-range values into a set of values (of that particular range type).

 **Syntax**

Use the below-stated syntax to execute the UNNEST() function on the specified multi-range:
    
    
    UNNEST(multirange ::int4multirange)

 **Parameters**

It accepts a valid multi-range as an argument.

 **Return Value**

The UNNEST() function returns an expanded set of range values which are sorted in ascending order.

Let’s implement the UNNEST() function practically for a profound understanding.

 **Example 1: Using UNNEST() Function on Multi-range**

The following example utilizes the UNNEST() function to expand the specified multi-range into a set of values:
    
    
    SELECT UNNEST('{(11, 31), [100, 200], [50,71]}'::int4multirange);

The output snippet demonstrates that the UNNEST() function retrieves the expanded set of values in ascending order:

 **Example 2: Using UNNEST() Function on Multi-range Dates**

In the following example, the UNNEST() function is executed with the “datemultirange” type to expand the specified multi-range dates into a set of values:
    
    
    SELECT UNNEST('{("2020-01-01", "2020-01-15"), 
     ["2020-12-20", "2021-03-15"], 
     ["2022-01-12", "2022-02-12"]}'::datemultirange);

The stated function retrieves a set of sorted values as follows:

This is how the UNNEST() function works on range types/values in PostgreSQL.

 **Conclusion**

In PostgreSQL, the **UNNEST()** function is used along with a valid multirange type such as “ **int4multirange** ”, “ **tstzmultirange** ”, “ **datemultirange** ”, etc., to expand multi-range values into a set of range values in Postgres. The UNNEST() function returns an expanded set of range values which are sorted in ascending order. This post has demonstrated a couple of use cases of the UNNEST() function in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-expand-a-multi-range-into-a-set-of-range-values-in-postgresql/)

---

# How to Check if the Lower Bound of the Given Range is Inclusive or Not

> In PostgreSQL, the LOWER_INC() function accepts a range or multi-range as an argument and checks if the lower bound of the specified range is inclusive or excl…

PostgreSQL supports several useful built-in functions designed to work with range types. These functions help us handle ranges more efficiently. For example, the **lower_inc()** tells us if the lower bound is included, and **lower()** gives us the lowest value in the range, the **upper_inc()** checks if the upper bound of the specified range is included, and so on.

This post illustrates how to check if the lower bound of the specified range is inclusive or not.

 **How to Check if the Lower Bound of the Given Range is Inclusive or Not?**

In PostgreSQL, the LOWER_INC() function accepts a range or multi-range as an argument and checks if the lower bound of the specified range is inclusive or exclusive.

 **Syntax**

Use the below-stated syntax to execute the LOWER_INC() function on the specified range:
    
    
    LOWER_INC(range | multirange);

 **Parameters**

This function accepts a single-range or multi-range value as an argument.

 **Return Type**

The return type of LOWER_INC() is Boolean.

 **Return Value**

It retrieves a True or False value which shows if the lower bound of the given range is inclusive or exclusive.

 **Example 1**

This example illustrates how to use the **LOWER_INC()** function to check if the lower bound is included or excluded:
    
    
    SELECT LOWER_INC('[0, 10]'::int4range) AS lower_bound_inclusice;

The output snippet shows “true” which indicates that the lower bound is included in the range:

 **Example 2**

Let’s try out another example for a better understanding of the LOWER_INC() function in Postgres:
    
    
    SELECT LOWER_INC('(5, 5)'::int4range) AS lower_bound_inclusice;

The output snippet shows “false” which indicates that the lower bound is not included in the range:

 **Example 3**

In the following example, the LOWER_INC() function is applied on the range “[5, 6)”:
    
    
    SELECT LOWER_INC('[5, 6)'::int4range) AS lower_bound_inclusice;

The output snippet shows that the lower bound is included in the range:

This is how the LOWER_INC() function works in PostgreSQL.

 **Conclusion**

In PostgreSQL, the LOWER_INC() function accepts a range or multi-range as an argument and checks if the lower bound of the specified range is inclusive or exclusive. The return type of the LOWER_INC() is Boolean. It retrieves a True or False value which shows if the lower bound of the given range is inclusive or exclusive. This post has demonstrated the various use cases of the LOWER_INC() function in PostgreSQL using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-if-the-lower-bound-of-the-given-range-is-inclusive-or-not/)

---

# Understanding Array Functions

> PostgreSQL supports various built-in array functions, such as ARRAY_PREPEND(), ARRAY_CAT(), etc., to deal with the array&#x27;s data efficiently.

PostgreSQL is a commonly used relational database that supports the **ARRAY** data type to store the data of the same type in consecutive blocks of memory. To deal with the array's data efficiently, Postgres supports a variety of built-in functions, such as ARRAY_PREPEND(), ARRAY_CAT(), etc. Each of these array functions has distinct objectives/functionality.

This post will discuss the below-stated array functions in PostgreSQL:

\- ARRAY_APPEND()  
\- ARRAY_PREPEND()  
\- ARRAY_CAT()  
\- ARRAY_REPLACE( )  
\- ARRAY_REMOVE( )

 **PostgreSQL ARRAY_APPEND() Function**

ARRAY_APPEND() is one of the most frequently used array functions that append a new element at the end of an array using the following syntax:
    
    
    ARRAY_APPEND(array, new_element);

Here, "new_element" represents the element you want to add, and "array" represents the array where you want to append the new element.

 **Example: Applying ARRAY_APPEND**

The following example uses the “ARRAY_APPEND()” function to insert “.com” element at the end of the array:
    
    
    SELECT ARRAY_APPEND(ARRAY['Welcome', 'to', 'commandprompt'], '.com');

The output illustrates that the desired element has been successfully appended/inserted at the end of the provided array:

Follow our dedicated guide on how to use [ARRAY_APPEND()](<https://www.commandprompt.com/education/postgresql-array_append-function-with-examples/>) function to learn more about it.

 **PostgreSQL ARRAY_PREPEND() Function**

The **ARRAY_PREPEND()** function works in a contrary manner to the ARRAY_APPEND() function. It adds/inserts a new element at the beginning of an array by utilizing the below-provided syntax:
    
    
    ARRAY_PREPEND(new_element, array);

Here, "new_element" represents the element you want to add, and "array" represents the array where you want to prepend the new element.

 **Example: Applying ARRAY_PREPEND**

The following example uses the “ARRAY_PREPEND()” function to append “Hello” at the start of the array:
    
    
    SELECT ARRAY_PREPEND('Hello', ARRAY['Welcome', 'to', 'commandprompt']);

The output displays that the provided element has been inserted at the start of the given array:

 **PostgreSQL ARRAY_CAT() Function**

As the name itself describes, the “ARRAY_CAT()” function concatenates/combines given arrays and retrieves a single array:
    
    
    SELECT ARRAY_CAT(array_1, array_2);

Here, the “array_1” and “array_2” are the arrays to be combined.

 **Example: Applying ARRAY_CAT()**

The following example code concatenates two TEXT-type arrays:
    
    
    SELECT ARRAY_CAT(ARRAY['Hello', '!!!'], ARRAY['Welcome', 'to', 'commandprompt']);

The given arrays have been successfully concatenated:

For more details, check out the following guide on concatenating multiple arrays using [ARRAY_CAT()](<https://www.commandprompt.com/education/array_cat-function-in-postgresql/>) function.

 **PostgreSQL ARRAY_REPLACE() Function**

PostgreSQL allows us to replace an element in an array by specifying the “new element” and the “element to be replaced” in the **ARRAY_REPLACE** function. Here is a simple syntax that will allow you to comprehend this function better:
    
    
    ARRAY_REPLACE(array, existing_element, new_element);

The “new_element” will replace all the occurrences of the “existing_element”.

 **Example: Applying ARRAY_REPLACE() Function**

In the provided example code, the “Hello” element will be replaced with the “Hi”:
    
    
    SELECT ARRAY_REPLACE(ARRAY['Hello', 'Welcome', 'to', 'commandprompt'], 'Hello', 'Hi!');

The selected element has been successfully replaced with the desired element:

For more details, check our detailed guide on [ARRAY_REPLACE()](<https://www.commandprompt.com/education/array_replace-function-in-postgresql/>) Function in PostgreSQL.

 **PostgreSQL ARRAY_REMOVE() Function**

Use the ARRAY_REMOVE() function to remove/delete all the occurrences of any unwanted elements from a particular array:
    
    
    ARRAY_REMOVE(array, element);

Here, the element represents any array element that needs to be deleted/removed.

 **Example: Applying the ARRAY_REMOVE Function**

The following example utilizes the ARRAY_REMOVE() function to remove an element “Hello” from the given array:
    
    
    SELECT ARRAY_REMOVE(ARRAY['Hello', 'Welcome', 'to', 'commandprompt', 'Hello'], 'Hello');

The ARRAY_REMOVE() function has successfully removed all the occurrences of the “Hello” element from the provided array:

Check out the following guide to learn various use cases of the [ARRAY_REMOVE()](<https://www.commandprompt.com/education/array_remove-function-in-postgresql/>) function in PostgreSQL.

 **Conclusion**

PostgreSQL supports various built-in array functions, such as **ARRAY_PREPEND()** , **ARRAY_CAT()** , etc., to deal with the array's data efficiently. Each of these array functions offers distinct objectives/functionality. This guide has elaborated on some of the most frequently used array functions along with their basic syntax and suitable examples.

---
[View this page online](https://www.commandprompt.com/education/understanding-array-functions/)

---

# How Does PostgreSQL LAG() Function Work?

> The LAG() function in PostgreSQL is an SQL function that can be used to get the values from the previous row of the table using its parameters.

PostgreSQL is the relational database to store and manage structured data as millions of users are working on it daily. PostgreSQL provides the user with the SQL query language which can be used to access data from the database and get useful insights from it. It can also be used to manipulate the data from multiple relations or different rows from the same relation to get a better understanding of the data.

This guide will explain the LAG() function in PostgreSQL and the process of using it with examples.

 **How Does PostgreSQL LAG() Function Work**

PostgreSQL uses Structured Query Language or SQL to fetch or manipulate data from the database to learn about the data. LAG() is a function used in the SQL language that can be used to fetch data from the previous row with respect to the provided offset value. It is a Windows function available that enables the user to compare the values of the current row and the previous row.

 **Syntax**

Use the following syntax of the LAG() function in PostgreSQL as mentioned and explained below:
    
    
    LAG(expression [,offset [,default_value]]) 
       OVER (
      [ORDER BY sort_expression [ASC | DESC]]
       )

The above code suggests:

\- The **LAG** keyword is used to specify the name of the function and then its argument list is mentioned in the small parentheses.  
\- The argument list of the **LAG()** function contains the “ **expression** ”, “ **offset** ”, and “ **default_value** ” where only the **expression** is mandatory, else are optional.  
\- The **expression** parameter specifies the **column name** or **subquery** which is evaluated against the previous row at a specific **offset**.  
\- The **offset** is used to specify the number of rows to return and its **default** value is **1** if not provided.  
\- The **default_value** is used to set the default value to return if the value is out of scope.  
\- After setting the **LAG()** function parameters, simply the **ORDER BY** function is used to get the resultant table in sorted order using a specific **column** or **field**.  
\- The **PARTITION BY** clause is an optional one that is used to divide the rows into parts on which the function is applied.

 **Example 1: How to Use LAG() Function?**

To use the LAG() function in the PostgreSQL database, simply create a table or use the existing one(if any). This guide has used an already created “employee” table to illustrate the use of the LAG() function in Postgres:
    
    
    SELECT * FROM employee;

Using the above command, the selected table has been displayed on the screen:

Apply the LAG() function on the above table using the following query:
    
    
    SELECT name, salary, gender,
      LAG(salary, 1, -1) 
      OVER (ORDER BY salary) 
      AS Lag_1
     FROM employee;

The above query selects the columns from the **employee** table to apply the **LAG()** function with **salary** as its expression with **1** as offset, and **-1** as its default_value. The above query uses the **salary** column to order the table and the resultant column will be named “ **Lag_1** ”:

The above screenshot displays that the **Lag_1** column shows the salary of the previous row and the first cell contains the **default_value**.

 **Example 2: How to Use PARTITION BY Clause in LAG() Function?**

The **LAG()** function can also be used with the **PARTITION BY** function as the following snippet contains the code:
    
    
    SELECT name, salary, gender,
      LAG(salary, 1, -1) 
      OVER (PARTITION By gender 
       ORDER BY salary) 
      AS Lag_1
     FROM employee;

The above code adds the **PARTITION BY** clause in the previous example to divide the **gender** field into parts according to its values:

The above screenshot divides the resultant values in **Female** and **Male** from the **gender** column and then **orders** it using the **salary** column. The LAG() function resets its value when a new partition is reached.

That’s all about the LAG() function in PostgreSQL using examples.

 **Conclusion**

To use the LAG() function in the PostgreSQL table, simply create a table in PostgreSQL to get the values of the previous rows from the table. The LAG() function contains three parameters including the expression, offset, and default_values, and retrieves the result accordingly. The LAG() function uses the ORDER BY clause to sort the table and the PARTITION BY clause is optional and can be used to divide the result set into parts. This post demonstrated the process of using the LAG() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-does-postgresql-lag-function-work/)

---

# How to Get the Name of a Current Database in PostgreSQL

> In Postgres, a couple of built-in methods, such as CURRENT_CATALOG, and CURRENT_DATABASE are used to get the names of the current database.

While working with the PostgreSQL database, identifying the database name is an important task as it enables us to access and manage that particular database. For this purpose, PostgreSQL offers a couple of methods, such as **CURRENT_CATALOG** , and **CURRENT_DATABASE**. Moreover, users can get a list of all databases using different commands and metacommands.

This post illustrates how to get the name of the current database using the following content:

\- Method 1: Using CURRENT_CATALOG  
\- Method 2: Using CURRENT_DATABASE  
\- Bonus Tip: Get All Databases’ Names

 **How to Get Current Database Name in PostgreSQL Using CURRENT_CATALOG?**

In SQL standard database management systems, databases are commonly known as “ **catalogs** ”. To get the name of current catalogs/databases, the CURRENT_CATALOG function is used in PostgreSQL. It doesn’t accept any argument and can be executed without parenthesis, as shown in the following example:
    
    
    SELECT CURRENT_CATALOG;

 **How to Get Current Database Name in PostgreSQL Using CURRENT_DATABASE?**

Alternatively, the **CURRENT_DATABASE** function can be utilized in PostgreSQL to get the name of current catalogs/databases. It doesn’t accept any argument and must be executed with parenthesis, as depicted in the following example:
    
    
    SELECT CURRENT_DATABASE();

 **Bonus Tip: How to Get All Databases’ Names in Postgres**

Execute the “\l” meta-command to list all the databases’ names along with their attributes/details, such as database name, owner, etc.
    
    
    \l

That’s all about getting the names of the current or all databases in PostgreSQL.

 **Conclusion**

In Postgres, a couple of built-in methods, such as **CURRENT_CATALOG** , and **CURRENT_DATABASE** are used to get the names of the current database. Moreover, users can get the names of all databases using different commands and metacommands. This post has presented different methods to get the names of current or all databases in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-name-of-a-current-database-in-postgresql/)

---

# JSON_ARRAY_ELEMENTS_TEXT() Function in PostgreSQL

> The JSON_ARRAY_ELEMENTS_TEXT() is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of text value…

PostgreSQL offers a JSON array data type, similar to standard arrays in programming, which enables the storage of ordered collections in JSON format. Postgres provides numerous functions to manipulate JSON data, including **JSON_ARRAY_ELEMENTS_TEXT()** , JSON_ARRAY_LENGTH(), JSON_ARRAY_ELEMENTS(), and many more.

This post illustrates the basic syntax and working of the JSON_ARRAY_ELEMENTS() function in Postgres using practical examples.

 **How to Use JSON_ARRAY_ELEMENTS_TEXT() Function in PostgreSQL?**

The JSON_ARRAY_ELEMENTS_TEXT() is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of text values.

 **Syntax**

Use the below-stated syntax to retrieve an expanded set of text values from the specified JSON array:
    
    
    JSON_ARRAY_ELEMENTS_TEXT(array JSON);

 **Parameters**

The stated function accepts a single argument “array” that must be a JSON array.

 **Return Value**

An expanded set that consists of given JSON array elements in the form of TEXT.

 **Return Type**

The data type of the expanded set values will be TEXT.

 **Example 1: Using JSON_ARRAY_ELEMENTS_TEXT() Function**

The below code snippet demonstrates the use of the JSON_ARRAY_ELEMENTS_TEXT() function in Postgres:
    
    
    SELECT JSON_ARRAY_ELEMENTS_TEXT('[100, 110, 90, [120, -12], [13, 14]]');

The stated function retrieves an expanded set that consists of the specified array elements as TEXT:

 **Example 2: Using JSON_ARRAY_ELEMENTS() Function as a Temp Table**

The return value of the JSON_ARRAY_ELEMENTS_TEXT() function is of type “SETOF” which allows us to utilize it as a temporary table. To do this, we can execute the JSON_ARRAY_ELEMENTS_TEXT() function with the “SELECT *” statement as follows:
    
    
    SELECT * 
    FROM JSON_ARRAY_ELEMENTS_TEXT('[100, 110, 90, [120, -12], [13, 14]]');

On successful execution, the JSON_ARRAY_ELEMENTS_TEXT() function will retrieve the following output:

This is how the JSON_ARRAY_ELEMENTS_TEXT() function works in PostgreSQL.

 **Conclusion**

The **JSON_ARRAY_ELEMENTS_TEXT()** is a built-in JSON function that accepts a JSON array as an argument and expands its top-level elements into a set of text values. The return value of the JSON_ARRAY_ELEMENTS_TEXT() function is of type “SETOF” which allows us to utilize it as a temporary table. This post has demonstrated the working of the JSON_ARRAY_ELEMENTS_TEXT() in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/json_array_elements_text-function-in-postgresql/)

---

# How to Run PostgreSQL and pgAdmin Using Docker

> To run PostgreSQL and pgAdmin using Docker, download Postgres and pgAdmin4 images from Docker Hub. Then, build and start the Postgres and pgAdmin4 containers.

**PostgreSQL** is a widely used relational DBMS that stores, handles, and retrieves large amounts of data in an organized structure. **pgAdmin** is a free graphical user interface tool for organizing and creating databases. It is a feature-rich tool for managing the PostgreSQL database. It enables users to establish connections and easily switch between databases. Moreover, it supports numerous OS and PostgreSQL versions.

This blog will illustrate the procedure to set up/run PostgreSQL and pgAdmin with Docker.

 **How to Set Up/Run PostgreSQL and pgAdmin With Docker?**

To set up/run PostgreSQL and pgAdmin using Docker, look at the below-mentioned steps:

\- Pull/Download Postgres Docker Image  
\- Start and Run Postgres Container  
\- Pull/Download pgAdmin4 Docker Image  
\- Build and Run pgAdmin4 Container  
\- Verify Executing Containers  
\- Access pgAdmin4 on Browser  
\- Establish a Connection Between pgAdmin and Docker Postgres Instance

 **Step 1: Pull/Download Postgres Docker Image**

Execute the below-provided “ **docker pull** ” command in Windows PowerShell to download the official Postgres image from the cloud repository (Docker Hub) to your local system:
    
    
    docker pull postgres

 **Step 2: Start and Run Postgres Container**

To create and run the Postgres container, utilize the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command:
    
    
    docker run --name   my-pgadmin -p 82:80 -e 'PGADMIN_DEFAULT_EMAIL=laiba@yahoo.com' -e 'PGADMIN_DEFAULT_PASSWORD=pass123' -d dpage/pgadmin4

Here:

\- “ **-d** ” flag specifies that the container should execute in the background.  
\- “ **\--name** ” option is used to assign the name for the container i.e. “ **postgresCont** ”.  
\- “ **-p** ” assigns the port for the container i.e. “ **5432:5432** ”.  
\- “ **-e POSTGRES_PASSWORD** ” configures the password to be “ **pass123** ”.  
\- “ **postgres** ” is the official Docker image:

This command has built and created the Postgres container.

 **Step 3: Pull/Download pgAdmin4 Docker Image**

Run the below-listed command to download the “pgAdmin4” image in the local repository:
    
    
    docker pull dpage/pgadmin4

 **Step 4: Build and Run pgAdmin4 Container**

To build and execute the pgAdmin4 container, type out the “ **docker run --name <cont-name> -p 82:80 -e 'PGADMIN_DEFAULT_EMAIL=<email>' -e 'PGADMIN_DEFAULT_PASSWORD=<password>' -d dpage/pgadmin4**” command:
    
    
    docker run --name my-pgadmin -p 82:80 -e 'PGADMIN_DEFAULT_EMAIL=laiba@yahoo.com' -e 'PGADMIN_DEFAULT_PASSWORD=pass123' -d dpage/pgadmin4

Here:

\- “ **my-pgadmin** ” is the container’s name.  
\- “ **-p** ” assigns the port for the container i.e. “ **82:80** ”.  
\- “ **-e PGADMIN_DEFAULT_EMAIL** ” sets the default email to be “ **laiba@yahoo.com** ”.  
\- “ **-e PGADMIN_DEFAULT_PASSWORD** ” configures the password to be “ **pass123** ”.  
\- “ **dpage/pgadmin4** ” is the official Docker image:

This command has created and started the pgAdmin4 container.

 **Step 5: Verify Executing Containers**

Ensure that the PostgreSQL and pgAdmin4 containers are executing via provided command:
    
    
    docker ps

It can be observed that both containers are running efficiently.

 **Step 6: Access pgAdmin4 on Browser**

Now, navigate to <http://localhost:82/> to access the pgAdmin4 interface and provide the required login credentials that we have configured in the previous step:

Upon doing so, it will redirect us to the dashboard:

This indicates that PostgreSQL and pgAdmin4 have been successfully installed using Docker.

 **Step 7: Establish a Connection Between pgAdmin and Docker Postgres Instance**

Right-click on the “ **Servers** ” option, then select the “ **Register** ” option to add the new server:

After that, in the “ **General** ” menu, specify the name of the server. For instance, we have named it “ **PostgreSQL** ”:

Next, set the hostname or address, port, username, and password in the “ **Connection** ” menu and click on the “ **Save** ” button:

Upon doing so, the connection between the pgAdmin and Postgres container instance will be established. Now, users can use and access PostgreSQL:

We have efficiently explained the method to run PostgreSQL and pgAdmin using Docker.

 **Conclusion**

To set up/run PostgreSQL and pgAdmin using Docker, download the official Postgres and pgAdmin4 images from Docker Hub. Then, build and start the Postgres and pgAdmin4 containers. Next, verify the executing containers. After that, access pgAdmin4 on the browser and establish a connection between pgAdmin and the Docker Postgres instance. This blog has illustrated the procedure to set up/run PostgreSQL and pgAdmin with Docker.

---
[View this page online](https://www.commandprompt.com/education/how-to-run-postgresql-and-pgadmin-using-docker/)

---

# How to Use NTH_VALUE Function in PostgreSQL

> The NTH_VALUE function in PostgreSQL is used to get the Nth_value from the table using the column and offset to set the value from the column.

PostgreSQL database is used to store and manage huge data in tabular form to access it at any moment in the future. It allows the user to get an understanding of big data and its efficient manageability using the Relational Database Management System. The user can apply different functions to get better results from the PostgreSQL database.

This post demonstrates the process of using the NTH_VALUE function in PostgreSQL.

 **How to Use NTH_VALUE Function in PostgreSQL?**

The NTH_VALUE function gets the nth row or data in the nth row of the table in the PostgreSQL Database Management System. The user can get the data in the ordered partition using the NTH_VALUE function and the result set will contain the Nth value of the table.

 **Syntax**

To use the NTH_VALUE function in the PostgreSQL table, simply use the following syntax:
    
    
    NTH_VALUE(field_name, offset) 
       OVER (
      [ORDER BY sort_expression [ASC | DESC]]
       )

The above code suggests:

\- The **NTH_VALUE** keyword is used to call the function in PostgreSQL with its **parameters** list like **expression** and **offset**.  
\- The **expression** is the column name and the **offset** will be used to get the value of the Nth row.  
\- The **ORDER BY** clause in the **NTH_VALUE** function uses the sort_expression to get the result in order using the column from the table.  
\- The **PARTITION BY** clause is the optional one that can be used to divide the table using the values of the column.

 **Example 1: Use NTH_VALUE Function in PostgreSQL**

To use the NTH_VALUE function in PostgreSQL, simply run the following command to get the data from the employee table:
    
    
    SELECT * FROM employee;

The following screenshot displays the data from the employee table:

The following code uses the NTH_VALUE function in the **employee** table from the PostgreSQL database:
    
    
    SELECT name, gender, salary,
      NTH_VALUE(name, 3) 
      OVER(ORDER BY salary
       RANGE BETWEEN 
      UNBOUNDED PRECEDING AND 
      UNBOUNDED FOLLOWING
       )
     FROM employee;

The above code contains the **NTH_VALUE** function in the PostgreSQL table with its arguments like **column name** and **offset**. The code selects the columns from the **employee** table and gets the Nth-value from the **name column** and the resultant column will be **ordered** by the **salary** column:

The above code displays the 3rd value from the name which is “ **Joe** ”.

 **Example 2: PARTITION BY Clause in NTH_VALUE Function**

The following code uses the PARTITION BY clause with the NTH_VALUE function in PostgreSQL:
    
    
    SELECT name, gender, salary,
      NTH_VALUE(name, 3) 
      OVER(PARTITION BY gender
       ORDER BY salary
       RANGE BETWEEN 
      UNBOUNDED PRECEDING AND 
      UNBOUNDED FOLLOWING
       )
     FROM employee;

The above code uses the PARTITION BY clause to divide the table using the gender column and salary will be the ordering column from the employee table:

That’s all about using the NTH_VALUE function in PostgreSQL with the help of examples.

 **Conclusion**

To use the NTH_VALUE function in the PostgreSQL table, simply create and insert data in the table and apply the NTH_VALUE function to it. It uses the argument list including the column name and offset for setting the Nth_value of the column value. The function allows the use of the PARTITION BY clause to divide the table into smaller parts to apply the NTH_VALUE Function. This post demonstrated the process of using the NTH_VALUE function in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-nth_value-function-in-postgresql/)

---

# How to Install PostgreSQL Using Docker Compose

> To install PostgreSQL using Docker Compose, specify the desired services in compose file. Then, start the compose service to build and run Postgres container.

**PostgreSQL** is a widely used relational DBMS that is designed to efficiently store, handle, and retrieve large amounts of data in a structured manner. **Docker Compose** is a tool that enables users to define and run multiple container applications with the help of a YAML file. Users can easily install PostgreSQL by utilizing Docker Compose.

This write-up will illustrate the process of installing PostgreSQL using Docker Compose.

 **How to Install PostgreSQL Using Docker Compose?**

To install PostgreSQL using Docker Compose, try out the below-mentioned steps:

\- Create/Make Docker Compose File  
\- Run the Postgres Container  
\- Verify Executing Container  
\- Interact With Executing Container  
\- Establish a Connection With a Database  
\- Execute psql Commands

 **Step 1: Create Docker Compose File**

Open Visual Studio Code and create a “ **docker-compose.yml** ” file. Then, define the desired services in the compose file. For instance, we have specified the following services:
    
    
    version: '3.8'
       services:
      postgres_db:
      image: postgres:latest
      container_name: PostgresCont 
      restart: always
      environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres123
      ports:
      - '5432:5432'
      volumes:
      - postgres_db:/var/lib/postgresql/data
       volumes:
      postgres_db:
      driver: local

Here:

\- “ **version** ” specifies the Docker Compose file’s version. In our case, it is “ **3.8** ”.  
\- “ **services** ” defines the services that need to be executed with Docker Compose.  
\- “ **postgres_db** ” is the Postgres service’s name.  
\- “ **image** ” defines the image to utilize i.e. “ **postgres:latest** ”.  
\- “ **container_name** ” represents the container name i.e. “ **PostgresCont** ”.  
\- “ **environment** ” sets the username and root password for the Postgres container.  
\- “ **ports** ” allocates port i.e. “ **5432:5432** ”  
\- “ **volumes** ” set up a volume to persist the Postgres data:

 **Step 2: Run the Postgres Container**

Type out the given command to start the Postgres services defined in the Docker compose file:
    
    
    docker-compose up -d

The above command has created and started the Postgres container.

 **Step 3: Verify Executing Container**

Ensure that the Postgres container is built and currently executing via the given below command:
    
    
    docker ps

It can be seen that the “ **PostgresCont** ” container is executing efficiently.

 **Step 4: Interact With Executing Container**

Type out the “ **docker exec -it <cont-name> bash**” command and specify the executing Postgres container name to open the shell within it:
    
    
    docker exec -it PostgresCont bash

Subsequently, the “PostgresCont” container has been accessed and now we can run commands in it.

 **Step 5: Establish a Connection With a Database**

To connect and access the database server, utilize the below-listed command:
    
    
    psql -h localhost -U postgres

After that, we can execute/run SQL queries and psql commands in the SQL shell.

 **Step 6: Execute psql Commands**

Finally, execute the psql commands in the PostgreSQL container. For instance, we are executing the “ **\l** ” command to list available databases:
    
    
    \l

We have efficiently installed PostgreSQL using Docker Compose.

 **Conclusion**

To install PostgreSQL using Docker Compose, first, create a Docker compose file and specify the desired services. Then, start the compose service to build and execute the Postgres container. After that, interact with the executing container and access the PostgreSQL database server. Lastly, execute psql commands. This write-up has demonstrated the method to install PostgreSQL using Docker Compose.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-postgresql-using-docker-compose/)

---

# How to Get the Name of the Current User in PostgreSQL

> In PostgreSQL, the “CURRENT_USER”, “CURRENT_ROLE”, and “USER” methods are used to get the details of the current user.

While working with the PostgreSQL database, identifying the user name is an important task that helps us manage access to the database. For this purpose, PostgreSQL offers several methods that retrieve the name of a user that is currently using the PostgreSQL database, such as **CURRENT_USER** , **USER** , and **CURRENT_ROLE**. Moreover, users can get a list of currently logged-in users or all users using different commands and functions.

This write-up demonstrates how to get the name of the current user in Postgres using the following content:

  * Method 1: Using CURRENT_ROLE Function
  * Method 2: Using CURRENT_USER Function
  * Method 3: Using the USER Function
  * Bonus Tip 1: Get Currently/Presently Logged-in Users
  * Bonus Tip 2: Get All Users



 **How to Get the Name of the Current User in Postgres Using CURRENT_ROLE?**

Execute the CURRENT_ROLE function with the aid of a SELECT query to get the name of the current user. This function doesn't require any arguments and it is executed without parentheses:
    
    
    SELECT CURRENT_ROLE;

The output snippet shows that the current user is “postgres”:

 **How to Get the Name of the Current User in Postgres Using CURRENT_USER?**

Use the CURRENT_USER function with the assistance of a SELECT statement to fetch the name of the current user: The stated function doesn't need any arguments and must be executed without parentheses:
    
    
    SELECT CURRENT_USER;

The desired function executed successfully and it retrieves “postgres” as output, which is nothing but the name of the current user:

 **How to Get the Name of the Current User in Postgres Using the USER Function?**

Alternatively, users can execute the USER() function with the help of a SELECT statement to fetch the name of the current user. The stated function doesn’t require any parenthesis to execute:
    
    
    SELECT USER;

The function executed successfully, and it returned "postgres" as the output, which is the name of the current user:

 **Bonus Tip 1: How to Get Currently Logged-in Users in Postgres?**

Use the “ **pg_stat_activity** ” view with the “SELECT DISTINCT” clause to fetch the information of the currently logged-in users in PostgreSQL:
    
    
    SELECT DISTINCT usename AS logged_in_users
    FROM pg_stat_activity;

The below output snippet retrieves the names of the currently logged-in users:

Check out our dedicated guide on how to locate [logged-in users](<https://www.commandprompt.com/education/how-to-find-logged-in-users-in-postgresql/>) in PostgreSQL for more details.

 **Bonus Tip 2: How to Get All Users in Postgres?**

Postgres offers several methods to find/get all users in Postgres. The “\du” is one such method that retrieves the user name along with their attributes:
    
    
    \du

For more details on [getting the list of users](<https://www.commandprompt.com/education/how-to-show-users-in-postgresql/>), check out the following guide.

 **Conclusion**

In PostgreSQL, the “CURRENT_USER”, “CURRENT_ROLE”, and “USER” methods are used to get the details of the current user. All these methods do not require parameters and are executed without any parentheses. Moreover, the “pg_stat_activity” view and “\du” command can be used to get currently logged-in users or all users, respectively. This post has elaborated on various methods to get the name of the current user in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-name-of-the-current-user-in-postgresql/)

---

# What Does SETVAL() Function Do in PostgreSQL?

> In PostgreSQL, SETVAL() is one of the sequence functions that resets the current value of the selected sequence and retrieves the specified value.

PostgreSQL supports the concept of " **sequences** ", which are database objects and are used for generating unique integers. Sequences are primarily used to generate primary keys for tables. PostgreSQL provides several functions, such as **SETVAL()** , **NEXTVAL()** , **CURRVAL()** , and **LASTVAL()** , to work efficiently with sequences.

This write-up will illustrate the use of the SETVAL() function in PostgreSQL sequences.

 **What Does SETVAL() Function Do in PostgreSQL?**

 **SETVAL()** is one of the sequence functions that resets the current value of the selected sequence and retrieves the specified value.

 **Syntax**

Use the below-stated syntax to execute the SETVAL() function on a specific sequence:
    
    
    SETVAL(seq_name TEXT, current_val BIGINT, is_called BOOLEAN);

 **Parameters**

The SETVAL() function accepts the following parameters:

\- **seq_name:** It represents a sequence upon which the stated function will be implemented.  
\- **current_val:** It indicates the current value of the selected sequence.  
\- **is_called:** It determines whether the specified current value is recalled. True indicates that the current value of the setting will be used, while false indicates that it won't be used. By default, the “is_called” parameter has a true value.

 **Return Value**

It retrieves the value of the “current_val” parameter.

 **Return Type**

The return type of the SEVAL() function is “BIGINT”.

 **Example: Using SETVAL() in Postgres**

First, create a sample sequence and name it “cp_seq”:
    
    
    CREATE SEQUENCE cp_seq 
    START 172;

The specified sequence is initialized with a start value of "172":

Now execute the NEXTVAL() function to proceed the cp_sequence to its next value and retrieve the current value:
    
    
    SELECT NEXTVAL('cp_seq');

Now invoke the SETVAL() function to set the sequence value to 180:
    
    
    SELECT SETVAL('cp_seq', 180);

Let’s invoke the NEXTVAL() function to obtain the next value of the “cp_seq”:
    
    
    SELECT NEXTVAL('cp_seq');

The NEXTVAL() retrieves the sequence value according to the specified value, i.e., “set value + 1”:

If a user wants to start the sequence from the specified value (instead of specified value + 1), then specify the value of the is_called parameter as “false”:
    
    
    SELECT SETVAL('cp_seq', 180, false);

This time, invoking the NEXTVAL() function will retrieve 180 instead of 181:
    
    
    SELECT NEXTVAL('cp_seq');

That’s all about the usage of the NEXTVAL() function in PostgreSQL.

 **Conclusion**

In PostgreSQL, SETVAL() is one of the sequence functions that resets the current value of the selected sequence and retrieves the specified value. The SETVAL() function accepts three parameters: sequence name, current value, and the is_called parameter. The “is_called” parameter determines whether the specified current value is recalled. Its default value is true. This post has demonstrated the working of the SETVAL() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/what-does-setval-function-do-in-postgresql/)

---

# How to Create a PostgreSQL Database in Docker

> To create a PostgreSQL database in Docker, use the “CREATE DATABASE &lt;database-name&gt;;” command. Then, create a new table in it and insert values in the table.

**PostgreSQL** is a well-known relational DBMS that provides a variety of features, such as built-in or user-defined functions, operators, data types, and many more. It is capable of running on numerous platforms, including Windows, Docker, and Linux. Moreover, users can also use PostgreSQL in Docker to easily create and manage the PostgreSQL database without installing it on the local host machine.

> Try the new PgManage (Open Source) and get rid of PgAdmin!

> Get 24x7 Enterprise Wide support for PostgreSQL and Open Source technologies

This article will demonstrate the method of creating a PostgreSQL database in Docker.

##  **How to Create/Set up a Postgres Database With Docker?**

To create a PostgreSQL database in Docker, check out the below-listed steps:

  1.  **Pull Official Postgres Image from Docker Hub**
  2.  **Create and Run Postgres Container**
  3.  **Verify Executing Container**
  4.  **Interact With Postgres Container**
  5.  **Connect to a PostgreSQL Database Server**
  6.  **Create a PostgreSQL Database**
  7.  **Confirm Database Creation**
  8.  **Establish a Connection With a Database**
  9.  **Create a Table in the Database**
  10.  **Insert Records into a Postgres Table**
  11.  **Fetch Table Data**



###  **Pull/Download Official Postgres Image From Docker Hub**

Launch the Windows PowerShell from the start menu and execute the below-provided “ **docker pull** ” command to download the official Postgres image from Docker Hub to your local system:
    
    
    docker pull postgres

Executing the above-stated command will download the latest version of the Postgres image, as shown in the following output snippet:

###  **Create and Run Postgres Container**

Create and run the Postgres container using the Postgres image via the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command:
    
    
    docker run -d --name postgresCont -p 5432:5432 -e POSTGRES_PASSWORD=pass123 postgres

Here:

\- “ **-d** ” flag specifies that the container should execute in the background.  
\- “ **\--name** ” option assigns the container’s name, i.e., “ **postgresCont** ”.  
\- “ **-p** ” assigns the port for the container i.e. “ **5432:5432** ”.  
\- “ **-e POSTGRES_PASSWORD** ” configures the password to be “ **pass123** ”.  
\- “ **postgres** ” is the official Docker image:

Upon doing so, the Postgres container has been created and started.

###  **Verify Executing Container**

Ensure that the Postgres container is built and currently executing via the given-provided command:
    
    
    docker ps

The above output indicates that the “ **PostgresCont** ” container is running.

###  **Interact With Executing Container**

Type out the “ **docker exec -it <cont-name> bash**” command and specify the executing Postgres container name to open the shell within it:
    
    
    docker exec -it postgresCont bash

Subsequently, the “PostgresCont” container has been accessed and now we can run commands in it.

###  **Connect to a PostgreSQL Database Server**

Execute the “psql” command along with the hostname and user name to make a connection with the Postgres Database Server:
    
    
    psql -h localhost -U postgres

Executing the above-stated command will take us to the SQL Shell, where we can execute/run SQL queries and psql commands:

###  **Create a PostgreSQL Database**

Now we are all set to create a new Postgres database. For this purpose, use/execute the “ **CREATE DATABASE** ” command along with the database name. For instance, we are creating a database named “ **tsl_employee** ”:
    
    
    CREATE DATABASE tsl_employee;

###  **Confirm Database Creation**

Display all the databases to view the newly created database:
    
    
    \l

It can be seen that the “ **tsl_employee** ” database has been created successfully.

###  **Establish a Connection With a Database**

Type out the “ **\c** ” meta-command along with the database name of your choice to establish a connection with it. For instance, we want to connect to the “ **tsl_employee** ” database:
    
    
    \c tsl_employee;

A connection has been successfully established with the specified database.

###  **Create a Table in the Database**

To make a new table in the selected database, utilize the “ **CREATE TABLE <table_name>(col_1 <data_type>, col_2 <data_type>, col_3 <data_type>,..., col_N <data_type>);**” command. Where table_name represents a table to be created, col_1, col_2, …, col_N are the column names, and data_type represents any valid data type. Here, we are creating a table named “ **tech_authors** ”:
    
    
    CREATE TABLE tech_authors(ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, TYPE TEXT NOT NULL, CATEGORY TEXT NOT NULL, ATICLES INT NOT NULL);

Executing the “CREATE TABLE” command will create a new table with the desired columns:

###  **Insert Records into a Postgres Table**

Use the “ **INSERT INTO <table_name> VALUES (value_1, value_2, value_3, ...);**” command for inserting new records into the newly created table. For instance, we have inserted the following values:
    
    
    INSERT INTO tech_authors VALUES (1, 'Laiba', 'Senior', 'Docker', 50);

###  **Fetch Table Data**

Write out the provided command to view the specific table’s data:
    
    
    SELECT * FROM tech_authors;

In the above screenshot, the data of the “ **tech_authors** ” table can be seen.

##  **Conclusion**

To create a PostgreSQL database in Docker, first, pull/download the official Postgres image using the “ **docker pull postgres** ” command. Then, create and start the Postgres container via the “ **docker run --name -d <cont-name> -p 5432:5432 -e POSTGRES_PASSWORD=<password> postgres**” command. After that, access the Postgres container and make a connection with the desired database. Next, create a Database utilizing the “ **CREATE DATABASE <database-name>;**” command. Furthermore, users can create tables in the database, insert values, and select data from the database.

## Related Articles

> How to Create a Database in Postgres

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-postgresql-database-in-docker/)

---

# How to Check/Verify if a Specific Table Exists in PostgreSQL Database

> In PostgreSQL, the “information_schema”, “pg_catalog”, and “pg_tables” are used to check the existence of a specific table in the current database.

Tables are the most important database object in any relational database like PostgreSQL as they serve as the primary means of storing data in rows and columns. Once a table is created, users can perform different operations on it. However, it is crucial to confirm the existence/presence of a specific table before working with it in PostgreSQL.

This blog post will discuss various methods of checking whether a particular table exists in a database.

 **How to Check/Verify if a Specific Table Exists in PostgreSQL Database?**

Accessing or using a particular Postgres table demands the existence of that specific table in the database. Therefore, Postgres offers various methods to check the presence of a specific table in a database. In this post, the below-listed methods will be discussed to check the existence of a Postgres table:

  * Using information_schema
  * Using pg_catalog
  * Using pg_tables



 **How to Check if a Specific Table Exists in PostgreSQL Database Using information_schema?**

Postgres provides a system schema named “ **information_schema** ” that helps us fetch the metadata about the database objects. Using information_schema, users can test the presence of a specific table. The below snippet illustrates the basic syntax of using the information_schema to check the existence of a table:
    
    
    SELECT EXISTS (
    SELECT 1
    FROM information_schema.tables
    WHERE table_name = 'name_of_table'
    ) AS table_existence;

In the above syntax, the EXISTS operator is used with the information_schema to validate the existence of a particular table.

 **Example: Check the Table’s Existence Using information_schema**

The below coding example tests the existence of the “emp_details” table by utilizing the “information_schema”:
    
    
    SELECT EXISTS (
    SELECT 1
    FROM information_schema.tables
    WHERE table_name = 'emp_details'
    ) AS table_existence;

The output snippet retrieves true, proving that the selected table exists in the connected database:

 **How to Check if a Specific Table Exists in PostgreSQL Database Using pg_catalog?**

Postgres provides a system schema named “ **pg_catalog** ” that allows us to fetch the metadata about the tables and views. Using pg_catalog, users can test the presence of a specific table. The below snippet illustrates how to use the pg_catalog to check the presence of a specific table:
    
    
    SELECT EXISTS (
    SELECT 1
    FROM pg_catalog.pg_class
    WHERE relname = 'name_of_table'
    AND relkind = 'r'
    ) AS table_existence;

In the above syntax, the EXISTS operator is used with the pg_catalog to test the existence of a particular table. The relkind = 'r' indicates that the relation type must be a regular table.

 **Example: Check the Table’s Existence Using pg_catalog**

The following snippet checks the existence of the “emp_details” table using the “pg_catalog”:
    
    
    SELECT EXISTS (
    SELECT 1
    FROM pg_catalog.pg_class
    WHERE relname = 'emp_details'
    AND relkind = 'r'
    ) AS table_existence;

The boolean “true” in the output verifies that the selected table exists in the connected database:

 **How to Check if a Specific Table Exists in PostgreSQL Database Using pg_tables?**

PostgreSQL offers a system view named **pg_tables** view that retrieves details about tables of a specific schema or all schemas in the current database. Here is the syntax for utilizing the pg_tables view in Postgres:
    
    
    SELECT EXISTS (
    SELECT 1
    FROM pg_tables
    WHERE tablename = 'name_of_table'
    ) AS table_existence;

The above syntax utilizes the EXISTS operator with the “pg_tables” view to confirm the presence of a particular table.

 **Example: Check the Table’s Existence Using pg_tables**

Type the following piece of code to check the table’s existence using the pg_tables view:
    
    
    SELECT EXISTS (
    SELECT 1
    FROM pg_tables
    WHERE tablename = 'emp_details'
    ) AS table_existence;

The output demonstrates that the selected table exists in the current database:

That’s all about checking the existence of a specific table in the Postgres database.

 **Conclusion**

In PostgreSQL, the “information_schema”, “pg_catalog”, and “pg_tables” are used to check the existence of a specific table in the current database. All these methods retrieve a boolean true or false, which indicates the presence of the selected table in the current database. This post has illustrated three different methods to check the presence of a particular table in the Postgres database.

---
[View this page online](https://www.commandprompt.com/education/how-to-checkverify-if-a-specific-table-exists-in-postgresql-database/)

---

# How to Check/Find the Hostname and Port Number in PostgreSQL

> In PostgreSQL, several methods are used to check/find the hostnames and port numbers, such as the “\conninfo” command, the “pg_settings” view, etc.

While working with databases, obtaining information about the hostname and port number is crucial. This is because a Postgres database requires a hostname and port number to establish a connection. Host names indicate the location of the database server, while port numbers indicate how we can access a database.

This write-up illustrates various methods of finding the hostname and port number in PostgreSQL.

 **How to Check/Find the Hostname and Port Number in PostgreSQL?**

The below-listed methods will be discussed in this post to check the hostname and port number:

  * Using \conninfo
  * Using pg_settings
  * Using “inet_server_addr()” and “inet_server_port()”
  * Using “postgresql.conf” File



 **How to Check/Find the Hostname and Port Number Using \conninfo?**

“\conninfo” is a meta-command that retrieves connection details, such as database name, user name, port number, and hostname. To utilize this command, open the psql utility, provide the login privileges, and execute the below-provided meta-command:
    
    
    \conninfo

The following snippet demonstrates that we are connected to “localhost” at the default port, which is “5432”:

 **How to Check/Find the Port Number Using pg_settings?**

Postgres provide a pre-defined view named "pg_settings" that keeps detailed information about the current configuration settings of the Postgres database server. Users can utilize this view to query the hostname and port number:
    
    
    SELECT * FROM pg_settings
    WHERE name = 'port';

 **How to Check/Find the Hostname and “inet_server_addr()”?**

PostgreSQL provides an inbuilt function named “inet_server_addr()” that retrieves the server’s IP address (hostname). To get the hostname using the inet_server_addr() function, query the following command:
    
    
    SELECT inet_server_addr() AS hostname;

The stated function retrieves “ **::1** ”, which is equivalent to " **127.0.0.1** ":

 **How to Check/Find the Port Number Using “inet_server_port()”?**

In Postgres, a built-in function named “inet_server_port()” is used to get the server’s port number. For this purpose, query the following command:
    
    
    SELECT inet_server_port() AS portNumber;

The given function retrieves the server's port number as " **5432** ":

 **How to Check/Find the Hostname and Port Number Using “postgresql.conf” File?**

The "postgresql.conf" is a configuration file that assists Postgres in managing different settings and parameters for the database server. Execute the following command to see the location where the "postgresql.conf" file is located:
    
    
    show config_file;

The below snippet shows that the configuration file is located at “C:\Program Files\PostgreSQL\15\data\postgresql.conf” path:

Navigate to the stated path, open the configuration file in any text editor, and scroll down a little bit to reach the “ **CONNECTIONS AND AUTHENTICATION** ” section:

The output snippet demonstrates that we are connected to “localhost” at the default port, which is “5432”.

 **Conclusion**

In PostgreSQL, several methods are used to check/find the hostnames and port numbers, such as the “\conninfo” command, the “pg_settings” view, the “inet_server_addr()” and “inet_server_port()” functions, and the “postgresql.conf” file. This post has demonstrated all these methods with practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-checkfind-the-hostname-and-port-number-in-postgresql/)

---

# How Do I Get the List of Existing Stored Procedures in PostgreSQL

> To get the list of all stored procedures in a database, the “\df” command, “pg_proc” catalog, and “information_schema.routines” view are used in Postgres.

In Postgres, a procedure is a named block of code that encapsulates a sequence of SQL statements to perform a specific operation. A new stored procedure in Postgres can be created by executing the “CREATE PROCEDURE” command. However, to call or utilize an existing stored procedure, users are required to be familiar with the name of that particular procedure. For this purpose, various commands, catalogs, and views can be used.

This write-up presents a practical guide to getting the list of available stored procedures in a Postgres database.

 **How Do I Get the List of Existing Stored Procedures in Postgres?**

Postgres offers several methods to get the list of available stored procedures. In this blog post, the below-listed methods will be discussed using suitable examples:

  * Method 1: Using \df Command
  * Method 2: Using information_schema.routines View
  * Method 3: Using pg_proc Catalog



 **How to List All Stored Procedures Using \df Command?**

“ **\df** ” is a meta-command that only works in the SQL Shell(psql). It retrieves the list of existing routines, including functions and stored procedures. For instance, in the following example, the “\df” command is executed to retrieve the list of all available user-defined functions and stored procedures:
    
    
    \df

The following output snippet shows all available stored procedures and user-defined functions:

 **How to List All Stored Procedures Using information_schema.routines View?**

The “i **nformation_schema.routines** ” is a standard view in Postgres that provides details about all routines of a database, including procedures and functions. To get the list of only stored procedures (excluding user-defined functions), specify the routine type as “PROCEDURE” in the WHERE clause:
    
    
    SELECT routine_schema As schema_name,
    routine_name As procedure_name
    FROM information_schema.routines
    WHERE routine_type = 'PROCEDURE';

The following snippet depicts that the “information_schema.routines” view successfully retrieves available procedures:

 **How to List All Stored Procedures Using pg_proc Catalog?**

The pg_proc is a system catalog in Postgres that stores information about all the routines of a database, including functions and stored procedures. It has several columns that demonstrate detailed information about each routine. In the following example, the “pg_proc” catalog is used to get the list of available procedures in the public schema:
    
    
    SELECT namespace.nspname As schema_name, 
    procedure.proname As procedure_name
    FROM pg_catalog.pg_namespace namespace
    JOIN pg_catalog.pg_proc procedure ON 
    procedure.pronamespace = namespace.oid
    WHERE procedure.prokind = 'procedure'
    AND namespace.nspname = 'public';

This is how users can get the list of stored procedures in Postgres.

 **Conclusion**

To get the list of all stored procedures in a database, the “ **\df** ” command, “ **pg_proc** ”, catalog, and “ **information_schema.routines** ” view are used in Postgres. All these approaches retrieve the list of all the user-defined functions and stored procedures. This write-up has demonstrated various methods of listing stored procedures in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-get-the-list-of-existing-stored-procedures-in-postgresql/)

---

# How to Check if a Table Exists in Postgres Database Using a User-Defined Function

> In PostgreSQL, a user-defined function can be created that accepts the table name and schema name as arguments.

PostgreSQL provides several system schemas, such as **information_schema** , **pg_catalog** , etc., which can be used to check the existence of a table in a database. However, using these schemas often requires executing multiple lines of code every time we need to perform the check. To facilitate this process, users can create a custom function that encapsulates the table existence check and call it whenever needed. This approach improves coding efficiency and enhances the overall performance of the program.

This post illustrates how to check the table’s existence using a user-defined function in Postgres.

 **How to Check if a Table Exists in Postgres Database Using a User-Defined Function?**

The user-defined functions allow us to create custom logic according to specific requirements. Using user-defined functions, users can check the existence of a particular Postgres table.

Let’s head into practical examples to understand this concept appropriately.

 **Example: Checking the Table’s Existence Using a User-defined Function**

In the following example, a user-defined function named check_existence is created that accepts the table name and schema name as arguments. It checks the existence of the specified table and returns true or false based on the table’s existence:
    
    
    CREATE FUNCTION check_existence(name_of_schema TEXT, name_of_table text) 
    RETURNS Boolean AS $$
    BEGIN
    RETURN EXISTS (
       SELECT 1
       FROM information_schema.tables
       WHERE table_schema = name_of_schema
       AND table_name = name_of_table
    );
    END;
    $$ LANGUAGE plpgsql;

The below snippet demonstrates that the desired user-defined function has been created successfully:

Now to check the existence of a specific table, all you have to do is call the “check_existence” function and pass the table’s name and schema name as arguments to it:
    
    
    SELECT check_existence('public', 'emp_bio');

The output snippet shows that the selected table exists in the public schema:

Let’s call the “check_existence” function one more time and pass it a table name that doesn’t exists:
    
    
    SELECT check_existence('public', 'employee_bio');

The output snippet confirms that the specified table does not exist:

That’s all about checking the table’s existence in Postgres using a user-defined function.

 **Conclusion**

In PostgreSQL, a user-defined function can be created that accepts the table name and schema name as arguments. Once a function is created, it can be invoked with the schema name and table name. The function will check the existence of the specified table and return true or false based on the table’s existence. This post has illustrated a complete process of checking the table’s existence using a user-defined function.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-if-a-table-exists-in-postgres-database-using-a-user-defined-function/)

---

# How to Show Installed Extensions in PostgreSQL

> In PostgreSQL, the “\dx” command, “pg_extension” catalog, and “pgAdmin” are used to get the list of installed extensions.

PostgreSQL extensions enhance the functionality of the database system by providing additional operators, functions, and valuable features. In Postgres, the " **CREATE EXTENSION** " command is utilized to add a new extension to the current schema of the connected database. However, to retrieve the list of installed extensions, various methods are used in PostgreSQL.

This write-up will illustrate different commands and queries to show the installed extensions in Postgres.

 **How to Show Installed Extensions in PostgreSQL?**

Postgres provides various commands that help us get the list of installed extensions. In this post, we will discuss the below-mentioned methods to get the list of installed extensions:

  * Using “\dx” Command.
  * Using “pg_extension” Catalog.
  * Using “pgAdmin”.



 **How to Show Installed Extensions in Postgres Using \dx Command?**

“ **\dx** ” is a meta-command in Postgres that executes in psql and retrieves the list of installed extensions. The retrieved list provides all the necessary details, such as extension name, version, schema name in which the extension is installed, and description. The following snippet demonstrates how the “\dx” command work in Postgres:
    
    
    \dx

The “\dx+” command can be utilized to get detailed information about the installed extensions and the associated objects:
    
    
    \dx+

 **How to Show Installed Extensions in Postgres Using pg_extension Catalog?**

Postgres provides a system catalog named “pg_extension” that keeps the information about the installed extensions. Use the pg_extension catalog with the SELECT command to fetch the extensions’ details, such as extension name, version, extension owner, default schema, etc. The below code snippet shows how the pg_extension catalog work in Postgres:
    
    
    SELECT * FROM pg_extension;

 **How to Show Installed Extensions in Postgres Using pgAdmin?**

pgAdmin is a popularly used graphical user interface (GUI) for Postgres and is used to perform various database-related tasks, such as database creation, managing tables, etc. Users can use pgAdmin to get the list of installed extensions without even executing any query. For this purpose, open pgAdmin, navigate to the “Servers” tree, expand the “databases” tab, select a database, and head into the “Extensions” section:

That’s all about getting information about the installed extensions in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “\dx” command, “pg_extension” catalog, and “pgAdmin” are used to get the list of installed extensions. The retrieved list provides all the necessary details regarding the installed extensions, such as extension name, version, schema name in which the extension is installed, and description. This write-up has provided a comprehensive guide on showing the list of installed extensions in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-show-installed-extensions-in-postgresql/)

---

# How to Update Multiple Columns in PostgreSQL

> To update multiple columns of a PostgreSQL table, use the comma-separated syntax within the UPDATE statement, combined with the SET clause.

In PostgreSQL, users can update one or more columns of the table simultaneously using the update query. It's simple to update a single column, but updating multiple columns can be a bit more challenging. However, there's no need to worry because using the **UPDATE** command with a simple comma-separated syntax can update a bulk of columns in a single operation.

This post illustrates a comprehensive guide on updating multiple columns of a Postgres table.

 **How to Update Multiple Columns in PostgreSQL?**

Use the comma-separated syntax for the UPDATE statement along with the SET clause to update multiple columns of a Postgres table:
    
    
    UPDATE table_name
    SET col_1 = val_1, col_2 = val_2, col_3 = val_3, ...
    WHERE update_condition;

Here in this syntax:

\- The table_name represents a table that needs to be updated/modified.

\- In the SET clause, specify the columns to be updated, along with their corresponding modified values, separated by commas.

\- Utilize the WHERE clause to specify update criteria.

 **Example: Updating Multiple Columns in Postgres**

A sample table named "emp_bio" has already been created with the following details:
    
    
    SELECT * FROM emp_bio;

Suppose we need to modify the “emp_sal” and “joining_date” columns of the emp_bio table. For this purpose, we will utilize the UPDATE command as follows:
    
    
    UPDATE emp_bio
    SET emp_sal = 55000, joining_date = '2019-08-01'
    WHERE e_id >= 5;

The following screenshot shows that three records have been updated in the “emp_bio” table:

Execute the following query to view the updated records from the "emp_bio" table:
    
    
    SELECT * FROM emp_bio;

The output snippet describes that the selected columns have been successfully updated:

This is how a user can update multiple columns of a table by executing a single “UPDATE” query.

 **Conclusion**

To update multiple columns of a PostgreSQL table, use the **comma-separated** syntax within the **UPDATE** statement, combined with the **SET** clause. In the SET clause, specify the columns to be updated, along with their corresponding modified values, separated by commas. This write-up has illustrated the usage of the Postgres UPDATE query for updating multiple columns.

---
[View this page online](https://www.commandprompt.com/education/how-to-update-multiple-columns-in-postgresql/)

---

# How Do I Add an IDENTITY Column to an Already Existing Postgres Table

> In PostgreSQL, the ALTER TABLE statement is executed with the “ADD GENERATED AS IDENTITY” option to add an IDENTITY column to a pre-existing table.

PostgreSQL 10 and later versions include a new feature called the " **IDENTITY** " column, which allows for the auto-incrementing of column values. The stated feature can be applied not only to new tables but also to existing tables. For this purpose, the ALTER TABLE statement is used along with the “ **ADD GENERATED AS IDENTITY** ” option.

This write-up will illustrate a thorough guide on adding an IDENTITY column to an already existing table in Postgres.

 **How Do I Add an IDENTITY Column to an Already Existing Postgres Table?**

Use the **ALTER TABLE** statement with the “ **ADD GENERATED AS IDENTITY** ” option to add/insert an IDENTITY column into an existing table. However, altering a regular column to an IDENTITY column requires the targeted column to be defined as NOT NULL.

Use the below-provided syntax for the **ALTER TABLE** command to modify a regular column to an **IDENTITY** column:
    
    
    ALTER TABLE tbl_name 
    ALTER COLUMN col_name 
    ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY { ( seq_option ) }

Use either the “ALWAYS” or “BY DEFAULT” option to define a column as an IDENTITY. Visit the following guide on “Create IDENTITY Column” to learn more about the “ALWAYS” and “BY DEFAULT” options.

 **Example**

We have a sample table named “emp_info” with the following details:
    
    
    \d emp_info;

In the following example, the ALTER TABLE command is executed to add the IDENTITY column to the emp_info table:
    
    
    ALTER TABLE emp_info
    ALTER COLUMN emp_id
    ADD GENERATED BY DEFAULT AS IDENTITY;

An error occurred while altering the “emp_id” column to the IDENTITY column:

To rectify the “ **column emp_id must be declared NOT NULL before IDENTITY can be added** ” error, first add a NON-NULL constraint on the selected column:
    
    
    ALTER TABLE emp_info
    ALTER COLUMN emp_id SET NOT NULL;

The NOT NULL constraint is successfully added to the “emp_id” column:

Let’s change the emp_info column to an IDENTITY column using the following query:
    
    
    ALTER TABLE emp_info
    ALTER COLUMN emp_id
    ADD GENERATED BY DEFAULT AS IDENTITY;

To verify the table’s alteration, execute the below-provided meta-command with the table name:
    
    
    \d emp_info;

The IDENTITY column has been successfully added to the emp_info table:

That’s all about adding an identity column to an existing table in Postgres.

 **Conclusion**

In PostgreSQL, the **ALTER TABLE** statement is executed with the “ **ADD GENERATED AS IDENTITY** ” option to add an IDENTITY column to a pre-existing table. However, altering a regular column to an IDENTITY column requires the targeted column to be defined as NOT NULL. This article has illustrated a thorough guide on adding an IDENTITY column to an already existing table.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-add-an-identity-column-to-an-already-existing-postgres-table/)

---

# How to Fix the “lastval is not yet defined” Error When Calling LASTVAL() in Postgres

> In PostgreSQL, the “lastval of the sequence is not yet defined” error occurs when the LASTVAL() function is invoked/called prior to the NEXTVAL() function.

In PostgreSQL, the “ **LASTVAL()** ” function is an inbuilt function that assists in working with sequences. It retrieves the most recently generated sequence value within the current session. This function is session-specific, meaning it only retrieves the last value of a sequence fetched within the current session. However, calling the LASTVAL() function before NEXTVAL() function in the current session will show you a “lastval of the sequence is not yet defined” error.

This write-up illustrates a complete process of fixing the “lastval of the sequence is not yet defined” error in PostgreSQL.

 **How to Fix the “lastval is not yet defined” Error When Calling/Invoking LASTVAL() in Postgres?**

The stated error occurs when the **LASTVAL()** function is invoked before the **NEXTVAL()** function. For a profound understanding, let’s create a new sequence and apply the LASTVAL() function to it:
    
    
    CREATE SEQUENCE commandprompt;

The below snippet shows that when the NEXTVAL() function is not used in the current session then directly invoking the LASTVAL() function will throw the stated error:
    
    
    SELECT LASTVAL();

To rectify this error, all you need to do is invoke the NEXTVAL() function before the LASTVAL() function at least once:
    
    
    SELECT NEXTVAL('commandprompt'),
    NEXTVAL('commandprompt');

In this example, the NEXTVAL() function is invoked a couple of times:

Now call the LASTVAL() function to see how it works:
    
    
    SELECT LASTVAL();

Note that the LASTVAL() function doesn’t accept any argument. The output snippet shows that the “LASTVAL()” function shows the last retrieved value of the NEXTVAL() function in the current session:

That’s all about fixing the “lastval of the sequence is not yet defined” error in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “lastval of the sequence is not yet defined” error occurs when the **LASTVAL()** function is invoked/called prior to the **NEXTVAL()** function. To fix the stated error, all you need to do is invoke the NEXTVAL() function before the LASTVAL() function at least once. This write-up has illustrated the complete process of fixing the “lastval of the sequence is not yet defined” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-the-lastval-is-not-yet-defined-error-when-calling-lastval-in-postgres/)

---

# How to Fix the “column can only be updated to DEFAULT” Error in Postgres

> The “column can only be updated to DEFAULT” error arises when a user tries to update the value of an IDENTITY column that is created using the &quot;GENERATED ALWAY…

PostgreSQL 10 introduced a new feature named the " **IDENTITY** " column, which allows us to create a table’s column with auto-incrementing values. While working with the IDENTITY column, users may face the “column can only be updated to DEFAULT” error. The stated error occurs when the IDENTITY column uses the " **GENERATED ALWAYS** " clause.

This post illustrates a complete process of fixing the “column can only be updated to DEFAULT” ERROR in Postgres.

 **How to Fix the “column can only be updated to DEFAULT” Error in Postgres?**

The IDENTITY column in Postgres can be created either by using the " **GENERATED ALWAYS** " constraint or by using the " **GENERATED BY DEFAULT** " constraint. The “ **column can only be updated to DEFAULT** ” error arises when a user tries to update the value of an IDENTITY column that is created using the " **GENERATED ALWAYS** " option. Use one of the below-provided methods to rectify the stated error:

  * DEFAULT Option
  * ALTER IDENTITY Column to the GENERATED AS DEFAULT.



 **Example: Update IDENTITY Column in Postgres**

A table named “commandprompt_example” is created with an IDENTITY column. Here is the detailed information regarding the selected table:
    
    
    \d commandprompt_example;

Let’s fetch all the records from the said table to comprehend the working of the IDENTITY column:
    
    
    SELECT * FROM commandprompt_example;

Suppose we want to update the column having id “3”. For this purpose, execute the UPDATE query as follows:
    
    
    UPDATE commandprompt_example
    SET id =  5
    WHERE id = 3;

 **Solution 1: Using the DEFAULT Option**

One way to fix the stated error is the utilize the “DEFAULT” keyword/option:
    
    
    UPDATE commandprompt_example
    SET id = DEFAULT
    WHERE id = 3;

The output snippet shows that the selected record has been successfully updated:

 **Solution 2: ALTER IDENTITY Column to the GENERATED AS DEFAULT**

Postgres allows us to modify the value of the IDENTITY column that is created using the "GENERATED BY DEFAULT" clause. So, altering the “ **GENERATED AS ALWAYS** ” to “ **GENERATED AS DEFAULT** ” will efficiently fix the stated error. To do that utilize the ALTER TABLE command as follows:
    
    
    ALTER TABLE commandprompt_example
    ALTER COLUMN id SET GENERATED BY DEFAULT;

The selected table has been successfully altered, as shown in the following snippet:

Now, execute the UPDATE statement to modify a particular identity:
    
    
    UPDATE commandprompt_example
    SET id =  6
    WHERE id = 2
    RETURNING *;

The selected record has been successfully updated:

That’s all about fixing the “column can only be updated to DEFAULT” ERROR in Postgres.

 **Conclusion**

The “ **column can only be updated to DEFAULT** ” error arises when a user tries to update the value of an IDENTITY column that is created using the " **GENERATED ALWAYS** " option. To rectify the stated error, either use the “DEFAULT” option or alter the IDENTITY column to the “GENERATED AS DEFAULT”. This write-up has presented a couple of fixes for the “column can only be updated to DEFAULT” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-the-column-can-only-be-updated-to-default-error-in-postgres/)

---

# How to Drop IDENTITY Column From a Postgres Table

> To drop or delete an IDENTITY column from a table, execute the ALTER TABLE statement with the DROP IDENTITY option.

PostgreSQL 10 and later versions have the latest feature named the IDENTITY column. This column is used to generate auto-incrementing values. The IDENTITY column can be added to newly created tables or existing tables. When this column is no longer needed, it can be deleted from the table.

This write-up will demonstrate a practical guide on dropping an IDENTITY column from a table in PostgreSQL.

 **How to Drop IDENTITY Column From a Postgres Table?**

To drop or delete an IDENTITY column from a table, execute the ALTER TABLE statement with the DROP IDENTITY option/clause:
    
    
    ALTER TABLE tbl_name 
    ALTER COLUMN col_name 
    DROP IDENTITY [ IF EXISTS ];

Use the IF EXISTS option to check the presence of an IDENTITY column before dropping it from a table.

 **Example 1**

First, let’s check the structure of the sample table by executing the following meta-command:
    
    
    \d emp_info;

The output screenshot shows that the emp_id is an IDENTITY column:

The below-provided coding example illustrates how to drop/remove an IDENTITY column from a specific table:
    
    
    ALTER TABLE emp_info 
    ALTER COLUMN emp_id 
    DROP IDENTITY;

Now execute the “\d” command to verify the table’s structure:
    
    
    \d emp_info;

The emp_info table does not have any IDENTITY column:

Trying to drop an IDENTITY column that does not actually exist will result in the following error:
    
    
    ALTER TABLE emp_info 
    ALTER COLUMN emp_id 
    DROP IDENTITY;

To avoid the stated error, use the IF EXIST option along with the DROP IDENTITY option:
    
    
    ALTER TABLE emp_info 
    ALTER COLUMN emp_id 
    DROP IDENTITY IF EXISTS;

The following snippet proves that Postgres shows a notice instead of throwing an error:

That’s all about dropping an identity column from a table in Postgres.

 **Conclusion**

To drop or delete an IDENTITY column from a table, execute the ALTER TABLE statement with the DROP IDENTITY option. Use the IF EXISTS option with the DROP IDENTITY clause to check the presence of an IDENTITY column before dropping it from a table. This blog post has illustrated a thorough guide on dropping/deleting the IDENTITY column from a Postgres table.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-identity-column-from-a-postgres-table/)

---

# How to Fix “ERROR: step size cannot equal zero” While Creating a Series in PostgreSQL

> The &quot;step size can&#x27;t equal zero&quot; error in PostgreSQL occurs when a user uses a wrong step size of 0 while generating a series using the generate_series() funct…

In PostgreSQL, the **generate_series()** is a popularly used function that creates a series of integers/dates within the determined range. However, Postgres users occasionally face a “ **step size can’t equal zero** ” error while generating a series. The stated error arises because of specifying a wrong step size, i.e., 0. To rectify this error a couple of solutions are used in Postgres.

This blog post will provide several fixes for the “ **step size can’t equal zero** ” error in PostgreSQL.

 **How to Fix “ERROR: step size cannot equal zero” While Creating a Series in PostgreSQL?**

In Postgres, the generate_series() function is used to create a sequence of numbers/dates. The stated function accepts an optional parameter named step size that can be any number other than 0. If a user passes a step size equal to zero, then the generate_series() function will throw the following error:

To rectify this error, the below-listed solutions can be used in Postgres:

  * Utilize the Default Step Size.
  * Specify a Non-zero Step Size.



 **Solution 1: Utilize the Default Step Size**

The most suitable approach to fix the “step size can’t equal zero” error is, don’t specify any step size at all. So that the generate_series() function utilizes the default step size. Here is how the generate_series() function works with the default step size:
    
    
    SELECT * FROM generate_series(5, 15);

From the below-provided snippet, you can notice that the stated problem has been rectified. The series has been successfully generated within the specified range:

 **Solution 2: Specify a Non-zero Step Size**

An alternative solution to the stated problem is specifying a non-zero step size. Upon doing so, the “step size cannot equal zero” error will be resolved, as shown in the following example:
    
    
    SELECT * FROM generate_series(5, 15, 3);

In this example code, the step size is specified as “3”. The following will be the output for the given generate_series() function:

That’s all you need to learn about the “step size can’t equal zero” error in Postgres.

 **Conclusion**

The " **step size can 't equal zero**" error in PostgreSQL occurs when a user uses a wrong step size of 0 while generating a series using the generate_series() function. To rectify the stated error, either use the default step size or specify a non-zero step size. The best possible fix to the stated error is don’t specify any step size at all. In that case, the generate_series() function will utilize the default step size. This write-up has provided a couple of solutions to fix the “step size can’t equal zero” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-error-step-size-cannot-equal-zero-while-creating-a-series-in-postgresql/)

---

# How to Fix the “column of the relation must be declared NOT NULL before an identity can be added” Error in PostgreSQL?

> In PostgreSQL, altering a regular column to an IDENTITY column requires the targeted column to be defined as NOT NULL.

In PostgreSQL, the ALTER TABLE statement is used along with the “ **ADD GENERATED AS IDENTITY** ” option to add the IDENTITY column to a pre-existing table. However, a user may face unwanted circumstances if the column to be altered is not defined as NOT NULL.

This write-up illustrates how to fix the “column ‘column_name’ of the relation ‘relation_name’ must be declared NOT NULL” error in PostgreSQL.

 **How to Fix the “column ‘column_name’ of the relation ‘relation_name’ must be declared NOT NULL before an identity can be added” Error in PostgreSQL?**

To fix the stated error, follow the below-exhibited steps:

 **Step 1: Check Table Structure**

Check the table’s structure by executing the following meta-command:
    
    
    \d emp_info;

The output snippet demonstrates that no constraint has been applied to the “emp_id” column:

In the below-given example code, the ALTER TABLE statement is executed to add the IDENTITY column to the emp_info table:
    
    
    ALTER TABLE emp_info
    ALTER COLUMN emp_id
    ADD GENERATED BY DEFAULT AS IDENTITY;

On executing the above code, we encountered the following error:

To fix the “ **column emp_id must be declared NOT NULL before IDENTITY can be added** ” error, first, we need to add a NOT NULL constraint on the selected column:
    
    
    ALTER TABLE emp_info
    ALTER COLUMN emp_id SET NOT NULL;

The NOT NULL constraint is successfully added to the “emp_id” column:

Now execute the “\d” meta-command one more time to see the modified structure of the emp_info table:
    
    
    \d emp_info;

The NOT NULL constraint has been added to the emp_id column:

Now execute the given statement to change the emp_info column to an IDENTITY column:
    
    
    ALTER TABLE emp_info
    ALTER COLUMN emp_id
    ADD GENERATED BY DEFAULT AS IDENTITY;

Execute the below-provided meta-command with the table name to check if the IDENTITY column is added to the table or not:
    
    
    \d emp_info;

The IDENTITY column has been successfully added to the emp_info table:

That’s all about fixing the “column of the relation must be declared NOT NULL before an identity can be added” error in Postgres.

 **Conclusion**

In PostgreSQL, altering a regular column to an IDENTITY column requires the targeted column to be defined as NOT NULL. If the selected column does not meet this criterion, the error “The column of the relation must be declared NOT NULL before an identity can be added” occurs in Postgres, as demonstrated in this write-up.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-the-column-of-the-relation-must-be-declared-not-null-before-an-identity-can-be-added-error-in-postgresql/)

---

# How to Fix the "can't insert a non-default value into column id" Error in Postgres

> The “can&#x27;t insert a non-default value into column id” error arises when a user tries to insert the value to an IDENTITY column that is created using the &quot;GENER…

The invention of the " **IDENTITY** " column feature in PostgreSQL 10 and later versions enables the creation of columns with auto-incrementing values. However, users may encounter the " **can 't insert a non-default value into column id**” error when working with the IDENTITY column. This error typically occurs when the IDENTITY column is defined with the " **GENERATED ALWAYS** " option.

This article illustrates a practical guide on fixing the "can't insert a non-default value into column id" Error in Postgres.

 **How to Fix the "can't insert a non-default value into column id" Error in Postgres?**

The “ **can 't insert a non-default value into column id**” error arises when a user tries to insert the value to an IDENTITY column that is created using the " **GENERATED ALWAYS** " option. To solve this error, use the **OVERRIDING SYSTEM VALUE** option while inserting a user-specified value.

Follow the steps below to fix the stated error:

 **Step 1: Create a Table**

Let’s create a new table with an IDENTITY column, as follows:
    
    
    CREATE TABLE cp_example(
    id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    blog_name TEXT
    );

The desired table has been successfully created.

 **Step 2: Insert Data**

Now let’s insert a couple of records into the selected table using the INSERT query:
    
    
    INSERT INTO cp_example(blog_name)
    VALUES ('blog 1'),
    ('blog 2');

The given records have been inserted into the “cp_example” table:

 **Step 3: Verify the Table’s Data**

Fetch the newly inserted records to comprehend the working of the IDENTITY column:
    
    
    SELECT * FROM cp_example;

 **Step 4: Insert a User-specified Value in the IDENTITY Column**

Now, let’s try to insert a user-specified value in the IDENTITY column and see how Postgres deals with that specific scenario:
    
    
    INSERT INTO cp_example(id, blog_name)
    VALUES (5, 'blog 5');

An error occurs while inserting an explicit value into the IDENTITY column:

 **Step 5: Use the OVERRIDING SYSTEM VALUE Option**

The most convenient way to address the stated issue is to use the “OVERRIDING SYSTEM VALUE” option:
    
    
    INSERT INTO cp_example( id, blog_name) 
    OVERRIDING SYSTEM VALUE
    VALUES (5, 'blog 5')
    RETURNING *;

The below-provided output snippet shows that the stated error has been successfully rectified:

That’s all about fixing the "can't insert a non-default value into column id" error in Postgres.

 **Conclusion**

In PostgreSQL, the “ **can 't insert a non-default value into column id**” error arises when a user tries to insert the value to an IDENTITY column that is created using the " **GENERATED ALWAYS** " option. To solve this error, use the **OVERRIDING SYSTEM VALUE** option while inserting a user-specified value. This post has presented a complete process for solving the “ **can 't insert a non-default value into column id**” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-the-cant-insert-a-non-default-value-into-column-id-error-in-postgres/)

---

# How to Alter max_connections Parameter in PostgreSQL

> To alter the “max_connections” parameter in Postgres, the “ALTER SYSTEM SET max_connections = num_of_connections;” command is used.

PostgreSQL allows 100 concurrent connections by default. exceeding the stated number will result in an error stating "too many clients already". However, while working with Postgres, users may encounter a situation where they need to maximize the "max_connections". To deal with such situations, the ALTER SYSTEM command can be used alongside the SET clause.

This write-up will explain how to use the ALTER SYSTEM command in Postgres to change the value of the max_connections parameter.

 **How to Alter max_connections Parameter in PostgreSQL?**

To alter the “max_connections” parameter in Postgres, the ALTER SYSTEM command is used along with the SET clause followed by the number of maximum connections:
    
    
    ALTER SYSTEM SET max_connections = num_of_connections;

Follow the below-exhibited steps to change the max_connections parameter in Postgres:

 **Step 1: Show Max Connections**

Open the SQL Shell and type the following command to check the value of the max_connections parameter:
    
    
    SHOW MAX_CONNECTIONS;

The following snippet shows that the current value of the max_connections parameter is “100”:

 **Step 2: Alter Max Connections**

Type in the following ALTER SYSTEM command to modify the value of the “max_connections” parameter:
    
    
    ALTER SYSTEM SET max_connections = 125;

The below snippet illustrates that the value of the “max_connections” parameter is updated:

 **Step 3: Restart Postgres Server**

Restart the Postgres server to apply the desired changes. For this purpose, open the “services” app, locate “postgresql” service, and hit the restart button:

 **Step 4: Verify Altered Connections**

Verify the altered value of the max_connections parameter by executing the below-stated command:
    
    
    SHOW MAX_CONNECTIONS;

The following snippet shows that the value of the max_connections parameter has been successfully altered/incremented:

 **Note:** To optimize the performance of your application, it is preferred to adjust the value of the "shared_buffers" parameter as well. To do that, use the "ALTER SYSTEM SET shared_buffers = buffer_size;". Altering the buffer size will enhance the overall performance/efficiency of the system.

 **Conclusion**

To alter the “max_connections” parameter in Postgres, the “ **ALTER SYSTEM SET max_connections = num_of_connections;** ” command is used. After that, restart the Postgres server to apply the desired changes. For this purpose, launch the “services” app, select the “postgresql” service, and click the restart button. Users can verify the altered value of the “max_connections” parameter by executing the “SHOW MAX_CONNECTIONS;” command. This post has provided a complete guide on altering the value of the max_connections parameter.

---
[View this page online](https://www.commandprompt.com/education/how-to-alter-max_connections-parameter-in-postgresql/)

---

# What Does the LASTVAL() Function Do in PostgreSQL

> In PostgreSQL, “LASTVAL()” is a built-in function that retrieves the most recently generated sequence value of the current session.

In PostgreSQL, different inbuilt functions are used to work with the sequences. One such function is the “ **LASTVAL()** ” function which retrieves the most recently generated sequence value of the current session. The LASTVAL() function is session-specific which means it retrieves the last value of a sequence fetched within the current session only.

This write-up explains the use of the LASTVAL() function in Postgres.

 **What Does the LASTVAL() Function Do in PostgreSQL?**

The LASTVAL() function in PostgreSQL operates in a manner similar to the CURRVAL() function but with a notable distinction. The CURRVAL() function requires the specification of the sequence name, while the LASTVAL() function executes without a sequence name.

The reason for this distinction is that the LASTVAL() function in Postgres does not provide information about a specific sequence. Rather, it retrieves the value from the most recent usage of the NEXTVAL() function within the current session, irrespective of the particular sequence utilized.

 **Syntax**

To use LASTVAL() function, specify the function name along with a set of parentheses:
    
    
    LASTVAL();

The above syntax states that the stated function doesn’t accept any arguments.

 **Example 1: How to Use LASTVAL() Function in Postgres?**

In the following snippet, the NEXTVAL() function is invoked against the “example_1” sequence:
    
    
    SELECT NEXTVAL('example_1');

Now use the LASTVAL() function to get the value from the most recent usage of the NEXTVAL() function within the current session:
    
    
    SELECT LASTVAL();

The LASTVAL() function retrieves “1”, which is the last returned value of the NEXTVAL() function:

 **Example 2: LASTVAL is Not Yet Defined Error in Postgres**

If the NEXTVAL() is not used in the current session then invoking the LASTVAL() function will lead you to the following error:

That’s all about the usage of the LASTVAL() function in PostgreSQL.

 **Conclusion**

In PostgreSQL, “ **LASTVAL()** ” is a built-in function that retrieves the most recently generated sequence value of the current session. It is session-specific which means it retrieves the last value of a sequence fetched within the current session only. If the NEXTVAL() is not used in the current session then invoking the LASTVAL() function will lead you to the “LASTVAL is not yet defined” error. This post has explained how the LASTVAL() function works in Postgres.

---
[View this page online](https://www.commandprompt.com/education/what-does-the-lastval-function-do-in-postgresql/)

---

# How to Alter IDENTITY Column in PostgreSQL

> In PostgreSQL, the ALTER TABLE statement is used with ADD IDENTITY or DROP IDENTITY to add or remove an IDENTITY column to a Postgres table.

PostgreSQL 10 and subsequent versions introduce a new feature known as the “ **IDENTITY** ” column, enabling automatic incrementation of column values. The stated feature can be applied not only to new tables but also to existing tables. The **IDENTITY** column can be added or removed from a particular table using the **ALTER TABLE** command.

This write-up illustrates how to use ALTER TABLE statement to add or drop the IDENTITY column from a table.

 **How to Alter IDENTITY Column in PostgreSQL?**

The below-listed topics will be covered in this PostgreSQL blog:

\- Add IDENTITY Column

\- Remove IDENTITY Column

 **Example 1: Add IDENTITY Column**

Use the **ALTER TABLE** statement with the “ **ADD GENERATED AS IDENTITY** ” option to add/insert an IDENTITY column into an existing table. We have a sample table named “emp_info” with the following details:
    
    
    \d emp_info;

Consider the following example to learn how to add an IDENTITY column to an existing table using the ALTER TABLE statement:
    
    
    ALTER TABLE emp_info
    ALTER COLUMN emp_id
    ADD GENERATED BY DEFAULT AS IDENTITY;

To verify the table’s alteration, execute the below-provided meta-command with the table name:
    
    
    \d emp_info;

The IDENTITY column has been successfully added to the emp_info table:

 **Example 2: Remove the IDENTITY Column**

To drop or delete an IDENTITY column from a table, execute the ALTER TABLE statement with the DROP IDENTITY option:
    
    
    ALTER TABLE emp_info 
    ALTER COLUMN emp_id 
    DROP IDENTITY;

Let’s verify the table’s structure by running the “\d” command:
    
    
    \d emp_info;

The output shows that the IDENTITY column has been successfully removed from the emp_info table:

That’s all about altering an IDENTITY column in PostgreSQL.

 **Conclusion**

In PostgreSQL, the ALTER TABLE statement is used to add or remove an IDENTITY column to a Postgres table. Use the **ALTER TABLE** statement with the “ **ADD GENERATED AS IDENTITY** ” option to add/insert an IDENTITY column into an existing table. To drop or delete an IDENTITY column from a table, execute the ALTER TABLE statement with the DROP IDENTITY option. This post has illustrated how to add or remove the IDENTITY column of a table using the ALTER TABLE command.

---
[View this page online](https://www.commandprompt.com/education/how-to-alter-identity-column-in-postgresql/)

---

# How Do I Create an IDENTITY Column in PostgreSQL

> PostgreSQL 10 introduced a new feature named the &quot;IDENTITY&quot; column, which allows us to create a table’s column with auto-incrementing values.

PostgreSQL 10 and later versions include a new feature called the " **IDENTITY** " column, which allows for the auto-incrementing of column values. This feature provides similar functionality to the SERIAL type but offers greater flexibility and enhanced features. IDENTITY columns are essentially a standardized version of SERIAL columns in SQL.

This write-up will demonstrate a complete process of creating and using the **IDENTITY** column in PostgreSQL.

 **How Do I Create/Generate an IDENTITY Column in Postgres?**

In Postgres, an **IDENTITY** column comes with a built-in sequence. When a new record is added, a value is generated/created from the sequence and assigned to the identity column.

Follow the given syntax to create an identity column in Postgres:
    
    
    col_name TYPE GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY[ ( seq_option ) ]

In the given syntax:

\- Replace the TYPE with SMALLINT, INTEGER, or BIGINT.  
\- The "GENERATED ALWAYS" clause means always generate/create a new and unique value for the IDENTITY column. In that case, inserting or updating values in the IDENTITY column will lead you to an error.  
\- Using the "GENERATED BY DEFAULT" clause in the IDENTITY column allows us to insert or update user-specified values instead of relying on system-generated values.

 **Example 1: Creating GENERATED ALWAYS AS IDENTITY Column in Postgres**

In the following example, a table named “commandprompt_example” is created with the “id” and “blog_name” columns. The “GENERATED ALWAYS AS IDENTITY” clause is utilized in the below-provided code example to create an IDENTITY column:
    
    
    CREATE TABLE commandprompt_example(
    id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    blog_name TEXT
    );

The following screenshot shows the successful creation of the “commandprompt_example” table:

Let’s utilize the INSERT query to insert a couple of records into the “commandprompt_example” table:
    
    
    INSERT INTO commandprompt_example(blog_name)
    VALUES ('blog 1'),
    ('blog 2');

Fetch the newly inserted records to comprehend the working of the IDENTITY column:
    
    
    SELECT * FROM commandprompt_example;

The following snippet demonstrates that the auto-incrementing values have been successfully inserted into the “commandprompt_example” table:

Let’s insert a user-specified value in the IDENTITY column and see how it deals with that particular scenario:
    
    
    INSERT INTO commandprompt_example(id, blog_name)
    VALUES (3, 'blog 3');

An error occurred stating that we can’t insert or update an IDENTITY column that is created with the “GENERATED ALWAYS” clause:

 **Example 2: Creating a “GENERATED BY DEFAULT” Column in Postgres**

In the following code, the id column is an IDENTITY column that is created using the “GENERATED BY DEFAULT” clause:
    
    
    CREATE TABLE commandprompt_example_1(
    id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    blog_name TEXT
    );

Now insert and retrieve the data into the “commandprompt_example_1” table:
    
    
    INSERT INTO commandprompt_example_1(blog_name)
    VALUES ('blog 1'),
    ('blog 2')
    RETURNING *;

Let’s explicitly insert a value in the IDENTITY column and see how it deals with that particular scenario:
    
    
    INSERT INTO commandprompt_example_1(id, blog_name)
    VALUES (3, 'blog 3');

The below snippet shows that an explicit value has been successfully inserted into the “GENERATED BY DEFAULT AS IDENTITY” Column:

That’s all you need to know about creating an IDENTITY column in Postgres.

 **Conclusion**

PostgreSQL 10 introduced a new feature named the " **IDENTITY** " column, which allows us to create a table’s column with auto-incrementing values. To create an IDENTITY column in Postgres, all you need to do is use the " **GENERATED ALWAYS** " or " **GENERATED BY DEFAULT** " constraints with the IDENTITY column. This write-up has illustrated the complete process of creating an IDENTITY column in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-create-an-identity-column-in-postgresql/)

---

# How Does the SUM() Function Work With the GROUP BY Clause in PostgreSQL

> In PostgreSQL, the SUM() function can be executed with the GROUP BY clause to compute the sum of a particular column grouped by single or multiple columns.

**SUM()** is an aggregate function in Postgres that helps us find the sum of given numeric values. The SUM() function can be executed with the **GROUP BY** clause to calculate the sum of a particular column grouped by one or more columns. This process enables users to obtain aggregated results and perform analysis by comparing the sums of different groups.

This post will illustrate the use of the **SUM()** function alongside the **GROUP BY** clause in PostgreSQL.

 **How Does the SUM() Function Work With the GROUP BY Clause in PostgreSQL?**

Follow the below-provided syntax to use the **SUM()** function along with the **GROUP BY** clause in Postgres:
    
    
    SELECT col_1, col_2, SUM(col_name)
    FROM table_name
    GROUP BY col_1, col_2;

In the above syntax, **col_1** and **col_2** represent the columns of the table, while **col_name** represents the column to be summed. The **col_1** and **col_2** columns in the **GROUP BY** clause determine the criteria by which the table's data will be grouped for the sum calculation.

 **Example: Using SUM() With GROUP BY**

We have a sample table named " **emp_bio** " that will be used throughout this post:
    
    
    SELECT * FROM emp_bio;

The following result set shows the data of the “ **emp_bio** ” table:

In the following snippet, we utilize the SUM() function to calculate the total salary from the “emp_sal” column. After that, the GROUP BY clause is used to group the table’s data according to the employee's salary:
    
    
    SELECT joining_date, SUM(emp_sal) 
    FROM emp_bio
    GROUP BY joining_date;

The following snippet demonstrates that the employees’ salary is summed/grouped based on their joining date:

In the following snippet, the data of emp_bio table grouped based on the emp_salary column:
    
    
    SELECT emp_sal, SUM(emp_sal) 
    FROM emp_bio
    GROUP BY emp_sal;

This is how the GROUP BY clause is used with the SUM() function in Postgres.

 **Conclusion**

In PostgreSQL, the **SUM()** function can be executed with the **GROUP BY** clause to compute the sum of a particular column grouped by single or multiple columns. By doing so, users can obtain the aggregated results and perform analysis by comparing the sums of different groups. This guide has provided a detailed explanation of how to utilize the SUM() function alongside the GROUP BY clause in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-does-the-sum-function-work-with-the-group-by-clause-in-postgresql/)

---

# How to Increase Maximum Connections in PostgreSQL

> To increase maximum connections in PostgreSQL, open the configuration file, locate the “max_connections” variable in that file, and increase its value accordin…

PostgreSQL has a default limit of 115 concurrent connections, with 15 reserved for superusers and 100 available for regular users. If this limit is exceeded, it triggers the "FATAL: sorry, too many clients already" error, causing incoming connections to be rejected. To address this issue, the maximum number of connections must be increased.

This Postgres blog post will illustrate a practical guide to increasing the maximum number of connections in PostgreSQL.

 **How to Increase Maximum Connections in Postgres?**

In PostgreSQL, the information about the maximum number of concurrent connections is stored in the server variable/parameter named “max_connections”. It is located in the Postgres configuration file named “postgresql.conf”. You can modify this file to increase or decrease the connection limit according to your requirements.

Follow the given steps to increase maximum connection in Postgres:

 **Step 1: Open Postgres Configuration File**

Open the Postgres configuration file located at the following path in Windows: “ **C:\Program Files\PostgreSQL\\{Postgres installed version}\data\postgresql.conf** ”:

Double-click on the configuration file to open it:

 **Note:** You can execute the following command to see the path where the configuration file is located:
    
    
    show config_file;

 **Step 2: Increase Maximum Connections**

Locate the “max_connections” variable in the configuration file available under the “ **CONNECTIONS AND AUTHENTICATION** ” section. By default, its value would be “100”, as shown below:

Modify the “max_connections” value according to your needs:

After making the necessary modifications, save the changes to the “postgresql.conf” file and close it.

 **Step 3: Restart the PostgreSQL Server**

Restart the PostgreSQL Server to ensure that the new “max_connections” value takes effect. For this purpose, open the “services” app, locate the “PostgreSQL” service, and click on the “restart” button:

Once the PostgreSQL service is restarted, the changes you made will be applied and take effect.

 **Conclusion**

In PostgreSQL, the default limit of concurrent connections is 115, with 15 reserved for superusers and 100 available for regular users. However, users can increase the connection limit according to their needs. To do that, first, open the Postgres configuration file, locate the “max_connections” variable in the configuration file, and modify its value according to your needs. Restart the Postgres Server to implement the desired modifications. This write-up has illustrated how to increase maximum connections in PostgreSQL using practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-increase-maximum-connections-in-postgresql/)

---

# How to Specify the Start Value and the Increment Value for an IDENTITY Column in PostgreSQL

> Use the sequence option to specify the start value and the increment value for an IDENTITY column in PostgreSQL.

In PostgreSQL, version 10, a new constraint named “ **GENERATED AS IDENTITY** ” was introduced. The stated constraint enables the automatic assignment of unique numbers to a column. In addition to this, the “ **GENERATED AS IDENTITY** ” constraint allows us to specify the increment and start values for the IDENTITY column.

This blog post illustrates how to specify the starting and incrementing values for an identity column in PostgreSQL.

 **How to Specify the Start Value and the Increment Value for an IDENTITY Column in PostgreSQL?**

Use the sequence option to specify the start value and the increment value for an IDENTITY column in PostgreSQL. Follow the below syntax to specify the start value and the increment value for an IDENTITY column of a table:
    
    
    col_name TYPE GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY[ (START WITH start_val INCREMENT BY increment_val) ]

 **Example: Specify the Start Value and the Increment Value for an IDENTITY Column While Table Creation**

In the below example, the starting value and increment value are specified at the time of table creation:
    
    
    CREATE TABLE emp_example (
       emp_id INT GENERATED BY DEFAULT AS IDENTITY 
       (START WITH 5 INCREMENT BY 5),
       emp_name TEXT
    );

Let’s insert a couple of records into the “emp_example” table by executing the following INSERT statement:
    
    
    INSERT INTO emp_example (emp_name)
     VALUES ('john'),
     ('alex')
     RETURNING *;

Let’s insert some more records into the “emp_example” table. For this purpose, run the INSERT statement as follows:
    
    
    INSERT INTO emp_example (emp_name)
     VALUES ('joseph'),
     ('alexa')
     RETURNING *;

The following screenshot depicts that the value of the IDENTITY column is modified according to the specified start and increment values:

That’s all about enabling or setting the sequence of options in PostgreSQL.

 **Conclusion**

Use the sequence option to specify the start value and the increment value for an IDENTITY column in PostgreSQL. For instance, the “col_name TYPE GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY[ (START WITH start_val INCREMENT BY increment_val) ]” syntax is used in PostgreSQL to define an IDENTITY column with the start and increment values. This write-up has illustrated a thorough process for specifying the start and increment values for an IDENTITY column in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-specify-the-start-value-and-the-increment-value-for-an-identity-column-in-postgresql/)

---

# What Does the CURRVAL() Function Do in PostgreSQL?

> In PostgreSQL, “CURRVAL()” is a built-in function that returns the most recently retrieved value of the NEXTVAL() function for a specific sequence in the curre…

In PostgreSQL, a wide range of built-in functions are available to facilitate working with sequences. One such function is the “ **CURRVAL()** ” function which returns the most recently retrieved value of the NEXTVAL() function for a specific sequence in the current session. It is a session-specific function which means it will retrieve the last value of a sequence fetched within the current session only.

This write-up explains the use of the CURRVAL() function in Postgres.

 **What Does the CURRVAL() Function Do in PostgreSQL?**

The CURRVAL() function in PostgreSQL operates in a manner similar to the LASTVAL() function but with a significant distinction. The CURRVAL() function accepts the sequence name as an argument, while the LASTVAL() function doesn’t require any sequence name. This is because the CURRVAL() function specifically reports on the value of a particular sequence.

Use the below-depicted syntax to execute the “CURRVAL()” function:
    
    
    CURRVAL('seq_name');

The above syntax states that the stated function accepts sequence name as an argument.

 **Example 1: How to Use CURRVAL() Function in Postgres?**

In the below snippet, the NEXTVAL() function is invoked against the “example_1” sequence:
    
    
    SELECT NEXTVAL('example_1');

Use the CURRVAL() function with the sequence name to obtain the value from the latest invocation of the NEXTVAL() function in the current session:
    
    
    SELECT CURRVAL('example_1');

The CURRVAL() function retrieves “3”, which is the last returned value of the NEXTVAL() function in the current session:

 **Example 2: CURRVAL is Not Yet Defined Error in Postgres**

Let’s create a new sequence and apply the CURRVAL() function to it:
    
    
    CREATE SEQUENCE commandprompt;

If the NEXTVAL() is not used in the current session then directly invoking the CURRVAL() function will throw the following error:
    
    
    SELECT CURRVAL('commandprompt');

That’s all about the use of the CURRVAL() function in Postgres.

 **Conclusion**

In PostgreSQL, “ **CURRVAL()** ” is a built-in function that returns the most recently retrieved value of the NEXTVAL() function for a specific sequence in the current session. It is a session-specific function which means it retrieves the last value of a sequence fetched within the current session only. If the NEXTVAL() is not used in the current session then invoking the CURRVAL() function will cause the “CURRVAL is not yet defined” error. This post has explained how the CURRVAL() function works in Postgres.

---
[View this page online](https://www.commandprompt.com/education/what-does-the-currval-function-do-in-postgresql/)

---

# Can a User Override a SERIAL Column in PostgreSQL?

> Yes! A SERIAL column can be overridden by the user by explicitly specifying the column name and corresponding value in the INSERT statement.

In PostgreSQL, SERIAL is a pseudo-type that generates an auto-incrementing column. If you specify SERIAL as the data type for a column during table creation, PostgreSQL will automatically generate unique values for that particular column. However, occasionally users may need to override the default behavior of a SERIAL column. For this purpose, users must explicitly provide the column names and their corresponding values in the INSERT statement.

This post demonstrates how to override a SERIAL column in PostgreSQL using suitable examples.

 **Can a User Override a SERIAL Column in PostgreSQL?**

Yes! A SERIAL column can be overridden by the user. This can be done by explicitly specifying the name of the SERIAL column in the INSERT statement and providing a corresponding value for that particular column.

Consider the following steps for a profound understanding of overriding the SERIAL column:

 **Step 1: Create a SERIAL Column**

Let’s first create a SERIAL column. For this purpose, specify the “SERIAL” data type for a specific column at the time of table creation:
    
    
    CREATE TABLE command_prompt( 
    id SERIAL PRIMARY KEY, 
    name TEXT
    );

A table named “command_prompt” with a SERIAL data type has been successfully created:

 **Step 2: INSERT Data**

Now insert a couple of records in the command_prompt table by executing the following query:
    
    
    INSERT INTO command_prompt(name) 
    VALUES ('blog 1'), 
    ('blog 2'), 
    ('blog 3')
    RETURNING *;

The “RETURNING *” clause is used in the above query to get the newly inserted records:

From the above output snippet, you can observe that the id column is filled automatically with the sequence of unique values.

 **Step 3: Override the SERIAL Column**

Use the INSERT command, and explicitly specify the id column in it to override the SERIAL column:
    
    
    INSERT INTO command_prompt(id, name) 
    VALUES (5, 'blog 5')
    RETURNING *;

The following snippet demonstrates that the SERIAL column has been successfully overridden:

Let’s insert one more record in the “command_prompt” table for a profound understanding of the SERIAL column:
    
    
    INSERT INTO command_prompt(name)
    VALUES ('blog 6')
    RETURNING *;

It is clear from the output that when a new record is inserted, the auto-incrementing sequence of the serial column starts from where it left off:

That’s all about overriding a SERIAL column in PostgreSQL.

 **Conclusion**

Yes! A SERIAL column can be overridden by the user by explicitly specifying the name of the column in the INSERT statement and providing a corresponding value for that particular column. Overriding a SERIAL column allows us to specify a value of our choice instead of letting it automatically increase on its own. This write-up has demonstrated a complete guide on overriding a SERIAL column in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/can-a-user-override-a-serial-column-in-postgresql/)

---

# How to Fix “START value cannot be less than MINVALUE” When Creating a Sequence in PostgreSQL

> In PostgreSQL, to fix the “START value can’t be less than MINVALUE” error, make sure that the starting value of the sequence is equal to or greater than the MI…

In PostgreSQL, a sequence is a database object that is used to create a series of unique numeric values. However, when creating a sequence in Postgres, users may occasionally encounter an error stating that the “ **START value can’t be less than MINVALUE** ”. This error occurs at the time of sequence creation and the possible reason can be the start value is smaller than its minimum value.

This write-up illustrates how to solve the “ **START value can’t be less than MINVALUE** ” error in Postgres.

 **How to Fix the “START value can’t be less than MINVALUE” While Creating a Sequence in Postgres?**

Encountering an error message like "START value can't be less than MINVALUE" while creating a sequence indicates that the sequence's starting value is smaller than the specified minimum value. Here is an example that demonstrates this error:
    
    
    CREATE SEQUENCE cp_seq
    MINVALUE 10
    START 5;

To rectify this error, make sure that the starting value of the sequence is equal to or more/greater than the MINVALUE. For this purpose, either you can increment the start value or decrement the MINVALUE (or perform both tasks):
    
    
    CREATE SEQUENCE cp_seq
    MINVALUE 10
    START 10;

In the following code example, setting the starting value of the sequence to be equal to the minimum value effectively resolves the mentioned issue:

This time the desired sequence has been successfully created. Type the following meta-command to view the sequence structure:
    
    
    \d cp_seq;

That’s all about fixing the “START value can’t be less than MINVALUE” error in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “ **START value can’t be less than MINVALUE** ” error occurs at the time of sequence creation and the possible reason can be the start value is smaller than its minimum value. To fix this error, make sure that the starting value of the sequence is equal to or more/greater than the MINVALUE. For this purpose, either you can increment the start value or decrement the MINVALUE (or perform both tasks). This post has illustrated a complete process of fixing the “ **START value can’t be less than MINVALUE** ” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-start-value-cannot-be-less-than-minvalue-when-creating-a-sequence-in-postgresql/)

---

# How to Fix “currval of sequence is not yet defined in this session” Error When Calling CURRVAL() in PostgreSQL

> In PostgreSQL, the “currval of sequence is not yet defined in this session” error occurs when the NEXTVAL() function is invoked before the CURRVAL() function.

In PostgreSQL, the “ **CURRVAL()** ” function is a built-in function that aids in working with sequences. It retrieves the most recently obtained value from the “ **NEXTVAL()** ” function for a specific sequence within the current session. This function is session-specific, which means it only retrieves the last value of a sequence fetched within the current session. However, calling the CURRVAL() function before NEXTVAL() function in the current session will lead you to the “currval of the sequence is not yet defined in this session” error.

This write-up illustrates a complete process of fixing the “currval of sequence is not yet defined in this session” error in PostgreSQL.

 **How to Fix “currval of sequence is not yet defined” Error When Calling/Invoking CURRVAL() in Postgres?**

The stated error occurs when the **CURRVAL()** function is invoked before the **NEXTVAL()** function. For better understanding, let’s create a new sequence and apply the CURRVAL() function to it:
    
    
    CREATE SEQUENCE commandprompt;

The below snippet shows that when the NEXTVAL() function is not used in the current session then directly invoking the CURRVAL() function will throw the stated error:
    
    
    SELECT CURRVAL('commandprompt');

To fix the stated error, all you need to do is invoke the NEXTVAL() function before the CURRVAL() function at least once:
    
    
    SELECT NEXTVAL('commandprompt'),
    NEXTVAL('commandprompt');

In this example, the NEXTVAL() function is invoked a couple of times:

Now invoke the CURRVAL() function to see how it works:
    
    
    SELECT CURRVAL('commandprompt');

The output snippet shows that the “CURRVAL” function shows the last retrieved value of the NEXTVAL() function in the current session:

That’s all about fixing the “currval of sequence is not yet defined in this session” error in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “currval of sequence is not yet defined in this session” error occurs when the **CURRVAL()** function is invoked/called prior to the **NEXTVAL()** function. To fix the stated error, all you need to do is invoke the NEXTVAL() function before the CURRVAL() function at least once. This write-up has illustrated the complete process of fixing the “currval of sequence is not yet defined in this session” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-currval-of-sequence-is-not-yet-defined-in-this-session-error-when-calling-currval-in-postgresql/)

---

# How to Fix the “nextval: reached minimum value of sequence” Error in PostgreSQL

> To fix &quot;nextval: reached minimum value&quot; issue, various solutions like the &quot;Cycle&quot; option, changing the minimum value, etc. are used in Postgres.

In PostgreSQL, a commonly encountered error is the “ **nextval: reached minimum value** ” error, which occurs when working with descending sequences. Users encounter this error when a sequence reaches its minimum value and they attempt to generate a new value. Postgres provides several solutions for this issue, including resetting the sequence, modifying the minimum value of the sequence, repeating the sequence, and more.

This write-up illustrates various fixes for the “nextval reached minimum value” error in PostgreSQL.

 **How to Fix the “nextval: reached minimum value of sequence” Error in Postgres?**

We have already created a sequence named “decrement_seq” with the following details:
    
    
    \d decrement_seq;

In the following snippet, we invoked the nextval() function six times (more than the specified minimum value):
    
    
    SELECT nextval('decrement_seq'),
    nextval('decrement_seq'),
    nextval('decrement_seq'),
    nextval('decrement_seq'),
    nextval('decrement_seq'),
    nextval('decrement_seq');

Upon doing so, we will be prompted with the following error:

The following methods can be utilized in Postgres to rectify the “nextval: reached a minimum value” error:

  * Method 1: Create a Repeating Sequence
  * Method 2: Change the Sequence Minimum Value
  * Method 3: Use Default Minimum Value
  * Method 4: RESTART the Sequence



 **Method 1: Create a Repeating Sequence**

Use the cycle option to create a repeating sequence. By doing so, the sequence will restart once it reaches the minimum limit:
    
    
    ALTER SEQUENCE decrement_seq
    CYCLE;

Type the below-given command to see the modified structure of the “decrement_seq”:
    
    
    \d decrement_seq;

The below snippet demonstrates that the “cycles” option has been enabled, which means that the sequence will restart whenever it reaches the specified minimum value:

For more clarity, you can execute the nextval() function once more:
    
    
    SELECT nextval('decrement_seq');

Now, the sequence will reset to the beginning whenever it exceeds the MINVALUE:

 **Method 2: Change the Sequence Minimum Value**

Changing the minimum value of the sequence will also fix the said error:
    
    
    ALTER SEQUENCE decrement_seq
    MINVALUE -50;

The following snippet clarifies that the sequence has been successfully altered:

 **Method 3: Remove the Minimum Value**

Specify the NO MINVALUE option to set the default minimum value:
    
    
    ALTER SEQUENCE decrement_seq
    NO MINVALUE;

The provided screenshot indicates that the default minimum value has been set as the minimum value for the “decrement_seq” sequence:

 **Method 4: RESTART the Sequence**

Resetting the sequence value means starting the sequence again from the beginning. For this purpose, you can use the ALTER SEQUENCE command with the RESTART option:
    
    
    ALTER SEQUENCE decrement_seq
    RESTART;

The below screenshot proves that the sequence has been successfully altered:

That’s all about fixing the “reached minimum value of sequence” error.

 **Conclusion**

In PostgreSQL, encountering the " **nextval: reached minimum value** " error is a common occurrence when a sequence reaches its minimum value, and the user still tries to generate a new value. To fix this issue, various solutions are available in Postgres, including the "Cycle" option, changing the minimum value, removing the MINVALUE option, and utilizing the RESTART option. This post has illustrated different approaches to fix the "nextval: reached minimum value" error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-the-nextval-reached-minimum-value-of-sequence-error-in-postgresql/)

---

# How to Setup Amazon RDS Aurora Postgres Database

> To set up an Amazon RDS Aurora database, head into the RDS dashboard and create a database. Configure it by selecting the Aurora PostgreSQL-compatible engine.

AWS offers the user an Amazon RDS to create databases using multiple engines available on the platform. Amazon RDS allows the user to create a PostgreSQL database using either a PostgreSQL engine or an Aurora PostgreSQL-Compatible engine. The Aurora engine offers improvements in terms of performance due to its architectural patterns on the AWS RDS.

This guide will explain how to set up an Amazon RDS Aurora PostgreSQL-compatible database.

 **How to Setup Amazon RDS Aurora Postgres Database?**

To set up the Amazon RDS Aurora PostgreSQL Compatible database, head into the RDS dashboard from the AWS Management Console:

Start configuring the Amazon RDS database by clicking on the “ **Create database** ” button from the RDS dashboard:

Select the database creation option from the “ **Standard create** ” or “ **Easy create** ” options to begin the configuration process:

Select the “ **Aurora (PostgreSQL Compatible)** ” engine type from the “ **Engine options** ” section:

Scroll down the page to select the available versions of the Aurora PostgreSQL Compatible:

Choose the template of the database by selecting the environment of the instance and typing the database name:

Configure the credentials settings by typing the username and unchecking the box for Auto generating a password:

Type the password a couple of times to confirm the password for the database:

Choose the “ **Aurora Standard** ” cluster storage configuration options:

Configure the instance for the database from the “ **Instance configuration** ” section as displayed in the screenshot below:

Locate the “ **Connectivity** ” section and choose the Compute resource, Network type, and Virtual private cloud settings:

Select the DB subnet group and allow the public access to the RDS database:

Turn on the Performance insights which will be available for a week and the security will be done by the AWS KMS key offered by the service:

Review all the configurations and complete the database creation process by clicking on the “ **Create database** ” button:

The database has been created successfully with Aurora PostgreSQL Compatible engine:

That’s all about setting up an Amazon RDS Aurora PostgreSQL-compatible database.

 **Conclusion**

To set up an Amazon RDS Aurora PostgreSQL database, simply head inside the RDS dashboard from the AWS console. Select the database creation option to start the database creation process by configuring its engine type with its versions compatible with PostgreSQL. Select the template for the size of the instance and then type the name of the database for its identification. After that, review the configurations before completing the creation of the database.

---
[View this page online](https://www.commandprompt.com/education/how-to-setup-amazon-rds-aurora-postgres-database/)

---

# How to Connect to the Amazon RDS Aurora Postgres DB Instance

> Launch an EC2 instance and then create an AWS RDS database. Connect to the instance and use the database endpoint to connect to the RDS database.

AWS is the cloud-providing platform that is used by millions of individuals as well as industries to run IT-based resources on the cloud. The platform offers the Amazon Relational Database Service or RDS to create database resources on the cloud and use them. The user gets the Endpoints and port number to establish the connection to it and then runs SQL queries on it.

This post demonstrates the process of connecting to the Amazon RDS Aurora PostgreSQL-compatible DB instance.

 **How to Connect and Use the Amazon RDS Aurora Postgres DB Instance?**

To connect and use the Amazon RDS Aurora(PostgreSQL-Compatible) database in AWS, follow this simple guide.

 **Launch EC2 Instance**

The first step to connect to the RDS Aurora database is launching the EC2 instance from the service dashboard:

Head into the network settings and allow all traffic to only your IP:

Scroll down the page and review the configurations to complete the process by clicking on the “ **Launch Instance** ” button:

The EC2 instance has been created successfully and the user can view its summary by simply selecting the instance:

 **Create RDS DB Instance**

Head into the RDS dashboard from the AWS Management Console to start the process of creating a database:

Start the process of creating an Amazon RDS database by clicking on the “ **Create database** ” button from the RDS dashboard:

Select the creation method for the database from a couple of options provided by the platform such as “ **Standard create** ” and “ **Easy create** ” options. The user also needs to configure the type of engine for the database which in this case is the “ **Aurora (PostgreSQL Compatible)** ” engine:

After selecting the engine of the database, choose the size of the DB instance and configure the database identification settings:

Set up the EC2 connection to select the EC2 instance created earlier and establish a connection between them:

After completing all the configurations, review all the settings before clicking on the “ **Create database** ” button to complete the process:

Simply click on the name of the database after it is created successfully and its status is “ **Available** ”:

Head into the database summary page and locate the “ **Connectivity & security**” section to copy the endpoint and port for establishing the connection:

 **Connect AWS RDS Aurora Database**

Head back to the EC2 instances page to connect to the EC2 instance by clicking on the “ **Connect** ” button:

Connection of the EC2 can be established using multiple methods provided by the platform. Here we use the SSH client section to copy the command:

Use the copied query and paste it on the Windows terminal after changing the path of the private key pair file from the system:
    
    
    ssh -i "C:\Users\Lenovo\Desktop\tmkp.pem" ec2-user@ec2-13-215-248-102.ap-southeast-1.compute.amazonaws.com

Running the above code establishes a connection to the EC2 instance:

Use the following command to update the instance if there are any new updates available:
    
    
    sudo dnf update -y

Type the following command to install PostgreSQL 15 on the instance:
    
    
    sudo dnf install postgresql15

Running the above command will prompt the user to confirm the installation process by typing “ **y** ” on the terminal:

After that, simply use the following command to connect to the Amazon RDS Aurora PostgreSQL Compatible:
    
    
    psql --host=database.cluster-ro-c8t9edwt9w0h.ap-southeast-1.rds.amazonaws.com --port=5432 --username=postgres

The above code uses the hostname which is provided by the platform on the AWS RDS database page within the endpoint and then uses the port number with the username:

Once the user is connected to the AWS Aurora PostgreSQL database, simply use SQL queries to work on it:
    
    
    SELECT CURRENT_TIMESTAMP;

Executing the above command will display the current time of the PostgreSQL database:

That’s all about connecting to the Amazon RDS Aurora PostgreSQL-compatible database instance.

 **Conclusion**

To connect to the AWS RDS Aurora PostgreSQL database instance, launch an EC2 instance from the EC2 dashboard and head into the RDS dashboard. Create an AWS RDS Aurora PostgreSQL-Compatible database by setting up the connection to the EC2 instance. After that, connect to the EC2 dashboard and install PostgreSQL 15 on the EC2 instance and connect to the Aurora PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-connect-to-the-amazon-rds-aurora-postgres-db-instance/)

---

# How to Create an AWS RDS Aurora (PostgreSQL Compatible) DB in pgAdmin

> Create an AWS RDS database using an Aurora PostgreSQL-Compatible engine and use its endpoint to create a server on the pgAdmin from the local system.

Amazon Web Services (AWS) is widely accepted and one of the most popular cloud-providing platforms across the globe. It offers multiple services to get IT resources on the cloud which can be used remotely without having to purchase the actual infrastructure. To create databases and use them by connecting remotely, Amazon RDS is used on AWS.

This post will demonstrate the process of creating an AWS RDS Aurora database in pgAdmin.

 **Create an AWS RDS Aurora DB in pgAdmin**

To create an AWS RDS Aurora Compatible with the PostgreSQL database in pgAdmin, visit the RDS service:

Start the process of creating an RDS database by clicking on its button from the Amazon RDS dashboard:

Select the Easy Create method offered by the platform to only configure the necessary settings and everything else will be maintained by the platform:

Configure the size of the instance by choosing the **Dev/Test** option to use the database for testing or development and **Production** for heavy workloads. After that, type the name of the DB cluster and Master username for the identification of the database:

Provide the password for the database and type it twice to confirm it:

Review the configurations and complete the creation process before clicking on the “ **Create database** ” button:

After that, head into the summary of the database by clicking on its name:

The **Connectivity & security** section contains the endpoint and port to be used for establishing the connection on pgAdmin:

Open the “ **pgAdmin 4** ” application from the local system by clicking on the “ **Open** ” button:

Before using the application, it is required to enter the password to connect to the PostgreSQL server:

Head into the pgAdmin dashboard to Connect the Aurora server by clicking on the “ **Add New Server** ” button from the Quick Links section:

Type the name of the PostgreSQL server from the General section:

Head into the “ **Connection** ” section to type the Hostname/address, port, and password before clicking on the “ **Save** ” button:

The server connection has been established with the “ **postgres** ” database using pgAdmin 4:

That’s all about creating an AWS RDS Aurora PostgreSQL-compatible database in pgAdmin.

 **Conclusion**

To create an AWS RDS Aurora database in pgAdmin, head into the RDS dashboard and configure the Aurora database. Once the database is configured, the platform provides an endpoint with the port number that can be used to establish the connection to it. Open the pgAdmin application from the local system and use the endpoint and port number to add the server to it.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-an-aws-rds-aurorapostgresql-compatible-db-in-pgadmin/)

---

# How to Backup and Restore PostgreSQL Databases Using Command Line

> Open the terminal and head into the PostgreSQL directory. Use the pg_dump command to create a backup of the database and pg_restore to restore the database.

Backups can be used to keep a copy of important files and store it safely on the local system, external hard disk drive, or other storage device. These copies can be used to restore the original file if it is lost during any incident or deleted by mistake. PostgreSQL allows the user to create a backup of the databases created on its server and then restore it in case of any emergency.

This guide will explain how to backup and restore the PostgreSQL database using the command line.

 **How to Backup and Restore PostgreSQL Databases Using Command Line?**

To create a backup and then restore PostgreSQL databases using the command line, open the terminal from Windows:

Type the following command to head inside the “ **bin** ” directory of the PostgreSQL folder from the local system:
    
    
    cd C:\Program` Files\PostgreSQL\15\bin

Running the above code will direct the user inside the selected directory:

Inside the bin directory, use the following command to create a backup of the PostgreSQL database:
    
    
    pg_dump -U postgres -d JOIN > C:\Users\Lenovo\Desktop\JOIN.sql

The above code uses the **pg_dump** keyword to extract the databases into a scripting file from the PostgreSQL server. After that, the username of PostgreSQL and the name of the database to be backed up in the local system. The “>” is followed by the path of the directory from the local system where the backup file will be stored on the computer:

The backup file has been stored on the local system at the provided location:

Use the following command to connect to the PostgreSQL user:
    
    
    psql -U postgres

Executing the above query will prompt the user to enter the password to connect to the user:

After connecting to the “ **postgres** ” user, use the following command to remove a PostgreSQL database:
    
    
    DROP DATABASE "JOIN";

Running the above code will drop/delete the database from the Postgres user:

After deleting the “ **JOIN** ” database from the PostgreSQL server, create another database by typing this query:
    
    
    CREATE DATABASE "JOIN";

A new PostgreSQL database has been created:

Use the following query to restore the File from the local directory:
    
    
    pg_restore --dbname=JOIN --verbose C:\Users\Lenovo\Desktop\JOIN.sql

The above query contains the pg_restore keyword which is used to restore the database using the backed-up file. Type the name of the database and then enter the path of the backup file from the local system:

The database has been restored successfully as displayed in the screenshot below:

That’s all about backing up and restoring PostgreSQL databases using the command line.

 **Conclusion**

To back up and restore PostgreSQL databases using the command line, open the terminal from Windows and head into the PostgreSQL directory. Create a backup of the database using the “ **pg_dump** ” command and store it in the local directory on the computer. After that, delete/drop the PostgreSQL database and then create another database to get the restored files in. Use the “ **pg_restore** ” command to restore the file using the backed-up file stores in the local system.

---
[View this page online](https://www.commandprompt.com/education/how-to-backup-and-restore-postgresql-databases-using-command-line/)

---

# How to Fix “relation does not exist” Error in Postgres

> The &quot;relation does not exist&quot; error in PostgreSQL can occur when accessing a table, usually due to incorrect naming, misspelling, etc.

PostgreSQL is an RDBM system that is used for creating databases that store data in tabular form. In PostgreSQL, tables are also referred to as relations. The relations must be named correctly, otherwise, users may encounter an error message. Moreover, the table names are essential for accessing data from PostgreSQL, as they help us retrieve information from the tables.

This guide will explain how to fix the “relation does not exist” error in the PostgreSQL database.

 **How to Fix the “relation does not exist” Error in Postgres?**

The Error “relation does not exist” occurs in the PostgreSQL database when the user makes mistakes while calling the table name. The error message appears if the user has made a spelling mistake, uses the wrong spelling convention, etc. It can also give an error message if the relation is unavailable in the database. To fix the “relation does not exist” error in PostgreSQL databases, follow the simple steps mentioned below:

 **Prerequisite**

To use the PostgreSQL databases and tables, it is required to connect to its server using the following command:
    
    
    psql --username=postgres

Running the above command will prompt the user to enter the Master password for the PostgreSQL database:

After connecting to the Postgres user in the PostgreSQL server, head into the database by using the following command:
    
    
    \c JOIN

Executing the above command will direct the user inside the selected database:

Use the following command to get the list of all the tables available in the database with their names:
    
    
    \dt

 **Reason 1: Spelling Mistake**

A common mistake a user can make while calling the table in the PostgreSQL database is typing the wrong spelling as the following code block contains:
    
    
    SELECT * FROM Cars;

Running the above code displayed the error that the “relation “cars” does not exist”:

The spelling of the select table is “ **Car** ” not “ **Cars** ” so the user needs to write the exact spelling of the relations as displayed in the following code block:
    
    
    SELECT * FROM "Car";

 **Reason 2: Table is Not Available/Exist**

Access the data from the vehicles table using the following query:
    
    
    SELECT * FROM Vehicles;

Running the above code has displayed the “relation “vehicles” does not exist” error:

Use the following command to get the list of all the tables available in the database:
    
    
    \dt

The following are the tables available in the PostgreSQL database so the user can access only these tables:

Use the following command to access the “ **employee** ” table from the PostgreSQL database:
    
    
    SELECT * FROM employee;

That’s all about solving the stated error in PostgreSQL when the query cant fetch a table from the database.

 **Conclusion**

To fix the “ **relation does not exist** ” error in the PostgreSQL database, simply connect to the PostgreSQL server and head into the database. After that, check all the tables/relations available on the database by using the “ **\dt** ” command to get the names of all the tables. After getting the list of all the tables, simply use the correct spelling and case convention to call the table. This guide has explained the process to solve the “relation does not exist” error in PostgreSQL databases.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-relation-does-not-exist-error-in-postgres/)

---

# JSON Functions and Operators in PostgreSQL

> JSON is the data type in the PostgreSQL database and it can be used to store data in a human-readable textual form which is different from other formats.

In PostgreSQL, data is stored in the tables using columns and rows and each column has a specific name that stores a specific type of data. JSON is a type of data in PostgreSQL that is more useful and efficient in storing data in the PostgreSQL database. JSON keeps the data as key-value pairs. To query JSON data various operators and functions are utilized in Postgres.

This guide will explain the process of using JSON functions and operators in PostgreSQL.

 **JSON Functions and Operators in PostgreSQL**

Postgres support various built-in functions and operators to fetch data using queries from JSON columns. This post will demonstrate the following concepts regarding JSON functions and Operators:

\- Use JSON Data Type in Table  
\- How to Use JSON Operators in Postgres?  
\- How to Use JSON Functions in Postgres?

 **Use JSON Data Type in Table**

Use the following command to create a PostgreSQL table to use JSON data type with its field:
    
    
    CREATE TABLE product (
      prod_id serial NOT NULL PRIMARY KEY,
      description json
       );

The above code creates a table named “ **product** ” and it contains a couple of fields which are “ **prod_id** ” and “ **description** ”. The **prod_id** column is a **primary key** of the table and its data type is **serial** which means that its values will be auto-incremented in a specific order. The **description** field has the data type **JSON** , which means users can apply JSON **operations** and **functions** on it:

Use the following command to insert values in the product table:
    
    
    INSERT INTO product (description)
     VALUES('{ "Laptop": "Lenovo", "Specifications": {"RAM": "10GB","color": "Black"}}'),
     ('{ "Laptop": "Lily Bush", "Specifications": {"RAM": "8GB","color": "Silver"}}'),
     ('{ "Laptop": "Josh William", "Specifications": {"RAM": "6GB","color": "Black"}}'),
      ('{ "Mouse": "Mary Clark", "Specifications": {"Wires/Wireless": "Wireless","color":   "Black"}}');

The above code inserts values in the **description** field which has the **JSON** data type so it contains the **description** of the product such as the **name** of the product and its **specifications** :

Use the following command to fetch the data stored in the description field of the product table:
    
    
    SELECT description
    FROM product;

The above code displays the data stored in the description field with JSON data type:

 **How to Use JSON Operators in Postgres?**

Once the data is stored in the table, use the following code to use JSON operators which in this case is the “ **- >**” operator:
    
    
    SELECT description -> 'Specifications' 
    AS Specifications
    FROM product;

The above code uses the “ **- >**” operator to select a specific key named “Specifications” of the “Description” column:

The following code uses two JSON operators which are “ **- >**” and “ **- >>**” to get the data from the JSON field:
    
    
    SELECT description ->> 'Laptop' AS Laptop
    FROM product
    WHERE description -> 'Specifications' ->> 'RAM' = '8GB';

The above code fetches the data from the **description** field which is stored as the **Laptop** where the **RAM** size is **8GB.** The “ **- >**” operator is used to get the JSON data by key and the “ **- >>**” operator fetches the data as text:

 **How to Use JSON Functions in Postgres?**

After using the JSON operators, the following query uses JSON functions to get data from the table:
    
    
    SELECT json_typeof(description -> 'Specifications')
    FROM product;

The above code uses the **json_typeof()** function which is used to return the **type** of the JSON value which in this case is the “ **object** ” data type:

Execute the following query to use another JSON function which is the **json_each()** function in PostgreSQL:
    
    
    SELECT json_each (description)
    FROM product;

The above code contains the **json_each()** function which enables the user to expand the JSON objects into multiple rows. The above functions separate the JSON field and divide the Laptop and specification section into multiple rows:

Run the following query to use the json_object_keys() function in PostgreSQL:
    
    
    SELECT json_object_keys (description->'Specifications')
    FROM product;

The json_object_keys() function allows the user to get the set of keys from the “specifications” object of the description field:

That’s all about JSON functions and operators in PostgreSQL.

 **Conclusion**

JSON is a data type to store data in the PostgreSQL database that is used when the user has to keep it in the textual format. PostgreSQL provides multiple JSON operators which can be used with SQL queries to fetch data from the JSON column in the table. It also provides different JSON functions to perform specific operations on the JSON field. This guide has explained the process of using JSON functions and operators to query the data stored in the JSON field.

---
[View this page online](https://www.commandprompt.com/education/json-functions-and-operators-in-postgresql/)

---

# How to Change Default Port in PostgreSQL

> Connect to the PostgreSQL server, get the port number to which the user is connected, and change the port number from the “postgresql.conf” file from a compute…

Ports are used to establish connections remotely between multiple nodes in a network to transfer data or perform some computational operations. PostgreSQL is generally running on the port number “ **5432** ” and the user can simply connect to the PostgreSQL server using this port. The platform allows the user to change its default port if somehow “ **5432** ” is not responding or is occupied elsewhere.

This guide will explain how to change the default port in PostgreSQL.

 **How to Change Default Port in PostgreSQL?**

To change the port of the PostgreSQL, connect to the PostgreSQL database using the following query:
    
    
    psql -U postgres

Running the above query will prompt the user to enter the master password for the Postgres user:

Use the following command to get all the data from the pg_settings view and use the WHERE clause to get the data about the port:
    
    
    select * from pg_settings where name='port';

Running the above query displays the default port which is “ **5432** ” of the PostgreSQL database:

Use the following command to get the port for the database and the user to which you are connected:
    
    
    \conninfo

Type the following command to get the location of the file where the default port is stored:
    
    
    show config_file;

The above command displays the path of the file where the port is saved:

Quit the PostgreSQL and head into the data directory of the PostgreSQL from the local system:
    
    
    cd C:\Program` Files\PostgreSQL\15\data

Find the port number from the “ **postgresql.conf** ” file:
    
    
    cat postgresql.conf | findstr 'port'

The port on each of the files on which the PostgreSQL database is running is “ **5432** ” so it is the default port for the PostgreSQL:

Locate the “ **postgresql.conf** ” file from the local system and open it:

Locate the port number from the file and change it from “ **5432** ” to “ **6543** ” before saving it:

After saving the file, use the following command again to get the updated port number:
    
    
    cat postgresql.conf | findstr 'port'

The above command displays the “ **6543** ” port number:

Open the “ **Run** ” application from the local system:

Type the “ **services.msc** ” and click on the “ **OK** ” button:

Locate the PostgreSQL file, select it, and click on the “ **Restart** ” button:

Once the service is restarted head inside PostgreSQL and type the following command:
    
    
    select * from pg_settings where name='port';

The default port has been changed successfully as displayed in the screenshot below:

That’s all about changing the default port in the PostgreSQL database.

 **Conclusion**

To change the default port in PostgreSQL, simply connect to the PostgreSQL server by providing the master password for the user. After that, get the specific data about the port from the pg_settings view to get the default port number on which it is running. Use the “show config_file” command to get the path of the file and then change the port number from that file. Restart the service from the “ **service.msc** ” application and check the updated default port number.

---
[View this page online](https://www.commandprompt.com/education/how-to-change-default-port-in-postgresql/)

---

# How to Execute Stored Procedure With Parameters in PostgreSQL

> Connect to the PostgreSQL database and head into the properties of the procedure. Locate the parameters and use them as arguments while calling the procedure.

Procedure in PostgreSQL is a user-defined function that can be created using the list of parameters and the body of the function. The function body contains the steps that will be performed upon its execution to manipulate PostgreSQL tables. Calling the function by its name will result in its execution to complete the transactional operation and complete the process each time.

This guide will explain how to execute stored procedures with parameters in PostgreSQL.

 **How to Execute Stored Procedure With Parameters in PostgreSQL?**

To execute the stored procedure with parameters in PostgreSQL, open the pgAdmin application from the local system:

Type the master password to connect to the PostgreSQL server and click on the “ **OK** ” button:

Head into the public Schema of the database and expand the procedures section to open it by right-clicking on it. Click on the “ **Properties** ” button from the options menu of the stored procedure:

Click here to learn how to create a procedure in PostgreSQL.

Head into the “ **Definition** ” section to get the argument list of the procedure:

Check the body of the procedure from the “ **Code** ” section which contains multiple steps to perform transactions. Calling it would take the amount from the receiver and adds it to the receiver’s account:

Use the following query to get the data from the **accounts** table:
    
    
    SELECT * FROM accounts;

The above command displays the data stored in the table:

 **Calling a Procedure**

Use the following command to call the stored procedure using its name and arguments:
    
    
    call transfer(1,2,1000);

The above command uses the call keyword followed by the **name** of the stored procedure and then comes the **list of the parameters**. The parameter list contains three arguments which are the **sender** , **receiver** , and the **amount** separated by commas:

Use the following command to get the data stored in the accounts table after the transaction is complete:
    
    
    SELECT * FROM accounts;

The following screenshot displays that **1000** is deducted from **Ross** ’ account and added to **Taylor’s** account:

That’s all about executing a stored procedure with parameters in PostgreSQL.

 **Conclusion**

To execute a stored procedure with parameters in PostgreSQL, open the pgAdmin application from the local computer and connect to the database. Open the properties of the procedure and get the parameters that will be used while calling the stored procedure. Use the “ **call** ” statement with the name and parameters of the procedure to execute the procedure in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-execute-stored-procedure-with-parameters-in-postgresql/)

---

# How to Create a Read-Only User in PostgreSQL

> To create a read-only user in PostgreSQL, create a role in the PostgreSQL database and grant read-only permissions to it. Create a user and grant the Role to i…

In PostgreSQL, a user is created to give login permission and with that, the user can be able to access some parts of the database. The user is like a profile that can be used for multiple purposes like read-only access as it only has permission to read the data. The root user has all the access control that can be divided between multiple users to perform their specific tasks.

This guide will explain how to create a read-only user in a PostgreSQL server.

 **How to Create a Read-Only User in PostgreSQL**

To create a read-only user in the PostgreSQL database, simply follow the following simple and easy steps:

 **Step 1: Create a Role**

Open the PostgreSQL client from the local system or connect to it from the Terminal and use the following query to create a Role:
    
    
    CREATE ROLE readaccess;

Running the above query has created a role in the PostgreSQL database:

 **Step 2: Assign Multiple Permissions**

Once the Role is created, grant a few permissions to it, starting by running the following command:

> [ **Contact us**](<https://commandprompt.com/contact-us/>) **today for all your Postgres and Open Source consulting and support needs.**  
> 
    
    
    GRANT CONNECT ON DATABASE postgres 
     TO readaccess;

The above code will grant the role with permission to connect to the Postgres database:

Use the following command to grant second permission to the role:
    
    
    GRANT USAGE ON SCHEMA public TO readaccess;

Executing the above code will allow the role to use the public schema of the Postgres database:

Use the following command to grant permissions to access the tables in the database:
    
    
    GRANT SELECT ON ALL TABLES IN SCHEMA public TO readaccess;

Running the above code will enable the Role to use all the tables from the public Schema:

 **Step 3: Create Read-Only User**

After all the permissions are assigned to the Role, simply use the following command to create a user in PostgreSQL with its password attach to it:
    
    
    CREATE USER read_user WITH 
    PASSWORD 'abc12345';

Running the above code will create a user that has the password set at the time of its creation:

Grant the role to the user to assign all the permissions that are attached to the role:
    
    
    GRANT readaccess TO read_user;

Running the above query will grant the Role to the user and with it all the permissions granted to the role will automatically be attached to the user:

That’s all about creating a Read-Only user in PostgreSQL.

 **Conclusion**

To create a read-only user in the PostgreSQL database, simply connect to the PostgreSQL server and type the query to create a Role in the PostgreSQL database. Use the role as the permission role by granting it all the read permissions such as Connecting to the database, Accessing schema, and tables in it. Create a user and grant the role to the user which makes it a read-only user in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-read-only-user-in-postgresql/)

---

# JSONB Data Type in PostgreSQL

> JSONB is the binary format of storing and exchanging data in JSON syntax which is a human-readable format and PostgreSQL allows the use of JSONB data types.

JSON or JavaScript Object Notation is a lightweight format for storing and transporting data in the form of text. It is used when the data is sent from the server to a particular web page and the user can extract data from the text using JSON syntax. JSON text is human-readable and PostgreSQL supports the JSON data types while creating tables or updating columns in the PostgreSQL table.

This guide will explain JSONB data types in the PostgreSQL database.

 **JSONB Data Type in PostgreSQL**

It was becoming difficult for PostgreSQL to process and analyze the huge amount of textual form of data so they opted for the binary form of JSON. JSONB in PostgreSQL is a data type that can be used to store data in decomposed binary format. It also enhances/improves performance significantly as it simplifies schema designs and provides efficiency by creating indexes on JSONB columns.

 **Example 1: How to Create a Table With JSONB Data Type**

Use the following query to create a table that uses JSONB data type for one of its columns:
    
    
    CREATE TABLE emp (
     emp_id int NOT NULL,
     data jsonb
     );

The above code creates a PostgreSQL table called “ **emp** ” and it contains two columns that are **emp_id** and **data**. The **emp_id** column has the **int** data type and it has the constraint of not having a NULL value at any time. The **data** field has the datatype of the **jsonb** so it can contain multiple values or a list in the field:

Once the table is created successfully, the user needs to insert values in it using the following query:
    
    
    INSERT INTO emp VALUES 
     (1, '{"name": "John", "hobbies": ["Movies", "Football", "Hiking"]}'), 
     (2, '{"name": "Marc", "hobbies": ["Gaming", "Movies", "Music"]}');

The above code inserts two rows containing the information regarding employees’ **ids** , **names,** and **hobbies** :

Type the following query to get all the data stored in the emp table:
    
    
    SELECT * FROM emp;

Running the above code displays the data stored in the **emp** table containing the JSONB datatype:

 **Example 2: How to Fetch the Specific Key of a JSONB Object**

The " **- >**" operator in Postgres retrieves the value of a specific key/index from a JSONB object or array stored in a JSONB field. Use the following command containing the **- >** operator to get the name from the data column and display it on the screen:
    
    
    SELECT data->'name' FROM emp;

Running the above code only displays the names of the employees from the JSONB column:

Use the following query to get the list of hobbies from the data column:
    
    
    SELECT data->'hobbies' FROM emp;

Executing the above code has displayed the list of hobbies for both employees:

 **Example 3: How to Fetch Specific Data From a JSONB Column**

Use the following command to get the specific key’s data from the selected column:
    
    
    SELECT data->'hobbies' FROM emp 
     WHERE data->'name' = '"Marc"';

The above code will display only **hobbies** from the data column of the employee “ **Marc** ”:

 **Example 4: Display a List of Hobbies**

Use the following code to get the list of all the hobbies stored in the table:
    
    
    SELECT jsonb_array_elements_text(data->'hobbies') 
     AS hobbies FROM emp;

Running the above query displays the list of all the hobbies in a separate cell:

Use the following query to get the **hobbies** but with their representation according to the **emp_id** column:
    
    
    SELECT emp_id, jsonb_array_elements_text(data->'hobbies') 
    AS hobbies FROM emp;

The above code displays the list of all the hobbies with reference to the emp_id column as each hobby belongs to a particular employee:

 **Example 5: Use @ Operator With WHERE Clause**

Use the “ **@** ” operator to get data from the employee table with reference to a particular hobby:
    
    
    SELECT emp_id, data FROM emp 
     WHERE data->'hobbies' @> '["Gaming"]'::jsonb;

The above query only displays the data of the employee whose hobby list contains “ **Gaming** ” data:

Use the following query to get the list of employees who has the hobby of watching “ **Movies** ”:
    
    
    SELECT emp_id, data FROM emp 
    WHERE data->'hobbies' @> '["Movies"]'::jsonb;

The above query displays that both employees have the hobby “ **Movies** ” in their data list:

That’s all about the JSONB data type in the PostgreSQL table.

 **Conclusion**

JSONB data type is used to create columns in the PostgreSQL table like other types such as integer, character, etc. A JSONB data type column can store a list of data in a single field like the example from this guide displays the name and hobbies in the same column. The user can get data from the JSONB column using different operators like “ **- >**” and “ **@** ”. This guide has explained the JSONB data type in PostgreSQL and different examples to use it.

---
[View this page online](https://www.commandprompt.com/education/jsonb-data-type-in-postgresql/)

---

# A Complete Guide to UUIDs in PostgreSQL

> Universal Unique Identifiers or UUID data types generate random values to be stored in the PostgreSQL database table. The user needs to create its extension be…

PostgreSQL database management system provides many data types like string, integer, character, etc. to store the data in the tables. One such data type is the UUID which is easier and more useful as it can be used to store randomly generated values while creating an application. It is unlikely that the UUID-generated numbers can repeat in the known universe as these are generated through an algorithm.

This guide will explain the use of UUIDs in the PostgreSQL database.

 **A Complete Guide to UUIDs in PostgreSQL**

UUID or Universal Unique Identifiers data types are used to generate random values which are not sequential and are of 128 bits storage. Randomly generated identities are more secure as they are difficult to perform enumeration attacks on. It is much more difficult to find the order of the table for a random person who does not have any idea about the schema of the PostgreSQL database.

The following are some randomly generated UUID values:
    
    
    b91cd23b-861c-4cc1-9119-801a4dac1cb9
    99fa6aba-1a78-457b-a333-052aa40f5544
    a4ae62b8-6615-48b5-a1b0-a05ddba7492c

The UUIDs are the 32-bit identifiers separated into 5 blocks using hyphens and it contains hexadecimal values.

 **Example 1: Generate UUIDs**

To generate random identifiers in Postgres using the UUID, it is required to create its extension first using the following query:
    
    
    CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

Running the above code will create an extension as it does not come by default with the database:

After creating the extension, the platform has provided the user with these UUID functions which can be used to generate random identifiers:

Use the following UUID function to get the 32-bit UUID:
    
    
    SELECT uuid_generate_v1();

The above code will display a 32-bit UUID on the screen after its execution:

Use the following function to generate random UUID in PostgreSQL:
    
    
    SELECT gen_random_uuid();

 **Example 2: UUID in PostgreSQL Table**

After generating UUIDs randomly, use the following command to use UUID in the PostgreSQL table:
    
    
    CREATE TABLE songs (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      name VARCHAR(50),
      description TEXT,
      created_at TIMESTAMP DEFAULT now()
       )

The above code will create a table named songs and its id field is the primary key of the table. The data type of the id column is UUID and it will generate random values as the id of the songs for each record. The other fields in the above table are the name of the song, its description, and the timestamp of the record creation/insertion:

After the table is created, simply insert data into it using this query:
    
    
    INSERT INTO songs (name, description)
     VALUES ('Bohemian Rhapsody', 'A classic rock ballad'),
      ('Shape of You', 'A popular pop song'),
      ('Thunderstruck', 'A hit rock song');

The above query will insert values in the songs table and we will only provide/insert the name and description of the table. The table's id will be generated randomly using the UUID data type and the current timestamp will be stored (by default) in the created_at column using the NOW() function:

After that, simply use the following command to display the data stored in the songs table:
    
    
    SELECT * FROM songs;

Running the above code displays the randomly generated id and inserted data with the timestamp attached:

That’s all about UUID data type and its use in the PostgreSQL database.

 **Conclusion**

Universal Unique Identifiers or UUID data types generate random values to be stored in the PostgreSQL database table. The user needs to create its extension before using it to generate 32-bit identifiers on the screen. Create a table and set the data type of the id as the UUID to generate a random value for each record to keep the database more secure. This guide has explained the UUID data types and their use in the PostgreSQL table.

---
[View this page online](https://www.commandprompt.com/education/a-complete-guide-to-uuids-in-postgresql/)

---

# How to Solve the FATAL: Password Authentication Failed for User "Postgres" Error

> Open the “pg_hba.conf” file from the local system and change the security method. Restart the application and change the password from the PostgreSQL server.

PostgreSQL is an open-source database management system that allows the user to create relational databases using different CLI or GUI applications. The user will need to set the credentials for the servers which will be required while accessing the PostgreSQL server at any moment. Additionally, it enables the user to alter the passwords and credentials if the user has lost them.

This guide will explain how to solve the password authentication error for the user in PostgreSQL.

 **How to Solve the FATAL: Password Authentication Failed for User Postgres Error?**

This error occurs in the PostgreSQL client application when the user provides the wrong password while connecting to the server:

To rectify the stated error, first, open the Notepad from the computer by clicking on the “ **Run as administrator** ” button:

Expand the “ **File** ” menu from the notepad and click on the “ **Open** ” button or press Ctrl+O from the keyboard:

Head into the “ **data** ” folder from the “ **PostgreSQL** ” directory to select the “ **pg_hba.conf** ” file and click on the “ **Open** ” button:

Scroll down to the bottom of the file to copy the last section of the file and store it on the local system:

After that, change the “ **scram-sha-256** ” with the “ **trust** ” keyword in the “ **METHOD** ” column, and click on the “ **Save** ” button from the “ **File** ” menu:

Open the “ **Run** ” dialog box from the local system:

Type the “ **services.msc** ” and click on the “ **OK** ” button:

Locate the “ **PostgreSQL** ” file from the list of all the services to click on it and then click on the “ **restart** ” button:

Restart the PostgreSQL client and it will allow the user to access the Postgres database to open the “ **Query Tool** ”:

Run the following query to change the password of the “ **postgres** ” user and then access the server using the newly provided password:
    
    
    ALTER USER postgres WITH PASSWORD 'postgres';

Head back to the “ **pg_hba.conf** ” file from the “ **PostgreSQL** ” directory to select and change the “ **trust** ” with the “ **scram-sha-256** ” keyword:

Open the “ **Run** ” application one more time from the system:

Head into the “ **services.msc** ” page by clicking on the “ **OK** ” button:

Select the PostgreSQL file and click on the “ **Restart** ” button:

Open the PostgreSQL client to use the password and click on the “ **OK** ” button:

That’s all about solving the password authentication error while connecting to the server.

 **Conclusion**

To solve the Fatal: password authentication failed for the user “postgres” error while connecting to the server, simply open the “ **pg_hba.conf** ” file. Change the values in the method column from the last section and then restart the PostgreSQL application from the “ **services.msc** ” application. Open the PostgreSQL client and change the password to log in to the server. This guide has explained the process of solving the password authentication failed error while connecting to the PostgreSQL server.

---
[View this page online](https://www.commandprompt.com/education/how-to-solve-the-fatal-password-authentication-failed-for-user-postgres-error/)

---

# Procedures Vs. Functions in PostgreSQL

> The major difference between a Procedure and a Function in PostgreSQL is that the Procedure does not return the value and the function does return it.

PostgreSQL allows the user to create tables and perform queries to fetch data from these tables and gain useful insights using the data. PostgreSQL allows the use of built-in functions as well as the creation of new functions and procedures to manage PostgreSQL tables. Functions and stored Procedures serve almost similar functionalities but there are a few differences between them.

This guide will explain the difference between Procedure and Function in PostgreSQL using examples.

 **Procedure Vs Function in PostgreSQL**

Procedures are a set of instructions that take a certain input and apply actions on it which are provided in its body. The procedure does not return any value on calling it however it performs the action and updates the values in the said table. Whereas, the function also takes input and performs some tasks to return the value while executing the calling query.

The Procedures can’t be called with other SQL queries whereas the function can be called within SQL queries to get the value in return. The procedure is compiled once and can be called many times to perform multiple tasks in order.

 **Create PostgreSQL Table**

Use the following code to create a table in the PostgreSQL database to use Procedure and Function on it:
    
    
    CREATE TABLE employees (
      id SERIAL PRIMARY KEY,
      name VARCHAR(50),
      age INT,
      salary DECIMAL(10, 2),
      department_id INT
       );

The above code creates a table named **employees** with multiple fields such as **id** , **name** , **age** , **salary** , and **department_id**. Each field has its data type according to the data to be stored in it and the **id** is set to be the **primary key** of the table:

Use the following code to insert data in the above-created table:
    
    
    INSERT INTO employees (name, age, salary, department_id)
       VALUES ('AB De-Villiers', 30, 5000.00, 1),
      ('Steve Smith', 28, 6000.00, 1),
      ('Michael Johnson', 35, 8000.00, 2),
      ('Ollie Robinson', 32, 5500.00, 2);

The output snippet clarifies that four records have been inserted into the selected table:

Use the following command to fetch the data stored in the employees' table:
    
    
    SELECT * FROM employees;

The above code displays the data available in the "employees" table:

 **How to Use a Procedure in PostgreSQL?**

After creating and inserting data in the PostgreSQL table, create a procedure to increase the salary of the employee:
    
    
    CREATE OR REPLACE PROCEDURE increase_salary_by_percentage(
      IN percentage DECIMAL(5, 2)
       )
     LANGUAGE plpgsql
     AS $$
     BEGIN
      UPDATE employees
      SET salary = salary + (salary * (percentage / 100));
     END;
       $$;

The above code creates a procedure named “ **increase_salary_by_percentage** ” using the SQL procedural language. The body of the procedure suggests that on calling it, the procedure should update the salary of the employee and adds a specific percentage of the current salary:

Simply call the stored procedure by specifying the increment percentage as an argument:
    
    
    CALL increase_salary_by_percentage(10.0);

The above code increases the salary of the employee by 10 percent as provided in the argument while calling the procedure:

Use the following code to get the updated table of PostgreSQL:
    
    
    SELECT * FROM employees;

The following screenshot displays the increased salary by 10 percent which happened after calling the procedure:

 **How to Use a Function in PostgreSQL?**

Create a function in PostgreSQL by using the following code:
    
    
    CREATE OR REPLACE FUNCTION get_average_salary()
     RETURNS DECIMAL(10, 2)
     LANGUAGE plpgsql
     AS $$
     DECLARE
      average_salary DECIMAL(10, 2);
     BEGIN
      SELECT AVG(salary) INTO average_salary
      FROM employees;
     RETURN average_salary;
     END;
       $$;

The above code creates a function named get_average_salary() which returns the value in decimal format using the SQL language. The body of the function suggests that the function will return the average salary from the employees' table:

Use the following code to call the function:
    
    
    SELECT department_id, get_average_salary() AS average_salary
     FROM employees
     GROUP BY department_id;

The above code fetches the data from the **department_id** to apply the function on the **employees '** table and then uses **GROUP BY** clause on the **department_id**. Running the above code displayed the average salary of each department on calling the PostgreSQL function:

That’s all about Procedure and Functions in PostgreSQL and it has been explained with examples.

 **Conclusion**

The major difference between a Procedure and a Function in PostgreSQL is that the Procedure does not return the value and the function does return it. The Procedures can’t be called with other SQL queries whereas the function can be called within SQL queries to get the value in return. This post demonstrated the difference between a Procedure and a Function in PostgreSQL using examples.

---
[View this page online](https://www.commandprompt.com/education/procedures-vs-functions-in-postgresql/)

---

# The CREATE PROCEDURE Statement in PostgreSQL

> The CREATE PROCEDURE Statement contains the name of the procedure with its arguments. The body of the procedure contains steps to be performed.

PostgreSQL Database management system is one of the most popular object-relational DB systems as it is open-source and free. It allows the use of functions/methods to perform specific tasks defined in the function according to the requirement to manage tables. PostgreSQL Functions are called Procedures and are used to perform a task consisting of multiple steps which would normally take several queries.

This guide will explain how to use a CREATE PROCEDURE statement in Postgres along with suitable examples.

 **CREATE PROCEDURE Statement in PostgreSQL**

Functions can be of two types; Built-in functions and user-defined functions and the user is allowed to use these functions. Built-in functions in PostgreSQL are not designed to perform transactional operations so to solve this problem a procedure can be created. The Procedure can be called multiple times and it performs the same set of operations on the PostgreSQL table every time.

 **Syntax**

The following is the syntax to create a procedure in PostgreSQL:
    
    
    create [or replace] procedure procedure_name(parameter_list)
    --Body of the Procedure with language SQL
     language plpgsql
     as $$
     declare
     -- variable declaration
     begin
     -- stored procedure body
     end; $$

In the above code snippet:

\- The **create [or replace] procedure** keyword is used with a **procedure name** to create a new or modify/replace an existing procedure.  
\- The procedure/function utilizes the small parenthesis to accept the **list of parameters** in it. The **arguments** in the parameter list can be **zero** to **many** for one procedure.  
\- After that, specify the **procedural language** for the PostgreSQL stored procedure such as **SQL** , **C** , etc.  
\- The procedure’s body must be wrapped between the **begin** and **end** keywords.

 **Create a Stored Procedure**

To create a procedure and use it on the PostgreSQL table, first, create a table using this query:
    
    
    CREATE TABLE accounts (
      id int generated by default as identity,
      name varchar(50),
      balance dec(30,4)
       );

The above query creates a table named “ **accounts** ” that has **id** , **name** , and **balance** as its fields. The value in the **id** field is generated automatically and it is set as the **primary key** of the table:

Use the following query to insert values/data in the accounts table:
    
    
    INSERT INTO accounts(name,balance)
     VALUES('Ross',10000), ('Taylor',10000);

The above query only inserts data in the name and balance field as the id is automatically generated:

Use the following query to get the data from the **accounts** table:
    
    
    SELECT * FROM accounts;

The above command fetches the data stored in the accounts table:

Use the following code to create a stored procedure named transfer to complete the transactions in the accounts table:
    
    
    CREATE PROCEDURE transfer(
      account1 int,
      account2 int, 
      amount dec
       )
     language plpgsql
     as $$
     begin
    update accounts 
      set balance = balance - amount 
      where id = account1;
     update accounts 
      set balance = balance + amount 
      where id = account2;
     commit;
     end;$$

The above code creates a **transfer** stored **procedure** with three **arguments** which are **account1** , **account1** , and **amount** to be transferred. It uses **SQL** procedural language and starts the body of the procedure using **dollar signs**. The body of the procedure contains multiple steps as it starts with **subtracting** the amount from the **account1** account. After that, it **adds** the said **amount** to the **account2** account and that’s how a transaction completes:

 **Calling a Procedure**

Type the following command to call the procedure by simply typing the name of the procedure with its arguments:
    
    
    call transfer(1,2,1000);

The PROCEDURE has been called successfully as displayed in the screenshot below:

That’s all about creating the procedure statements in PostgreSQL databases.

 **Conclusion**

The procedure is a user-defined function in PostgreSQL that performs transactional operations on the database tables. The create [or replace] procedure statement is used with a valid procedure name to create a new procedure or modify/replace an existing procedure. The procedure may contain a list of arguments that can be used while calling it. This guide has explained the Create Procedure statement in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/the-create-procedure-statement-in-postgresql/)

---

# How to Backup and Restore PostgreSQL Databases Using pgAdmin

> Open the pgAdmin application and create a backup of the database by providing its location. Restore the database from the local system using the backup file.

In PostgreSQL, users can create multiple databases with different purposes and create multiple tables within each database. However, in databases, there is always a possibility of losing the stored data. Therefore, database experts recommend creating backup files of these databases to restore them in case of any accidents like deletion of the database, etc.

This post demonstrates how to back up and restore PostgreSQL databases in pgAdmin.

 **How to Backup and Restore a Postgres Database Using pgAdmin?**

To backup and restore PostgreSQL databases using pgAdmin, follow this simple guide using these basic steps:

 **Step 1: Backup PostgreSQL Database**

To create a backup of the PostgreSQL database, open the pgAdmin application from the local system:

Type the Master password and click on the “ **OK** ” button to connect to the PostgreSQL servers:

Select the database and right-click on it from the mouse to expand the options menu containing the “ **Backup…** ” button:

Clicking on the “ **Backup…** ” button will direct the user to the Backup window so from there click on the folder icon from the filename tab:

Select the folder in which the backup file will be stored, type the name of the backup file with its type, and click on the “ **Save** ” button:

Once the folder and file name is selected, simply click on the “ **Backup** ” button:

The backup has been created successfully as the process has been finished successfully:

 **Step 2: Delete PostgreSQL Database**

After creating a backup of the database, the user can always recover a database in case of its deletion accidentally. To delete the database, simply right-click on the database and click on the “ **Delete/Drop** ” button:

Click on the “ **Yes** ” button to confirm its deletion:

 **Step 3: Create PostgreSQL Database**

After the deletion of the database, the user needs to create a database and then restore the backup file of the database. To create a database, simply right-click on the “ **Databases** ” button and click on the “ **Database…** ” button from the “ **Create** ” menu:

Create a database by typing its name in the Database tab and click on the “ **Save** ” button to complete the creation of the database:

 **Step 4: Restore PostgreSQL Database**

Once the database is created on the PostgreSQL server, simply right-click on the database and click on the “ **Restore…** ” button:

Select the format of the file and provide the complete address of the file from the local system before clicking on the “ **Restore** ” button:

The process of restoring a PostgreSQL database from a backed-up file has been successfully completed:

That’s all about backing up and restoring PostgreSQL databases using pgAdmin.

 **Conclusion**

To back up and restore the PostgreSQL database, open the pgAdmin application from the computer and create a backup of the database. To create a backup of the database, it is required to provide the format of the backup and its location on the local system. After that, delete the database and then recreate another database using pgAdmin on the computer. Restore the PostgreSQL database from the backup file located in the local system.

---
[View this page online](https://www.commandprompt.com/education/how-to-backup-and-restore-postgresql-databases-using-pgadmin/)

---

# How to Use Escape Single Quotes in PostgreSQL

> Create a table in PostgreSQL with a field to store data in text format. Insert data in it to insert single quotes using multiple methods offered by the platfor…

PostgreSQL allows the user to store data of any type in tables, including textual data. When working with text data in PostgreSQL, occasionally you may need to use escape sequences to handle special characters. For example, if a user wants to store a string in PostgreSQL that includes quotation marks to indicate the importance of a word or phrase, then he can use escape sequences to handle the quotation marks appropriately.

This guide will explain how to use single quotes in PostgreSQL.

 **How to Use Escape Single Quotes in PostgreSQL?**

The Escape characters are used to invoke the alternative interpretation of the character following it as this guide uses them before single quotes. Single quotes can be used to emphasize a single word or a clause in the sentence while storing strings in the PostgreSQL database. PostgreSQL allows the user to insert these quotations using escape sequences like backslashes, dollar quotes, etc.

 **Create PostgreSQL Table**

To start using the Escape single quotes in PostgreSQL, create a table in the database using the following query:
    
    
    CREATE TABLE comments
     (
      id INT NOT NULL GENERATED ALWAYS AS IDENTITY,
      postid INT,
      comments TEXT,
      commentdate TIMESTAMP,
     )

The above code creates a table named “ **comments** ” with multiple columns/fields to store data in them. The fields in the table are “ **id** ”, “ **postid** ”, “ **comments** ”, and “ **commentdate** ”. The comments fields store data in the text format and this field will be used to insert data using escape single quotes:

Insert data in the comments table using the following query in the PostgreSQL database:
    
    
    INSERT INTO comments (postid, comments, commentdate)
     VALUES (1, 'The post is great', '07-02-2023 11:03:05');

The above query inserts data in the **comments** table using the **postid** , **comments** , and **commentdate** fields. This insertion of data does not contain any escape single quotes which could have been used in the comments field:

 **Example 1: Double Quotes As Escape Single Quotes**

Use the following code which uses double quotes to add a single quotation in the comments field. The first quote will act as the escape character so the second quote will be used as its alternative perspective:
    
    
    INSERT INTO comments (postid, comments, commentdate)
    --The Comment contains Double Quotes for Escape Single Quote
     VALUES(1, 'We' 've found the right post', '07-02-2023 01:17:02');

The above query inserts data in the comments field and uses double quotes to add a single quote in the table:

Use the following command to get inserted data from the PostgreSQL table:
    
    
    SELECT * FROM comments;

The following screenshot displays the data inserted has the single quote in the comments field:

 **Example 2: Using BackSlash**

The user can also add single quotes in the text using the following query as the backslash is used as the escape character for the single quote following it:
    
    
    INSERT INTO comments (postid, comments, commentdate)
    --The Comment contains backslash for Escape Single Quote
     VALUES(3, E'I\'m working on a related post', '08-02-2023 09:12:17');

The above query inserts data in the comments table and adds single quotes while inserting a comment using a backslash before the single quote. The user also needs to insert the “ **E** ” symbol which can be considered as the comments in this example:

Use this command to display the data inserted in the comments table:
    
    
    SELECT * FROM comments;

The following screenshot displays the comment with a single quote in the PostgreSQL table:

 **Example 3: Using Dollar-Quoted String**

The third method to insert a single quote is using the dollar quotes added at the start and end of the text:
    
    
    INSERT INTO comments (postid, comments, commentdate)
     VALUES (3, $$'I've shared the post. It's quite impressive'$$, '09-02-2023 16:34:17');

The above screenshot inserts data in the comments table and inserts single quotes in the text using dollar quotes at the start and end of the text:

Use the following command to check the single quote inserted using the dollar quotes:
    
    
    SELECT * FROM comments;

The following screenshot displays the comment with single quotes added in the previous step:

 **Example 4: Using CHR Function**

Another method of adding a single quote in the text is using the CHR() function with the SQL query:
    
    
    SELECT 'The ' || CHR(39) || 'post' || CHR(39) || ' is great' AS quoted_string;

The above code uses **CHR()** function to display text stored in the table as the quoted string and it can be used to insert a single quote in the text:

That’s all about using escape single quotes in PostgreSQL.

 **Conclusion**

To use the escape single quote in the PostgreSQL table, the user can use multiple methods with SQL queries. Start the process by creating a table in the PostgreSQL database and inserting data into the table in the text format. Postgres supports multiple methods to escape single quotes in SQL queries, such as “ **Double quotes** ”, “ **Backslash** ”, “ **Dollar quotes** ”, and “ **CHR() Functions** ”. This guide has explained all the methods to use Escape single quotes in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-escape-single-quotes-in-postgresql/)

---

# How to Query JSONB Array of Objects in PostgreSQL

> To query a JSONB array of objects in PostgreSQL, create a table with a JSONB data type column and expand it to an array format to apply queries on it.

PostgreSQL allows the user to store their structured data in the databases using rows and columns in the table. The user can store data in different formats/types like string, integer, character, JSON, JSONB, etc. JSON format stores data in the form of text and JSONB refers to the binary format of data storage to provide better efficiency.

This guide will explain querying the JSONB array of objects in PostgreSQL.

 **How to Query JSONB Array of Objects in PostgreSQL?**

To query the data from the JSONB-type array of objects in PostgreSQL, use the following query:
    
    
    SELECT * FROM emp;

The above query displays the data from the **emp** table containing **JSONB** type of column named **data** :

Use the following query to get the data using the **WHERE** clause that filters data with respect to some specific condition:
    
    
    SELECT data FROM emp WHERE emp_id =1;

The above query gets the **JSONB** type data from the **emp** table where the **emp_id** column has value **1** :

Use the following command that utilizes the JSONB operator ( **- >>**) to get the data associated with the name key from the JSONB column and retrieve it as text:
    
    
    SELECT data ->> 'name' AS Name FROM emp;

The above command fetches **names** from the **data** field and **displays** them in the **name** field:

Use the following query to use another JSONB operator ( **- >**) which returns the JSONB object from the emp table:
    
    
    SELECT data -> 'name' AS Name FROM emp;

The above query gets the names from the JSONB data field and displays them as individual objects:

Use the following query to get the **subject_marks** field from the “ **students** ” table. The “subject_marks” column contains data for the student in the **JSONB** data type:
    
    
    Select subject_marks from students;

Running the above code displays that the “subject_marks” column contains the subject id, subject name, and their respective marks:

Use the following query to expand the subjects_marks field into an array format for a student having id 2:
    
    
    --Array functions to Query JSONB
    SELECT arr.position,arr.item_object
     FROM students,
     jsonb_array_elements(subject_marks) with ordinality arr(item_object, position) 
     WHERE id=2;

The query selects the position and object of an Array from the students' table. After that, a function named jsonb_array_element is used to extract elements from subject_marks. The stated function takes two arguments: a JSONB array and the element index to be extracted:

That’s all about querying the JSONB array of objects in PostgreSQL.

 **Conclusion**

To query the JSONB array of objects in PostgreSQL, simply create a table with a JSONB column and insert data into the table. Use different operators to query the JSONB data and retrieve the desired information from the table. Use SQL queries to get data based on the position and objects within the array. This guide has explained the process of querying the JSONB array of objects in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-query-jsonb-array-of-objects-in-postgresql/)

---

# How to Create A Pivot Table in PostgreSQL

> To create a pivot table, the user can either use the crosstab function or the CASE statement. Create a tablefunc extension to use the crosstab function.

PostgreSQL enables the user to create tables in the relational database to store data in them using SQL queries. It allows the user to query these tables and fetch data according to the user’s requirements and gain useful insights through that information. The user can create pivot tables in PostgreSQL to convert data in the rows with the columns data.

This guide explains the process of creating a Pivot table in PostgreSQL.

 **How to Create A Pivot Table in PostgreSQL**

Pivot tables are created to transform the data from the rows to the columns and it can be used to get the results according to a particular column in the table. The user can create a pivot table in PostgreSQL using either the crosstab function which is provided by the tablefunc or using the CASE statement.

 **Using Crosstab Function**

Use the following query to create a table in the PostgreSQL database:
    
    
    CREATE TABLE sales (
     product VARCHAR(50),
     region VARCHAR(50),
     year INT,
     revenue DECIMAL(10, 2)
     );

The above query creates a table named **sales** with **product** , **region** , **year** , and **revenue** columns:

Insert the data in the sales table using this query:
    
    
    INSERT INTO sales (product, region, year, revenue)
     VALUES ('Desktop', 'North', 2020, 10000.00),
      ('Desktop', 'North', 2021, 12000.00),
      ('Desktop', 'South', 2020, 8000.00),
      ('Desktop', 'South', 2021, 9000.00),
      ('Laptop', 'North', 2020, 15000.00),
      ('Laptop', 'North', 2021, 18000.00),
      ('Laptop', 'South', 2020, 10000.00),
      ('Laptop', 'South', 2021, 12000.00);

The above query inserts data in the product, region, year, and revenue columns of the sales table:

To create a pivot table in PostgreSQL using the **Crosstab** function, it is required to create an extension named **tablefunc**. For this purpose, execute the following piece of code:
    
    
    CREATE EXTENSION IF NOT EXISTS tablefunc;

Running the above command will create the extension as displayed in the screenshot below:

Once the extension is created, type the following code to create a pivot table using the crosstab function:
    
    
    SELECT *
     FROM crosstab(
     'SELECT product, region, year, revenue
     FROM sales
     ORDER BY 1, 2',
     'SELECT DISTINCT year
     FROM sales
     ORDER BY 1'
     )AS pivot_table (product VARCHAR, region VARCHAR, revenue_2020 DECIMAL, revenue_2021 DECIMAL);

The above code uses the crosstab function to create a pivot table of sales table with product, region, year, and revenue columns. The following screenshot displays the revenue generated in the years 2020 and 2021 from the sales table:

 **Using CASE Statement**

The user can create a pivot table using the CASE statement:
    
    
    SELECT * FROM sales;

The above query fetches all the data from the sales table and displays it on the screen:

Use the following CASE statement with the SUM function to create a pivot table:
    
    
    SELECT
      product,
      region,
      SUM(CASE WHEN year = 2020 THEN revenue END) AS revenue_2020,
      SUM(CASE WHEN year = 2021 THEN revenue END) AS revenue_2021
     FROM
      sales
     GROUP BY
      product,
      region;

The above code selects the **product** and **region** column from the **sales** table and uses the **SUM** function to add the **revenue** according to each year. The following screenshot displays the data from the sales table which is grouped by product and region to get the revenue for the years **2020** and **2021** :

That’s all about creating a pivot table using the crosstab function and CASE statement.

 **Conclusion**

To create a pivot table in PostgreSQL, create a table and insert data in a Postgres table using SQL queries. Once the table is created in PostgreSQL, the user can either create a Pivot table using the crosstab function or a CASE statement. This guide has demonstrated the process of creating a pivot table in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-pivot-table-in-postgresql/)

---

# JSON Vs JSONB in PostgreSQL: What is the Difference?

> JSON is the data type to store data in the form of text and JSONB stores data in the binary format to improve the retrieval of the data from the PostgreSQL dat…

PostgreSQL allows the user to store data in the database using different formats, such as JSON, JSONB, etc. In Postgres, JSON is used to store data of an unspecified type and the user does not have the means to understand its type. JSONB is the binary version of the JSON data type to improve the performance while extracting the data from the PostgreSQL database.

This guide will explain the differences between JSON and JSONB types in PostgreSQL with examples.

 **JSON Vs. JSONB in PostgreSQL**

JSON is a semi-structured data that is a widely adopted data interchangeable format and it is a lightweight and flexible data type. JSON data type is only used when the user doesn't have knowledge about the format of the data and there are no other options to get to know it. JSONB is its binary form which comes as the better version of JSON in terms of performance as it reads data at a faster pace. JSONB stores data in the decomposed binary format so it requires more time to write data in JSONB format.

 **Operators Supported by JSON & JSONB**

To understand the differences between JSON and JSONB, the following sections contain examples of using JSON and JSONB operators in PostgreSQL:

 **JSON Operators**

Type the following query to use the JSON operator ( **- >**) in the PostgreSQL database:
    
    
    select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2

The above query gets a JSON array element with indexes starting from zero and the **json- >2** indicated the 3rd position in the array:

Use the following query to use the JSON operator ( **- >>**) on the array:
    
    
    select'[1,2,3]'::json->>2

The above query selects an array containing multiple numbers and uses the “ **- >>**” operator to get the JSON element as the text:

Use the following query that contains a JSON operator **# >** to get data from the given array:
    
    
    select '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}'

The above query obtains a JSON object from the specified path which in this case is the data inside the innermost bracket:

 **JSONB Operators**

Use the following query to use the JSONB operator **@ >** to get the boolean value:
    
    
    select '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb

The above code specifies whether the left JSON value contains the right JSON path or value:

Use the following query to use the JSONB operator || which is used to merge two conditions:
    
    
    select '["a", "b"]'::jsonb || '["c", "d"]'::jsonb

The above query contains the || operator that is used to concatenate two or more conditions and the answer will be true if either condition is true:

 **Functions Supported by JSON & JSONB**

After using the operators, this section uses different functions to demonstrate the differences between JSON and JSONB:

 **JSON Functions**

Use the following query to use the json_array_length() function in PostgreSQL:
    
    
    select json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]');

The above query uses the json_array_length function to get the size/length of the array:

Type the following command to use the json_typeof() function which is a JSON function:
    
    
    select json_typeof('-123.4');

The above query uses the json_typeof() function to get the data type of the data:

 **JSONB Functions**

Execute the following query that uses the jsonb_set() function to modify a value within a JSONB document:
    
    
    select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}','[2,3,4]', false);

The above query returns the objects in the target parameter and this section is specified by the path parameter:

Use the following query to use the jsonb_insert() function in JSONB data type:
    
    
    select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"');

The above query uses the jsonb_insert() function to insert a new value at the location provided between the array and new_value:

That’s all about the differences between JSON and JSONB in PostgreSQL using examples.

 **Conclusion**

The JSON and JSONB are the data types in the PostgreSQL database that are used to store unidentified data in a semi-structured format. The JSON and JSONB types have different operators and functions to extract information from the stored data in the PostgreSQL database. This guide has demonstrated with examples some of the comparisons between JSON and JSONB data types in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/json-vs-jsonb/)

---

# Can a Temporary Table Have the Same Name as a Permanent Table in PostgreSQL?

> In Postgres, a temporary table can have the same name as a permanent table. However, database experts recommend the use of distinct names to avoid ambiguity.

In PostgreSQL, it is possible to define a temp/temporary table with the exact duplicate name as a permanent/regular table. However, it is not recommended because of possible confusion/ambiguity. For instance, it would not be an easy task to differentiate between temporary and permanent tables when working with complex databases. Moreover, when a temporary table is created with the same name as a regular table, then the user's access to the permanent table will be temporarily denied until the temporary table is dropped.

 **Can a Temp Table Have the Exact Same Name as a Regular/Permanent Postgres Table?**

Yes! A permanent and a temp table can have the same name at the same time. However, database experts recommend the use of distinct names for temporary and permanent tables to avoid ambiguity in queries and database operations.

Let’s comprehend this concept practically!

 **Example: Creating Temp and Regular Tables With the Same Name**

First, create a regular PostgreSQL table named “cp_table” by executing the following query:
    
    
    CREATE TABLE cp_table(
    id INT,
    name TEXT,
    email VARCHAR);

Now verify the table’s structure by executing the below-provided “SELECT” command:
    
    
    SELECT * FROM cp_table;

The above snippet confirms the existence of the “cp_table”. Now create a TEMP table with the exact duplicate name:
    
    
    CREATE TEMP TABLE cp_table(
    cp_id INT,
    cp_name TEXT
    );

Utilize the following command with the table’s name to confirm its creation:
    
    
    SELECT * FROM cp_table;

The below snippet verifies that a temp table is created with the same name as a permanent table already has:

Now, in the current session, whenever you fetch the “cp_table”, Postgres will retrieve the result set for the temporary table. To fetch the data of the permanent table, either you have to wait for the current session to expire or drop the temporary table explicitly.

 **Conclusion**

In PostgreSQL, it is possible to create a temp table with the exact duplicate name as a permanent/regular table. However, database experts recommend the use of distinct names for temporary and permanent tables to avoid ambiguity in queries and database operations. This post has illustrated a practical guide on can a temp table have the exact same name as a permanent/regular table in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/can-a-temporary-table-have-the-same-name-as-a-permanent-table-in-postgresql/)

---

# How to Explicitly Drop a TEMPORARY Table in Postgres

> In PostgreSQL, the temporary tables can be explicitly dropped/removed by executing the DROP TABLE command following the temporary table’s name.

In PostgreSQL, temporary or temp tables are automatically removed at the end of a session/transaction, depending on their definition/creation. However, occasionally users may need to drop a temporary table before the current session or transaction expires. In such cases, the temporary tables can be dropped by using the DROP TABLE command. This post will illustrate a complete procedure for dropping a temporary table in PostgreSQL.

 **How to Explicitly Drop a TEMP Table in Postgres?**

In Postgres, the TEMP or TEMPORARY keyword is used along with the “CREATE TABLE” command to create a temporary table. On the other hand, a temporary table can be explicitly dropped by executing a regular DROP TABLE command, without specifying a “TEMP or TEMPORARY” keyword. However, if the session/transaction has already terminated, then the temporary table will be automatically removed from the database, and there is no need to explicitly drop it.

To drop a temp table in Postgres, simply run the DROP TABLE command with the following syntax:
    
    
    DROP TABLE IF EXISTS temporary_table_name;

 **Example: Explicitly Removing a TEMP Table in Postgres**

Let’s first create a temporary table by executing the following command:
    
    
    CREATE TEMP TABLE cp_table(
    id INT,
    name VARCHAR);

The above snippet shows that a temporary table has been created using a “TEMP” keyword. The table’s creation can be verified by running the below-provided command:
    
    
    SELECT * FROM cp_table;

When it comes to removing a temporary table, there is no need of specifying the TEMP keyword. The following snippet demonstrates that a temporary table is removed just like a regular table:
    
    
    DROP TABLE cp_table;

The table’s removal can be verified by executing the below-given query:
    
    
    SELECT * FROM cp_table;

The output proves that the selected temporary table has been explicitly removed from the database.

 **Conclusion**

In PostgreSQL, the temporary tables can be explicitly dropped/removed by executing the DROP TABLE command following the temporary table’s name. However, if the session/transaction has already terminated, then the temporary table will be automatically removed from the database, and there is no need to explicitly drop it. This article has illustrated a complete procedure of explicitly dropping a temporary table in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-explicitly-drop-a-temporary-table-in-postgres/)

---

# How to Deallocate a Prepared Statement in PostgreSQL

> Use the DEALLOCATE command followed by the name of the prepared statement to explicitly Deallocate a Prepared Statement in PostgreSQL.

PostgreSQL supports a concept of prepared statements that help us optimize the server’s performance. For this purpose, the PREPARE statement is used. A prepared statement is automatically deallocated when the session terminates. However, occasionally users need to deallocate the prepared statement explicitly. In such cases, the **DEALLOCATE** command can be used.

This article illustrates how you can explicitly deallocate a prepared statement in Postgres.

 **How to Deallocate a Prepared Statement in PostgreSQL?**

In PostgreSQL, if a prepared statement is no longer needed, it can be explicitly deallocated by executing the DEALLOCATE statement:
    
    
    DEALLOCATE prepared_statement_name;

Let’s learn it practically.

 **Example: Deallocating a Prepared Statement in Postgres**

Let’s execute the following command to get the list of prepared statements:
    
    
    SELECT name, statement
    FROM pg_prepared_statements;

In the above snippet, the “pg_prepared_statements” view is used to display a list of prepared statements along with their names and statement type:

Execute the following command to deallocate the “emp_info” statement explicitly:
    
    
    DEALLOCATE emp_info;

The selected prepared statement has been explicitly deallocated:

To confirm the statement’s deallocation, execute the select query for the “pg_prepared_statements” view:
    
    
    SELECT name, statement
    FROM pg_prepared_statements;

From the above snippet, you can clearly see that the prepared statement named “emp_info” has been deallocated successfully.

 **Conclusion**

A prepared statement is automatically deallocated when the session terminates. However, occasionally users need to deallocate the prepared statement explicitly. In such cases, use the **DEALLOCATE** command followed by the name of the prepared statement. This post has illustrated a detailed guide on deallocating a prepared statement in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-deallocate-a-prepared-statement-in-postgresql/)

---

# How to Get List of Running Queries in PostgreSQL

> PostgreSQL provides a system view named pg_stat_activity that retrieves information about the currently running queries and active sessions on the database ser…

While working with a PostgreSQL database, it is often necessary to view the running queries on the server. This information can assist us in performance monitoring, troubleshooting, resource management, query analysis, and capacity planning. For this purpose, Postgres provides a “pg_stat_activity” view that enables users to gain valuable insights into the database's current activity and optimize its performance.

This post illustrates how to get the list of active/running queries in PostgreSQL.

 **How to Get a List of Active/Running Queries in Postgres?**

PostgreSQL provides a system view named pg_stat_activity that retrieves information about the currently running queries and active sessions on the database server. A detailed description of the pg_stat_activity view is listed below:

  *  **datid** : It displays the OID of the database with which the session is associated.
  *  **datname** : This column shows the name of the database.
  *  **pid** : An integer-type column that shows the process ID of the session.
  *  **usename** : It represents the user name.
  *  **client_addr** : It retrieves the IP address information.
  *  **application_name** : This column retrieves the application/client name.
  *  **query** : this column shows the information about the currently executing query/command.
  *  **state** : Shows the session’s current state, like "active", "idle", etc.).
  *  **wait_event_type** and **wait_event** : these are Text-type columns that show the type of event a session is waiting for and the name of the event, respectively.



Now, head into SQL Shell, provide login privileges to connect to the Postgres database, and execute the following query to fetch the list of currently running/active queries:
    
    
    SELECT pid AS process_id, 
    query AS active_query
    FROM pg_stat_activity
    WHERE state = 'active';

The following snippet shows the currently active query:

To get a list of all queries, execute the following command:
    
    
    SELECT pid AS process_id, 
    query AS all_query
    FROM pg_stat_activity;

The following snippet depicts the list of all queries:

That’s all about getting the list of active queries in Postgres.

 **Conclusion**

PostgreSQL provides a system view named pg_stat_activity that retrieves information about the currently running queries and active sessions on the database server. It returns a list of currently active queries in Postgres, which help us monitor and analyze the workload and performance of a database. This write has illustrated a step-by-step method to fetch the list of running/active queries.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-list-of-running-queries-in-postgresql/)

---

# How the PREPARE Statement Works in PostgreSQL

> In PostgreSQL, the PREPARE statement creates a prepared statement that can be utilized repeatedly. It allows us to execute the command with different values.

When working with a PostgreSQL database, there are situations where you might need to execute a specific command multiple times or repeatedly with different values. In such cases, the **PREPARE** statement comes in handy. It enables us to prepare a statement with a unique name and execute it repeatedly(when needed) using the EXECUTE command.

This article will illustrate the use of PREPARE statement in PostgreSQL.

 **How Does the PREPARE Statement Work in PostgreSQL?**

In PostgreSQL, the PREPARE statement creates a prepared statement that can be utilized repeatedly. It allows us to define parameters, which makes it possible to execute the command with different values simply by modifying the parameter values. It optimizes the performance of the Postgres Server by reducing the overhead of parsing, analyzing, and planning a query each time it is executed.

 **Syntax**

Follow the below-given syntax to use the PREPARE statement in PostgreSQL:
    
    
    PREPARE statement_name [ ( data_type [, ...] ) ] AS statement;

Once a statement is prepared, we can execute it using the **EXECUTE** statement:
    
    
    EXECUTE statement_name (parameter_value1, parameter_value1, ...);

Moreover, if a prepared statement is no longer needed, it can be deallocated using the DEALLOCATE statement:
    
    
    DEALLOCATE prepared_statement_name;

 **Example: How to Use PREPARE Statement in PostgreSQL**

The following snippet demonstrates how to prepare a statement in Postgres:
    
    
    PREPARE emp (INT, TEXT, INT, DATE) AS
    INSERT INTO emp_bio VALUES($1, $2, $3, $4);

The following snippet depicts that a statement has been prepared:

Let’s execute the above statement using the EXECUTE() function:
    
    
    EXECUTE emp(6, 'Ambrose', 55000, '2018-01-01');

The prepared statement has been successfully executed:

Let’s execute the prepared statement one more time with different values:
    
    
    EXECUTE emp(7, 'Kane', 35000, '2023-01-01');

The output shows that the statement executed with different values successfully:

Let’s confirm the prepared statement execution using the following query:
    
    
    SELECT * FROM emp_bio;

The below snippet verifies the working of the prepared statement:

Suppose we want to deallocate the prepared statement, for this purpose, we will execute the following query:
    
    
    DEALLOCATE emp;

The given statement has been deallocated successfully:

That’s all about the “PREPARE” statement in PostgreSQL.

 **Conclusion**

In PostgreSQL, the **PREPARE** statement creates a prepared statement that can be utilized repeatedly. It allows us to define parameters, which makes it possible to execute the command with different values simply by modifying the parameter values. Once a statement is prepared, we can execute it using the **EXECUTE** statement. This post has illustrated the working of PREPARE statements in PostgreSQL using examples.

---
[View this page online](https://www.commandprompt.com/education/how-the-prepare-statement-works-in-postgresql/)

---

# How to Install and Set Up Docker PostgreSQL Environment

> To install the Docker PostgreSQL environment, install Docker on the system from the official link. After that, pull the Postgres image from Docker Hub using th…

Docker is a powerful tool for creating and maintaining containers, which are isolated environments that may run multiple applications without interfering with one another. PostgreSQL is a powerful and open-source relational database system that can handle complex queries and large volumes of data.

This post will explain a step-by-step procedure for installing as well as setting up a Docker PostgreSQL environment on the local machine.  


 **How to Install and Set Up Docker PostgreSQL Environment**

For complete installation and setup docker PostgreSQL environment, users need to follow the given instructions:

 **Step 1: Download Docker**

First, we need to download the docker application which is freely available on the [official](<https://docs.docker.com/get-docker/>) page of docker. Select the docker compatible with your operating system, in our case, it is Windows:

Clicking on the “ **Download Docker Desktop** ” button will initiate the downloading process:

 **Step 2: Install Docker**

Once the downloading process is finished, install the docker on your system by following the on-screen instructions:

On successful installation, you will meet the following window:

Click on the “ **Close** ” button to proceed further.

 **Step 3: Run Docker**

Once docker is installed on your system, you can run it from the Windows search bar:

Running docker will start the docker service or alternatively, you can run it from the command line:

 **Step 4: Set up a Docker Account**

A wide range of images is available on the docker hub. However, to access any image, first, we need to set up an account on the docker hub:

Clicking on the “ **Register** ” button will navigate you to the signup page. Provide the registration details, and click on the “ **Sign up** ” button to proceed further:

Choose a plan from the available options to get started with docker:

Next, it will ask you to verify your email address, which will ultimately log you into the docker hub:

Once the account is created, you can find and use any image of your choice.

 **Step 5: Download PostgreSQL Image**

The files that dockers use to run the applications are known as “images”. These images are nothing but a pre-built collection of files. Let us find a PostgreSQL image and download it from the docker hub. For this purpose, type “ **Postgres** ” in the search bar and press enter:

Clicking on Enter button will navigate you to the following window:

Selecting the “Postgres docker official image” will lead you to a new page that shows all the details regarding the Postgres docker image:

 **Step 6: Pull the PostgreSQL Image**

The next step is to pull the PostgreSQL image from the Docker Hub, which is a repository of pre-built images for various applications. Users can use the following command to pull the latest version of PostgreSQL in the command prompt:
    
    
    docker pull postgres

It downloads the image to your local machine and stores it in your Docker cache.

 **Step 7: Create a Container from the PostgreSQL Image**

For creating a container through the PostgreSQL image and executing it in the background. A container is an instance of an image that can be configured with several arguments, such as environment variables, volumes, ports, etc. You can use the following command to create and run a PostgreSQL container:
    
    
    docker run --name postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres

Let us break down this command and see what each option does:

  * “ **\--name postgres** ”: assigns a name to the container, which makes it easier to identify and manage later.
  * “ **-e POSTGRES_PASSWORD=postgres** ” sets an environment variable that defines the password. You can change this to any value you want, but make sure to remember it as you will need it later to connect to the database.
  * “ **-p 5432:5432** ” maps the port 5432 between the host machine and the container. This allows us to access the database from outside the container using the host's IP address and port number.
  * “ **-d postgres** ” executes the container in detached mode. The last argument “p **ostgres** ” specifies the name of the image that we want to use for the container.



Users can confirm that the container is running by using the below command:
    
    
    docker ps

 **Step 8: Connect to the PostgreSQL Database**

Finally, connect to the PostgreSQL database and start using it. There are many ways to connect to a PostgreSQL database, such as using a graphical user interface (GUI) tool like pgAdmin or using a command-line tool.

To connect to the database using SQL Shell, users need to execute the below-provided command:
    
    
    docker exec -it postgres psql -U postgres

Now, users are connected to the database and ready to execute SQL commands.

Users can use ‘\l’ to list all the databases, ‘\c’ to connect to a specific database, ‘\dt’ to list all the tables in a database, ‘\d’ to describe a table’s structure, etc. For instance, use ‘\?’ to see all the available commands and options:

To exit Postgres, users can use the ‘\q’ command.

 **Conclusion**

To install and set up the Docker PostgreSQL environment, users need to install Docker on the system from the [link](<https://www.docker.com/get-started>). After that, pull the PostgreSQL image from Docker Hub using the “ **docker pull postgres** ”. Furthermore, create a container from the PostgreSQL image and connect to the PostgreSQL container using the “ **docker exec -it postgres psql -U postgres** ” command. Finally, users can now create databases, tables, and queries using PostgreSQL commands.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-and-set-up-docker-postgresql-environment/)

---

# How to Delete Data From PostgreSQL Tables Using Python

> To delete data from PostgreSQL tables using Python, execute the delete query with the help of the “execute()” function.

PostgreSQL data can be manipulated through interaction with Python. For this purpose, a popular library named psycopg2 is used. psycopg2 serves as an efficient PostgreSQL adapter that allows us to establish a connection between Python and PostgreSQL. Once the connection between Postgres and Python is established, you can perform any operations, such as creating, searching, updating, and deleting data. In this guide, we will show you how to delete data from a Postgres table using Python.

 **How to Delete Data From PostgreSQL Tables Using Python?**

Before deleting the data from Postgres tables using Python, you need to make sure that “psycopg2” is installed on your system. It can be installed by executing the following “pip” command:
    
    
    pip install psycopg2

 **Output**

To delete the table’s data from the PostgreSQL database using Python programming, simply follow the below-provided steps.

 **Step 1: Import psycopg2**

Open any code editor, make a new file with the “.py” extension, and import the “psycopg2” at the top of it
    
    
    import psycopg2

 **Step 2: Connect Python With Postgres**

Make a Postgres Python connection by providing the essential connection details, such as database name, password, hostname, etc:
    
    
    conn_details = psycopg2.connect(
    host="localhost",
    database="postgres",
    user="postgres",
    password="*****",
    port= '5432'
    )

In the above snippet, the connect() function is utilized to connect to the “postgres” database as a “postgres” user.

 **Step 3: Check the Table’s Data**

Navigate to the SQL Shell and execute the “SELECT” command to see the table’s data:
    
    
    SELECT * FROM emp_info;

 **Step 4: Delete the Table’s Data**

Suppose we want to remove those employees whose “joining_date” is greater than “2023-01-01”. To do this, execute the delete query with the help of execute() function:
    
    
    cursor = conn_details.cursor()
    delete_tbl_data = "DELETE FROM emp_info WHERE joining_date > '2023-01-01';"
    cursor.execute(delete_tbl_data)

Here:

  * First, a cursor object is created.
  * After that, the DELETE FROM command is executed to remove data from the “emp_info” table.
  * Finally, the query is executed using the “execute()” function to delete the table’s data.



 **Step 5: Save Changes**

In the below code snippet, the commit() and close() functions are utilized to save the changes and close the cursor and the connection:
    
    
    conn.commit()
    cursor.close()
    conn.close()

Here is what you will get on successful execution:

The given code was executed successfully.

 **Step 6: Confirm Table’s Data Deletion**

Navigate back to the SQL Shell and run the “SELECT” query for the “emp_info” table:
    
    
    SELECT * FROM emp_info;

The below snippet demonstrates that the select records have been successfully removed from the “emp_info” table:

That’s all about deleting data from a Postgres table using Python.

 **Conclusion**

To delete data from PostgreSQL tables using Python, open any code editor, make a new file with the “.py” extension, and import the “psycopg2” at the top of it. Connect Python with Postgres using psycopg2.connect(), and execute the delete query with the help of the “execute()” function to remove the selected records from a Postgres table. This post has illustrated a stepwise guide on deleting data from Postgres tables using Python.

---
[View this page online](https://www.commandprompt.com/education/how-to-delete-data-from-postgresql-tables-using-python/)

---

# How to Call a User-defined Function in PostgreSQL

> To call/invoke a user-defined function in PostgreSQL, Positional Notation, Named Notation, or Mixed Notation can be used.

In PostgreSQL, user-defined functions allow us to execute a group of statements to get the desired results. Using Postgres functions, we can create custom logic and reutilize it in our database when needed. To utilize the functionality of a user-defined function in PostgreSQL, we need to invoke/call it. In this write-up, we will illustrate different methods to invoke a user-defined function in Postgres.

 **How to Call a User-defined Function in Postgres?**

Calling/invoking a user-defined function requires the function name and its parameters(if any). Depending on how it is implemented, a user-defined function may retrieve a value or perform some specific actions. To call a user-defined function in Postgres, use one of the following methods:

  * Positional Notation
  * Named Notation
  * Mixed notation



 **How to Call a User-defined Function Using Positional Notation?**

To call a user-defined function using positional notation, all you need to do is specify the argument in the same order as the parameter’s order while calling a function. Here is the syntax to call a user-defined function using the positional notation:
    
    
    SELECT func_name(parameter_list);

 **Example: Positional Notation**

Let’s first create a function named “product” that accepts two numbers and retrieves their multiplication:
    
    
    CREATE FUNCTION product(num_1 INT, num_2 INT) 
    RETURNS INTEGER 
    LANGUAGE plpgsql 
    AS 
    $$
    BEGIN
     RETURN num_1 * num_2;
    END;
    $$

Let’s call the “product” function using the positional notation:
    
    
    SELECT product(45, 5);

The output shows that the stated function retrieves the product/multiplication of given numbers.

 **How to Call a User-defined Function Using Named Notation?**

Calling a user-defined function with named notation allows us to specify the parameter values along with their names at the time of function invoking. It is recommended that the “Named Notation” approach should be used when there are many parameters as it eliminates ambiguity. The below snippet shows the basic syntax:
    
    
    SELECT func_name(
       parameter_name_1 => val, 
        parameter_name_2 => val
    );

 **Example: Named Notation**

In this example, we will utilize the same “product” function, however, we will invoke it using the named notation:
    
    
    SELECT product(
       num_1 => 12, 
       num_2 => 6
    );

The output proves that calling the product function with a named notation retrieves accurate results.

 **How to Call a User-defined Function Using Mixed Notation?**

As the name itself suggests, Mixed Notation is a mixture of both “named notation” and “positional notation”. This means the Mixed notation approach allows us to call a function by specifying the parameters using both named and positional notations. However, the positional arguments must come first, and then comes the named arguments. Else you will experience an error. Here is a syntax to use the mixed notation:
    
    
    SELECT func_name(
       parameter_val, 
       parameter_name => parameter_val
    );

 **Example: Mixed Notation**

The below code snippet demonstrates the use of mixed notation in Postgres:
    
    
    SELECT product(
       12, 
       num_2 => 6
    );

That’s all about calling a user-defined function in Postgres using different notations.

 **Conclusion**

To call a user-defined function in Postgres, Positional Notation, Named Notation, or Mixed Notation can be used. Calling/invoking a user-defined function requires the function name and its parameters(if any). Depending on how it is implemented, a user-defined function may retrieve a value or perform some specific actions. This write-up has illustrated various notations to call a user-defined function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-call-a-user-defined-function-in-postgresql/)

---

# Creating a Repeating Sequence in PostgreSQL: A Comprehensive Guide

> To create a repeating sequence in Postgres, the CREATE SEQUENCE command can be executed with the “CYCLE” option enabled.

When working with sequences in PostgreSQL, we have the flexibility to choose between creating a non-repeating sequence or a repeating sequence. It totally depends on the user’s requirements. A repeating sequence, as the name itself suggests, cycles through its values once it reaches its maximum or minimum values and starts over again. While the non-repeating sequence follows a linear progression and stops its execution when it reaches its maximum or minimum value.

This comprehensive guide demonstrates how to create a repeating sequence in Postgres.

 **Creating a Repeating Sequence in PostgreSQL: A Comprehensive Guide**

Creating a repeating sequence in Postgres guarantees that the previously generated sequence numbers can be reused, which means a repeating sequence can repeat indefinitely. While a non-repeating sequence follows a linear progression and hence generates unique values without any repetition.

 **Syntax**

To create a repeating sequence in Postgres, the **CREATE SEQUENCE** command can be executed with the “CYCLE” option enabled. Here is the syntax for creating a repeating sequence in Postgres:
    
    
    CREATE SEQUENCE Seq_name
    MAXVALUE maximum_value
    CYCLE;

Let's delve into practical implementation to gain a deeper understanding of this concept.

 **Example 1: Creating an Ascending Repeating Sequence**

The following example creates an ascending repeating sequence starting from 1, ending at 5, and incremented by 2 on each iteration:
    
    
    CREATE SEQUENCE cp_sequence
    START 1
    INCREMENT 2
    MAXVALUE 5
    CYCLE;

Now utilize the nextval() function to see how repeating sequence works in Postgres:
    
    
    SELECT nextval('cp_sequence')
    UNION ALL
    SELECT nextval('cp_sequence')
    UNION ALL
    SELECT nextval('cp_sequence')
    UNION ALL
    SELECT nextval('cp_sequence')
    UNION ALL
    SELECT nextval('cp_sequence');

The output demonstrates that the sequence restarted when it reaches its maximum limit.

 **Example 2: Creating a Descending Repeating Sequence**

In the following example, we will show you how to create a descending repeating sequence in Postgres:
    
    
    CREATE SEQUENCE cp_seq
    START 0
    INCREMENT -2
    MINVALUE -10
    MAXVALUE 0
    CYCLE;

Let’s utilize the nextval() function to see how descending repeating sequence works in Postgres:
    
    
    SELECT nextval('cp_seq')
    UNION ALL
    SELECT nextval('cp_seq')
    UNION ALL
    SELECT nextval('cp_seq')
    UNION ALL
    SELECT nextval('cp_seq')
    UNION ALL
    SELECT nextval('cp_seq')
    UNION ALL
    SELECT nextval('cp_seq');

That’s all about creating an ascending or descending repeating sequence in Postgres.

 **Conclusion**

To create a repeating sequence in Postgres, the **CREATE SEQUENCE** command can be executed with the “CYCLE” option enabled. Creating a repeating sequence in Postgres guarantees that the previously generated sequence numbers can be reused, which means a repeating sequence can repeat indefinitely. This post has explained how to create an ascending or descending repeating sequence in Postgres.

---
[View this page online](https://www.commandprompt.com/education/creating-a-repeating-sequence-in-postgresql-a-comprehensive-guide/)

---

# What is the Equivalent of Java Long in PostgreSQL

> In PostgreSQL, the &quot;BIGINT&quot; data type is used to store extremely large positive or negative numbers and can serve as an alternative to Java’s Long data type.

Java users commonly use different databases to efficiently store and manipulate data. PostgreSQL is a popular choice among developers due to its notable features like security, scalability, and ease of use. However, when working with large numeric datasets, storing and managing enormous data can be challenging. For instance, Postgres offers BIGINT data type to store gigantic numeric values while Java keeps them in Long data type.

To address this problem, the "BIGINT" data type is used in PostgreSQL, which serves as an alternative to Java’s Long data type.

This post will present a comprehensive guide on Postgres’ equivalent of Java’s long data type.

 **What is Java’s Long Data Type?**

Before understanding how BIGINT works, first, you must understand Java's LONG data type. In Java, the long data type is commonly used to handle extremely large whole numbers. It allows us to store numbers as small as "-9,223,372,036,854,775,808" and as large as "9,223,372,036,854,775,807". To declare a variable of type long, simply use the keyword "long" followed by the desired variable name:
    
    
    long num = 9223372036854775L;

"L" must be appended at the end of the number.

 **What is the Equivalent of Java Long in Postgres?**

In Postgres, the "BIGINT" data type corresponds to Java’s long data type and is used to store extremely large positive or negative numbers. The range of BIGINT spans from “-9,223,372,036,854,775,808 to +9,223,372,036,854,775,807”.

 **Example: How BIGINT Works in PostgreSQL?**

To illustrate the usage of the "BIGINT" data type in Postgres, we can create a table using the "CREATE TABLE" command and define a column with the "BIGINT" data type, as shown below:
    
    
    CREATE TABLE cp_table (
     cp_id INT PRIMARY KEY,
     cp_name TEXT NOT NULL,
     cp_number BIGINT
    );

The “cp_table” has been created successfully. Let’s insert a really big value into the “cp_table” using the INSERT query:
    
    
    INSERT INTO cp_table (cp_id, cp_name, cp_number) 
    VALUES (1, 'Dean', 922337203685476800),
    (2, 'Joe', 922337203685477800),
    (3, 'Ambrose', 922337203685476802),
    (4, 'Joseph', 92233720368776804),
    (5, 'Mike', 922337203685768001);

Let’s fetch the table’s data using the below-provided query:
    
    
    SELECT * FROM cp_table;

This is how you can store and manipulate really big numeric values in Postgres.

 **Conclusion**

In PostgreSQL, the "BIGINT" data type is used to store extremely large positive or negative numbers and can serve as an alternative to Java’s Long data type. It allows us to store numbers as small as "-9,223,372,036,854,775,808" and as large as "9,223,372,036,854,775,807". This post has explained how to use BIGINT as an alternative to Java’s LONG data type.

---
[View this page online](https://www.commandprompt.com/education/what-is-the-equivalent-of-java-long-in-postgresql/)

---

# How to List User-Defined Functions in PostgreSQL

> In PostgreSQL, the “\df” mata-command, “information_schema.routines” View, and the “pg_proc” Catalog is used to get the list of user-defined functions.

Listing user-defined functions allows us to understand the available functions and their purpose in a database. By getting the details of the function like their names, argument types, return types, etc. we can gain valuable insights into the functionality and behavior of the functions. Therefore, Postgres offers various methods to get a list of user-defined functions/procedures.

This write-up presents the below-listed methods to get the list of user-defined functions in Postgres:

  * Using “\df”
  * Using “pg_proc”
  * Using “information_schema.routines”



Let’s begin with the “\df” command.

 **How to List User-Defined Functions Using “\df” Command?**

The “ **\df** ” is a meta-command in Postgres that is executed in the SQL Shell. It helps us get the list of all available functions in the current database, including inbuilt as well as user-defined functions. It retrieves the details of the function like name, accepted arguments, return type, and much more. Execute the following meta-command to get a better insight into the "\df" command:
    
    
    \df

The output shows that the stated command retrieves the list of functions along with detailed information.

 **How to List User-Defined Functions Using the “pg_proc” Catalog?**

“pg_proc” is a Postgres system catalog table that keeps information regarding functions and procedures defined in a database. It retrieves the function list along with the functions’ metadata, such as name, data types, return data type, etc. Consider the following code snippet for a better understanding of the “pg_proc” catalog:
    
    
    SELECT proname AS function_name, 
    pg_get_function_identity_arguments(oid) AS arguments_accepted
    FROM pg_proc
    WHERE pronamespace = 'public'::regnamespace;

The output snippet shows that the “pg_proc” successfully retrieves the list of user-defined functions.

 **How to List User-Defined Functions Using “information_schema.routines” View?**

The “information_schema.routines” is a system view in PostgreSQL that contains information about database routines, such as functions and procedures. It retrieves details like routine names, parameter data types, return types, etc. Execute the following code to gain a better understanding of the “information_schema.routines” View:
    
    
    SELECT routine_name AS function_name,
    routine_type AS function_type,
    data_type
    FROM information_schema.routines
    WHERE routine_type = 'FUNCTION' AND routine_schema = 'public';

That’s all about listing the user-defined functions in Postgres.

 **Conclusion**

In PostgreSQL, the “\df” mata-command, “information_schema.routines” View, and the “pg_proc” Catalog is used to get the list of user-defined functions. All these approaches retrieve the details of the user-defined functions like their name, accepted arguments, return type, and much more. This post has illustrated various methods to get a list of user-defined functions in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-list-user-defined-functions-in-postgresql/)

---

# CREATE FUNCTION Statement in PostgreSQL

> The CREATE FUNCTION statement allows us to create a user-defined function by specifying its name, parameters, return type, and the language to be implemented.

In PostgreSQL, creating a user-defined function assist us in defining customized logic and operations that can be executed in a database when needed. For this purpose, the CREATE FUNCTION statement is used in PostgreSQL. User-defined functions allow us to accomplish a particular task with ease. Moreover, creating a user-defined function help us encapsulate our own custom logic directly in the database.

This write-up illustrates how to use the CREATE FUNCTION statement in Postgres.

 **How Does CREATE FUNCTION Work in PostgreSQL?**

The CREATE FUNCTION statement allows us to create a user-defined function by specifying its name, input parameters, return type, and the language used for its implementation. Execute the following syntax to create a user-defined function:
    
    
    CREATE [OR REPLACE] FUNCTION func_name ([par_1 data_type [, par_2 data_type [, ...]]])
    RETURNS return_type 
    LANGUAGE plpgsql
    AS
    $$
    -- Function body
    $$

Let's comprehend the **CREATE FUNCTION** statement line by line:

  * Specify any valid name of your choice in place of func_name.
  * “par_1, par_2, …” represents the function parameters that have a specific “data_type”.
  * “RETURNS return_type” denotes the data type that will be retrieved by the function.
  * “LANGUAGE plpgsql” represents the procedural language PL/pgSQL in which the function will be written.
  * The “AS” keyword indicates the start of the function body.



 **Sample Table**

The following snippet depicts the data of the sample table named “emp_bio”:
    
    
    SELECT * FROM emp_bio;

 **Example: How to Create a User-defined Function in Postgres?**

Let’s create a new user-defined function and named it “emp_count”:
    
    
    CREATE FUNCTION emp_count (sal_from INTEGER, sal_to INTEGER)
    RETURNS INTEGER
    LANGUAGE plpgsql
    AS
    $$
    DECLARE
    total_count INTEGER;
    BEGIN
    SELECT COUNT(*)
    INTO total_count
    FROM emp_bio
    WHERE emp_sal between sal_from and sal_to;
    RETURN total_count;
    END;
    $$;

In the above code snippet:

  * A user-defined function named “emp_count” is created that accepts two parameters.
  * The “emp_count” will retrieve an integer value.
  * A variable named “total_count” is created that will keep the number of employees selected from the emp_bio table.
  * The SELECT INTO statement will select the employees whose salary is between “emp_from” to “emp_to” and assign them to the variable “emp_count”.
  * The RETURN statement will retrieve the number of employees:



A function named “emp_count” has been successfully created. Let’s call the newly created user-defined function by specifying the argument in the same order as the parameter’s order:
    
    
    SELECT emp_count(45000,50000);

The function retrieves “3” which indicates that there are three employees in the emp_bio table whose salary is between “45000” to “50000”.

 **Conclusion**

In PostgreSQL, the CREATE FUNCTION statement is utilized to develop/create a user-defined function. It allows us to create a user-defined function by specifying its name, input parameters, return type, and the language used for its implementation. A user-defined function can be invoked using the SELECT statement. This post has illustrated a complete guide on creating a user-defined function in Postgres.

---
[View this page online](https://www.commandprompt.com/education/create-function-statement-in-postgresql/)

---

# How to Update a Postgres Table Using Python

> To update a Postgres table using Python, first, create a Python file, import the “psycopg2” library, make a connection between Postgres and Python, and update …

Python is a popularly used programming language that is used across various fields/domains, such as Web development, artificial intelligence, machine learning, etc. While working with mega projects developers often require a proper database to securely store and retrieve data. In such cases, Postgres emerges as the developer's first choice. Connecting Python with Postgres allows users to create, search, update, or delete data easily and securely.

This post illustrates how to update a PostgreSQL table using Python.

 **How to Update/Modify a Postgres Table Using Python?**

“psycopg2” is a widely used library that helps us in creating a connection to a PostgreSQL database using Python. Follow the provided instructions to update a Table in the PostgreSQL database using Python programming:

 **Prerequisite Step**

Before updating a table using Python, users must ensure that “psycopg2” is installed on their system. To do that, execute the following “pip” command:
    
    
    pip install psycopg2

The following snippet illustrates that psycopg2 has been successfully installed on our system:

 **Step 1: Sample Table**

Open psql and execute the “SELECT” query with the “*” wildcard to fetch the sample table’s data:

 **Step 2: Create a Python Program/File**

Launch your favorite code editor and make a Python file with the “.py” extension. Import the “psycopg2” at the start of the file:
    
    
    import psycopg2

 **Step 3: Create a Connection**

Make a Postgres Python connection by setting the required connection details, such as database name, username, port number, etc:
    
    
    conn_details = psycopg2.connect(
       host="localhost",
       database="postgres",
       user="postgres",
       password="*****",
       port= '5432'
    )

Here:

  * The connect() function is utilized to make a connection with the “postgres” database and as a “postgres” user.
  * The password must be valid according to the specified Postgres user.



 **Step 4: Update Table Record**

Suppose we want to update the joining_date of employees whose id is greater than 4 to the current date. For that particular purpose, let’s execute the below-given UPDATE query:
    
    
    cursor = conn_details.cursor()
    table_modification = "UPDATE emp_info SET joining_date = CURRENT_DATE WHERE emp_id > 4;"
    cursor.execute(table_modification)

Here:

  * First, a cursor object is created.
  * Next, the UPDATE query is executed to modify the “emp_info” table.
  * Finally, the query is executed using the “execute()” function to update the table.



 **Step 5: Save Changes**

In the below-given snippet, the commit() and close() functions are invoked to save the changes and close the cursor and the connection:
    
    
    conn.commit()
    cursor.close()
    conn.close()

 **Output**

The output snippet shows that the cursor moves to the next line without any error, which proves that a table has been successfully updated.

 **Step 6: Verify Table Updation**

Now open the “psql” terminal and run the “SELECT *” query one more time to confirm the modified table’s data:
    
    
    SELECT * FROM emp_info;

The resultant table confirms that the selected Postgres table has been successfully updated using Python.

 **Conclusion**

To update a Postgres table using Python, first, create a Python file, import the “psycopg2” library, make a connection between Postgres and Python, update the selected table, save changes, and close the cursor as well as the connection. This post has illustrated a comprehensive guide on updating a Postgres table using Python programming.

---
[View this page online](https://www.commandprompt.com/education/how-to-update-a-postgres-table-using-python/)

---

# How to Create a Postgres Table Using Python

> To create a Postgres table using Python, first, create a Python file, import the “psycopg2” library, establish the connection between Postgres and Python, and …

Python allows us to interact with and retrieve/manipulate data stored in a PostgreSQL database utilizing the Python programming language. For this purpose, Python provides different libraries, such as psycopg2, that serve as PostgreSQL adapters. Connecting Python with PostgreSQL allows us to create, search, update, and delete data, execute complex queries, build robust applications, etc.

This post illustrates how to create a PostgreSQL table using Python.

 **How to Create a Postgres Table Using Python?**

“psycopg2” is a popularly used library that assists us in establishing a connection to a PostgreSQL database using Python. Follow the given steps to create a Table in the PostgreSQL database using Python programming:

 **Prerequisite Step**

Before table creation using Python, users must ensure that “psycopg2” is installed on their system. It can be installed using the following “pip” command:
    
    
    pip install psycopg2

The following snippet depicts that psycopg2 has been successfully installed on our system:

 **Step 1: Create a Python Program/File**

Open any code editor and make a Python file with the “.py” extension. After that import the “psycopg2” in it:
    
    
    import psycopg2

 **Step 2: Establish a Connection**

Establish a Postgres Python connection by specifying the required connection details, such as database name, username, hostname, etc:
    
    
    conn_details = psycopg2.connect(
       host="localhost",
       database="postgres",
       user="postgres",
       password="*****",
       port= '5432'
    )

In the above snippet, the connect() function is used to establish a connection with the “postgres” database and as a “postgres” user.

 **Step 3: Create a Table**

Once the connection is successfully established, we can create a table in the Postgres database using Python as follows:
    
    
    cursor = conn_details.cursor()
    Table_creation = '''
       CREATE TABLE staff_information (
           stf_id SERIAL PRIMARY KEY,
           stf_name TEXT NOT NULL
       )
    '''
    cursor.execute(table_creation)

Here:

  * First, a cursor object is created.
  * After that, the CREATE TABLE command is executed to create a “staff_inforamtion” table.
  * The table is created with two columns: “stf_id” and “stf_name”.
  * Finally, the query is executed using the “execute()” function to create a table.



 **Step 4: Save Changes**

In the following snippet, the commit() and close() functions are used to save the changes and close the cursor and the connection:
    
    
    conn.commit()
    cursor.close()
    conn.close()

 **Output**

From the output snippet, you can observe that the cursor moves to the next line without any hassle, which proves that a table has been successfully created.

 **Step 5: Verify Table Creation**

Now open the “psql” terminal and execute the following “\d” command to verify the table creation:
    
    
    \d staff_information;

The output snippet confirms that the desired table has been successfully created in the Postgres database using Python.

 **Conclusion**

To create a Postgres table using Python, first, create a Python file, import the “psycopg2” library, establish the connection between Postgres and Python, create a table, save changes, and close the cursor as well as connection. This post has illustrated a detailed method of creating a Postgres table using Python programming.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-postgres-table-using-python/)

---

# How to Remove/Delete Password for a User in PostgreSQL

> To remove/delete a password for a user in Postgres, execute the “ALTER USER user_name PASSWORD NULL;” command. Replace user_name with the username of your choi…

PostgreSQL is a widely-used open-source RDBMS that offers several advanced security features, like secure authentication, encryption, etc. Implementing strong passwords is one of the most important aspects of securing a PostgreSQL database. However, sometimes users may need to remove a password for various purposes, for example if access to the database is no longer needed, etc.

This write-up illustrates a detailed guide on removing passwords for users in Postgres.

 **How to Remove/Delete Passwords for a User in PostgreSQL?**

By setting a strong password, PostgreSQL users can ensure that only authorized users can access the database and its sensitive information. However, occasionally, we may need to remove a password for a user in Postgres. For this purpose, the ALTER USER command can be executed with the PASSWORD clause. In addition to this, the password value must be specified as “NULL”. Here is the syntax to remove a password for a user in Postgres:

To remove/delete a password for a user in Postgres, you can execute the following command:
    
    
    ALTER USER user_name PASSWORD NULL;

In the above command, specify the actual name of a user(whose password needs to be deleted) in place of the user_name. Moreover, only the superusers can execute the above-stated command.

 **Example 1: Remove User Password in Postgres**

Execute the following “\du” command to see the list of available users:
    
    
    \du

Suppose we want to remove the password of a user named “joseph”. For this purpose, we will execute the below-provided command:
    
    
    ALTER USER joseph PASSWORD NULL;

The above command will set the password for the “joseph” user as “NULL”, which is equivalent to removing the password:

The output snippet signifies that the user has been altered, indicating that the password has been successfully removed.

To verify the password removal, run the following query:
    
    
    postgres=# SELECT rolname, rolpassword FROM pg_authid WHERE rolname = 'joseph';

You should see the following output, the empty 'rollpassword ' column confirms that the password has been removed.

 **  
Conclusion**

To remove/delete a password for a user in Postgres, execute the “ALTER USER user_name PASSWORD NULL;” command. In the stated command, replace user_name with the username of your choice. To execute this command you must be a superuser, else you will encounter a “permission denied” error. This post has illustrated a detailed method for removing passwords for a user in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-removedelete-password-for-a-user-in-postgresql/)

---

# How to Use UPDATE JOIN in PostgreSQL

> UPDATE JOIN in PostgreSQL is used to alter the values of the tables using the reference of the other table having a common column available in both tables.

PostgreSQL database is used to create multiple tables to store data on it and access it when needed using queries. These queries can be used to fetch data from multiple tables using JOINS and create other tables to display on the screen. JOINS are very useful in the database to gain useful information through them. Once a join is created in PostgreSQL, it can be modified using the UPDATE JOIN statement.

This guide will explain the use of UPDATE JOIN in Postgres using syntax and examples.

 **How to Use UPDATE JOIN in Postgres?**

The **UPDATE JOIN** is used to update or change the data in the table with reference to the values of the other tables. It combines two or more tables containing at least one similar field to change the value of the first table on the values of the other table.

 **Syntax**

The following is the syntax of the **UPDATE JOIN** in PostgreSQL:
    
    
    UPDATE TableA
       SET TableA.c1 = New_Value
       FROM TableB
       WHERE TableA.c2 = TableB.c2;

The above syntax:

\- It begins with the **UPDATE** keyword and the table name.  
\- Use the **SET** keyword to assign the value of the column of the above table.  
\- In the **FROM** clause, specify/write the name of the reference table.  
\- The **WHERE** keyword is used to provide the reference column from both tables.

 **Example: UPDATE JOIN in PostgreSQL**

The following example will explain the use of the **UPDATE JOIN** in PostgreSQL. First, type the following query to get the values of the “ **customers** ” table:
    
    
    SELECT * FROM customers;

Running the above query will display all the data from the “ **customers** ” table:

Use the following query to get the data of the **orders** table:
    
    
    SELECT * FROM orders;

Now use the **UPDATE JOIN** statement on the given tables:
    
    
    UPDATE customers
     SET email = 'newemail@example.com'
     FROM orders
     WHERE orders.customer_id = customers.id
      AND orders.price > 10;

The above code will update the **email** column of the “ **customers** ” table by assigning them a new value. It will take the reference from the orders table and use the “ **customer_id”** column from both and also check the price to change the email:

Use the following query to get the updated values of the table:
    
    
    SELECT * FROM customers;

Running the above code has displayed the changed value of the email column:

That’s all about using UPDATE JOIN in PostgreSQL.

 **Conclusion**

PostgreSQL tables are linked through relationships, and data is stored in these tables that can be accessed at any time. JOINS are used to combine multiple tables of the database and apply queries on them to fetch useful information through them. **UPDATE JOIN** is used to alter the values of the first table using the reference column from the other tables. This guide has demonstrated the use of UPDATE JOIN in PostgreSQL with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-update-join-in-postgresql/)

---

# How to Use PostgreSQL Transaction

> A database transaction in PostgreSQL is used to perform multiple steps at once and confirm it using the COMMIT clause or reverse it with the ROLLBACK keyword.

PostgreSQL DBMS is used to manage data by creating tables in the databases and attaching them by creating relationships between them. Accessing the data which can be useful for the consumer is the major aspect of creating databases. Manipulating tables to update values stored in them can be helpful to get useful insights by applying queries. Transactions are utilized in queries to fetch data from PostgreSQL tables and perform updates on them securely and reliably.

This guide will discuss the use of PostgreSQL transactions.

 **How to Use PostgreSQL Transaction?**

Transactions are allowed to be used in the queries to fetch data from the PostgreSQL tables and make updates to them. A database Transaction is a unit of work containing multiple steps to be performed all at once or none at all. It means that all steps in the transaction will be performed or if there occurs a problem during the transaction, it will revoke all the previous steps and start from the beginning.

 **Features of Transaction**

A database transaction contains 4 major features which are referred to as ACID:

 **Atmocity** : It guarantees that the steps involved in the transaction must be completed in an all-or-nothing method.

 **Consistency** : Consistency refers to the updation or alteration of the data of the database that should be performed according to predefined rules.

 **Isolation** : Isolation means that if there are multiple transactions happening in the database won't bother each other or have their own privacy rules.

 **Durability** : It makes sure that the committed transaction is stored in the database permanently and not just for the transaction period.

 **Syntax**

The following is the syntax for the transaction in the PostgreSQL database:
    
    
    BEGIN;
       statements
       [COMMIT | ROLLBACK];

Here in the above syntax:

\- The transaction starts with the **BEGIN** keyword that marks the transaction.  
\- Write some statements in the query to be performed inside the transaction which refers to the body of the transaction.  
\- It ends with **COMMIT** or **ROLLBACK** that is used to confirm the transaction or revoke it respectively.

 **Example 1: Starting PostgreSQL Transaction**

The following query is used to start the transaction to insert values in the table:
    
    
    BEGIN; 
    INSERT INTO trxn(name,balance)
     VALUES('Alice',10000);

Running the above command starts the transaction to insert a row containing **name** and **balance** fields:

Start a new session and run the following command:
    
    
    SELECT * FROM trxn;

The above command is supposed to print the data inserted in the table in the previous step but it shows nothing in the table. It is because the transaction is not committed which is used to update the changes permanently:

 **Example 2: Committing PostgreSQL Transaction**

This example will use COMMIT to insert data on the PostgreSQL table:
    
    
    BEGIN;
    INSERT INTO trxn(name,balance)
     VALUES('Alice',10000);
     COMMIT;

The above code starts a transaction and runs the query containing a statement to insert data in the PostgreSQL table. After that, the query ends with the **COMMIT** keyword to confirm the changes made through the transaction:

Use the following query to check the data inserted in the PostgreSQL table:
    
    
    SELECT * FROM trxn;

Running the above code will display the data inserted through the transaction:

 **Example 3: RollBack in PostgreSQL Transaction**

The next example will use the ROLLBACK clause in the transaction to revoke the changes made through the transaction. Use the following query to check the data available in the PostgreSQL table:
    
    
    SELECT * FROM trxn;

Running the above query displays that there are multiple rows inserted in the table:

Use the following code to start a transaction and then apply changes to the table but revoke them at the end:
    
    
    BEGIN;
    UPDATE trxn 
     SET balance = balance - 1500
     WHERE id = 2;
     UPDATE trxn
     SET balance = balance + 1500
     WHERE id = 4; 
     ROLLBACK;

This code will subtract the balance from id 2 and add it to the balance of id 4 on the “ **trxn** ” table. At the end of the query, the **ROLLBACK** keywords are used to reverse the updation to the table:

Use the following code to check if there is any change occurred through the above transaction:
    
    
    SELECT * FROM trxn;

The following screenshot displays that the transaction has made no change to the PostgreSQL table:

That’s all about using transactions in PostgreSQL.

 **Conclusion**

A database transaction in PostgreSQL acts as a unit containing multiple steps in it to be performed at once or none at all. The syntax of the database transaction in PostgreSQL contains the BEGIN keyword marking the start of the transaction. It then contains statements of the query and ends with the COMMIT or ROLLBACK clauses used to confirm or reverse the changes respectively. This guide has demonstrated the use of PostgreSQL transactions with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-postgresql-transaction/)

---

# How to Use NATURAL JOIN in PostgreSQL

> NATURAL JOIN supports INNER, LEFT, and RIGHT JOINs but uses INNER by default as it is used to combine multiple tables having the same field names.

To store and retrieve data efficiently, databases rely on relationships between tables. This enables users to access and use the datasets at any given time. Relational databases like PostgreSQL provide query support for accessing these datasets. To access related data from multiple tables, JOINS can be used in PostgreSQL. NATURAL JOIN is the type of JOIN supporting Multiple JOINs but uses INNER JOIN by default.

This guide will explain how to use NATURAL JOIN in PostgreSQL.

 **How to Use NATURAL JOIN in PostgreSQL?**

The **NATURAL JOIN** includes **INNER** , **LEFT** , and **RIGHT JOINs** within the single JOIN to combine multiple tables. If the user does not specify any of these keywords, the NATURAL JOIN automatically uses the INNER JOIN as a default JOIN. To apply a NATURAL JOIN, the tables must have one common column name between the two of them.

 **Syntax**

The syntax to use the NATURAL JOIN is as follows:
    
    
    SELECT <Columns>
     FROM <TableA>
     NATURAL [INNER, LEFT, RIGHT] JOIN <TableB>;

In the above code block:

\- The **SELECT** keyword is used to select columns or fields of the table mentioned after the **FROM** keyword.  
\- The **NATURAL** keyword can be followed by these [ **INNER, LEFT, RIGHT** ] **JOINs** containing the name of the second table.

 **Example 1: Use NATURAL JOIN to Combine Tables**

Use the following query to get the data of the **person** table:
    
    
    SELECT * FROM person;

Running the above code with “ ***** ” displays all the data/records of the person table:

Use the following code to get data from the vehicle table:
    
    
    SELECT * FROM vehicle;

The following is the query for the NATURAL JOIN:
    
    
    SELECT * FROM vehicle
     NATURAL JOIN person;

The above query will join the vehicle table with the person table and display all records having data in the common field:

 **Example 2: Use NATURAL JOIN With ORDER Clause**

NATURAL JOIN can be used with additional conditions using the ORDER clause as mentioned below:
    
    
    SELECT * FROM vehicle
     NATURAL JOIN person
    ORDER by vehicle.price;

Running the above query will join both the vehicle and person table and display the results according to the price of the vehicle:

That’s all about using NATURAL JOIN in PostgreSQL.

 **Conclusion**

 **NATURAL JOIN** in PostgreSQL databases can be used to join multiple tables containing the same field name. NATURAL JOIN contains **INNER** , **RIGHT** , and **LEFT** JOINs and all of them can be used with it however, by default it uses INNER JOIN. The user can use the **ORDER** clause with NATURAL JOIN to add a sorting condition to the resultant table. This guide has explained the use of NATURAL JOIN in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-natural-join-in-postgresql/)

---

# How to Use FULL OUTER JOIN in PostgreSQL

> FULL OUTER JOIN combines the working of both LEFT and RIGHT JOINs to produce a result table containing matched and unmatched results from the tables.

Relational databases such as MySQL, PostgreSQL, etc. store data in multiple tables that are related through unique keys assigned to them. There is always a need to combine two or more tables in the database to produce a resultant table containing comprehensive information. JOINs are used to extract records from multiple locations called tables based on some conditions in the database.

This guide will explain the use of FULL OUTER JOIN in PostgreSQL.

 **How Does FULL OUTER JOIN Work in Postgres?**

FULL OUTER JOIN in PostgreSQL is used to generate all the records from all the tables involved in the JOIN. It is the combination of LEFT and RIGHT JOIN as it provides all the matched and unmatched records from all the tables. It only works when it finds a match of a column name in both or all tables involved in the operation:

 **Syntax**

Following is the syntax of the FULL OUTER JOIN:
    
    
    SELECT <Columns>
    FROM <TableA>
    FULL [OUTER] JOIN <TableB> ON <TableA.id> = <TableB.id>;

This code block:

  * Selects a column list from the tables to be joined/merged with another one.
  * Apply FULL OUTER JOIN containing the second table and ON condition containing matched columns referencing their respective tables:



 **Example 1: Use FULL OUTER JOIN to Combine Tables**

The following query is used to fetch the data from the vehicle table to start the first example of FULL OUTER JOIN:
    
    
    SELECT * FROM vehicle;

Running the above query will display all records of the vehicle table:

Use this query to get the data of the person table:
    
    
    SELECT * FROM person;

It will display the results of data present in the person table:

Use the following query to apply FULL OUTER JOIN on the vehicle and person tables:
    
    
    SELECT * FROM person p
    FULL OUTER JOIN vehicle v 
     ON v.id = p.id;

The above code contains:

  * It selects all records from the **person** table and applies **FULL OUTER JOIN** with the **vehicle** table.
  * It uses **id** columns from vehicle and person tables with the **ON** condition:



 **Example 2: Use FULL OUTER JOIN With WHERE Clause**

Use the following query to apply FULL OUTER JOIN based on the condition specified in the WHERE clause:
    
    
    SELECT * FROM person p
    FULL OUTER JOIN vehicle v 
     ON v.id = p.id
    WHERE vehicle_id IS NULL;

Here in the above code block:

  * It uses the **id** column from **person** and **vehicle** tables to apply **FULL OUTER** JOIN on them
  * The additional condition uses the **WHERE** clause to find a specific record that does not contain any value in the **vehicle_id** column:



That’s all about the use of FULL OUTER JOIN in PostgreSQL.

 **Conclusion**

In PostgreSQL, FULL OUTER JOIN combines the working of LEFT and RIGHT JOINs to join multiple tables on the database. It generates all the data matched and unmatched from the tables involved in the joining query having a common column between them. The ON condition is used with FULL OUTER JOIN containing common columns from the tables and the WHERE clause can add conditions to it. This guide has explained the use of FULL OUTER JOIN in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-full-outer-join-in-postgresql/)

---

# How to Use DELETE JOIN in PostgreSQL

> DELETE JOIN is not directly supported by the PostgreSQL database but a DELETE statement with either USING or WHERE clauses can be used for this purpose.

To access related data from multiple tables, JOINS can be used in PostgreSQL. However, the " **DELETE** " command can be used to remove a Join if it is no longer needed. The DELETE command allows the removal of data from multiple tables according to the defined “join” conditions.

This guide will explain how to delete a JOIN in PostgreSQL using practical examples.

 **How to Use DELETE JOIN in PostgreSQL?**

The DELETE JOIN is not supported by PostgreSQL directly but the USING clause can be used along with the DELETE keyword to get the same effect. DELETE JOIN can be used to delete data from one table using the reference of other tables. The reference table can either be a single table or multiple tables joined to apply DELETE JOIN in PostgreSQL.

 **Syntax**

The following query is the syntax of the DELETE statement with USING keyword:
    
    
    DELETE FROM Table_A
    USING Table_B
    WHERE condition
    RETURNING returning_columns;

The above query:

  * Starts with a **DELETE** statement containing the table name and **USING** clause that has the reference table inside it.
  *  **WHERE** condition has the columns which are used to provide the similarity in both the tables for joining the data.



The following query provides a simple description of the **DELETE** statement with **USING** clause with **A** and **B** tables having an **id** column common between them:
    
    
    DELETE FROM tA
    USING tB
    WHERE tA.id = tB.id;

 **Example 1: DELETE JOIN in PostgreSQL**

First, get the data from the **orders** table using the below command:
    
    
    SELECT * FROM orders;

The above query displays the data from the **orders** table upon its execution:

Use the following code to get data from the “ **customers** ” table:
    
    
    SELECT * FROM customers;

Use the following query to use as the **DELETE JOIN** :
    
    
    DELETE FROM orders
    USING customers
    WHERE orders.customer_id = customers.id;

The above code deletes the data from the **orders** table using the “ **customers** ” table having the **customer_id** column common between them:

Check the data from the **orders** table by using the following query:
    
    
    SELECT * FROM orders;

All the data is deleted from the orders table:

 **Example 2: Sub-Query For DELETE JOIN**

 **WHERE** clause can be used instead of **USING** to get the **DELETE JOIN** results as this example uses it to delete data. First, use the following query to access the data from the **orders** table:
    
    
    SELECT * FROM orders;

Use the below-given query to apply **DELETE JOIN** in the PostgreSQL table:
    
    
    DELETE FROM orders
    WHERE customer_id IN (SELECT customer_id FROM customers);

The above code deletes the data from the orders table where **customer_id** is common in the **customers** and **orders** table:

The following query displays the deletion of data from the **orders** table:
    
    
    SELECT * FROM orders;

That’s all about using DELETE JOIN in PostgreSQL.

 **Conclusion**

PostgreSQL does not support the direct use of DELETE JOIN in its queries; however, the DELETE statement with USING clause can be used for this purpose. DELETE statements with either USING or WHERE keywords can produce similar results compared to the DELETE JOIN. This guide has explained the use of both these methods with examples in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-delete-join-in-postgresql/)

---

# Creating an AWS RDS PostgreSQL Database in pgAdmin

> Connect to the AWS RDS PostgreSQL in pgAdmin and create a database from there. Use a Query Tool to perform database operations.

PostgreSQL is an open-source and advanced RDS that supports both SQL (relational) and JSON (non-relational) queries. Amazon RDS service allows the user to create database instances using the PostgreSQL engine on the cloud. The pgAdmin application can be used to connect to the DB instance and create databases on it.

This guide will explain how to create an RDS PostgreSQL database in pgAdmin.

 **Creating an AWS RDS PostgreSQL Database in pgAdmin**

To create a database in pgAdmin, create a DB instance in the AWS RDS dashboard and click on the “ **View connection details** ” button:

This page contains the connection credentials which will be used later to connect to the pgAdmin:

Open the pgAdmin application from the local system:

Provide the password for the application and click on the “ **OK** ” button:

Click on the “ **Add New Server** ” button from the “ **Quick Links** ” section:

Type the name of the server in the “ **General** ” page:

Head into the “ **Connection** ” page to provide the credentials like Endpoint in the Host name/address tab, username, and password of the DB instance. These credentials can be found on the AWS RDS dashboard mentioned above and after that, click on the “ **Save** ” button:

The server has been added to the pgAdmin and its dashboard is visible on the screen:

Right-click on the “ **Databases** ” button from the server, expand the “ **Create** ” menu, and click on the “ **Database…** ” button:

Type the name of the database and click on the “ **Save** ” button:

Right-click on the name of the database to open the menu and click on the “ **Query Tool** ” button from the list:

Type the following query in the query tool to create a new table:
    
    
    CREATE TABLE test
       (
     ID SERIAL PRIMARY KEY,
       testID VARCHAR(50),
       testhistory VARCHAR(600),
       CREATED TIMESTAMP
       );

Run the above query by clicking on the “run” icon given in the navigation bar. It will create a table named “ **test** ” which contains “ **ID** ” as its primary key, “ **testID** ”, “ **testhistory** ” and “ **CREATED** ” as its fields:

Insert the data into the test table using the following query:
    
    
    INSERT INTO test (testID,   testhistory, CREATED) 
    VALUES ('test#4854', '{}', NOW());

The above query contains:

\- INSERT INTO contains the name of the fields for the test database.  
\- VALUES contain the data to be inserted in these fields:

Use the “SELECT” query with the “*” symbol to fetch all fields of a table:
    
    
    SELECT * FROM test;

The above query will fetch everything available in the test table:

That’s all about creating an AWS RDS PostgreSQL database in pgAdmin.

 **Conclusion**

To create an AWS RDS PostgreSQL database in pgAdmin, connect to the DB instance by providing its credentials from the pgAdmin application. After that, create a database from the server added to pgAdmin and configure it before saving it. Open a Query tool to perform any database operation using the queries. This guide has explained the process of how to create an AWS RDS PostgreSQL database in pgAdmin.

---
[View this page online](https://www.commandprompt.com/education/creating-an-aws-rds-postgresql-database-in-pgadmin/)

---

# How to Create PostgreSQL Database in AWS RDS

> Visit the AWS RDS dashboard from the AWS account and click the “Create database” button to configure the DB using a PostgreSQL engine and its latest version.

Amazon Web Services or AWS is the cloud service providing platform containing over 200 IT-based services over the internet. Relational Database Service or RDS is the AWS service that is used to create databases using different engines on the cloud. The user is allowed to create a database using the PostgreSQL engine in the AWS RDS.

This guide will explain the creation of an AWS RDS PostgreSQL database.

 **How to Create an AWS RDS PostgreSQL Database?**

To create a PostgreSQL database in AWS RDS, it is required to sign in to the AWS dashboard and click on the “ **RDS** ” button:

Clicking on the RDS button will direct the user to the RDS dashboard; click on the “ **Create database** ” button from there:

Click on the “ **Standard create** ” button to choose a database creation method:

To create a “ **PostgreSQL** ” database, select its engine from the available “ **Engine options** ”:

Choose the latest version of the PostgreSQL engine and then select the “ **Free Tier** ” option from the Templates section:

Type the name of the database instance and the Master username:

Set the password for the master user and confirm it by typing it again:

Configure the storage section by providing its type, Allocated Storage, and threshold:

Choose the “ **Compute resource** ” and “ **Network type** ” from the connectivity section:

Select the subnet of the database and select “ **Yes** ” to allow public access:

Select the existing VPC that is already available on the AWS account:

Select the “ **Password authentication** ” option from the “ **Database authentication** ” section:

Configure the “ **Monitoring** ” section by selecting the retention period and AWS KMS key:

Review the settings and click on the “ **Create database** ” button:

The PostgreSQL database has been created successfully:

That’s all about how to create a PostgreSQL database in AWS RDS.

 **Conclusion**

To create a PostgreSQL database in AWS RDS, visit the RDS dashboard from the AWS account after signing in to it. On the RDS dashboard, create an RDS database using the PostgreSQL engine and its latest version. Configure its settings by typing the name and password for the database to be used for the connection. This guide has explained the creation process of a PostgreSQL database in AWS RDS.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-postgresql-database-in-aws-rds/)

---

# How to Use SELF JOIN in PostgreSQL

> SELF JOIN is used in the PostgreSQL database to join a table to itself when tables are created in a hierarchy fashion to apply queries on it.

In relational databases like PostgreSQL, data can be distributed across multiple tables to ensure efficient organization. However, retrieving comprehensive information often requires fetching data from multiple tables. In that particular scenario, JOINs come in handy as they allow us to gain useful insights from the data stored in tables.

This guide will explain how to use SELF JOIN in PostgreSQL.

 **How to Use SELF JOIN in PostgreSQL?**

SELF JOIN allows us to join/merge a table with itself and it is needed when tables are created in a hierarchy fashion, to draw the details of the table. It is more of a strategy to join a table using its own reference and joining itself, table can use either of the JOIN like INNER, LEFT, etc. It uses tables with their alias name which is the temporary name given at the time of the query execution.

 **Syntax With INNER JOIN**

The following is the syntax for the Postgres SELF JOIN:
    
    
    SELECT <Columns>
     FROM <Table> <Alias1>
     INNER JOIN <Table> <Alias2> ON Alias1.column = Alias2.column;

In this code block:

\- The SELECT keyword selects one, multiple, or all columns of the table  
\- It starts the query at FROM keyword which contains the table name and its Alias name, which is a temporary name for the query  
\- An alias can be used to specify the table name and the column name of the table.  
\- The INNER JOIN contains the table name with an alias to join the column provided in the ON condition.

 **Syntax With LEFT JOIN**

SELF JOIN can also be used with LEFT JOIN via the following syntax:
    
    
    SELECT <Columns>
     FROM <Table> <Alias1>
     LEFT JOIN <Table> <Alias2> ON Alias1.column = Alias2.column;

The above snippet uses almost the same syntax as the previous one with a minor change, i.e. LEFT JOIN instead of INNER JOIN.

 **Example 1: SELF JOIN Using LEFT JOIN**

To start the example, use the following query to fetch the table created on the PostgreSQL database:
    
    
    SELECT * FROM orders;

The above query will return all the records of the “orders” table:

Use the following query to apply SELF JOIN on the orders table:
    
    
    SELECT o1.customer_id, o1.order_date
     FROM orders o1
       LEFT JOIN orders o2 
      ON o1.customer_id = o2.customer_id
      AND o1.order_date = o2.order_date
      AND o1.order_id <> o2.order_id;

The above query performs the following tasks:

\- It selects two columns **customer_id** and **order_date** from the orders table and assigns them their aliases.  
\- After that, it applies **LEFT JOIN** to the order table with the second alias.  
\- **ON** condition returns the customer_id and order_date with order by **order_id** column:

 **Example 2: SELF JOIN Using INNER JOIN**

Take another example using the employee table to use SELF JOIN with INNER JOIN, start by accessing the employee table using the given query:
    
    
    SELECT * FROM employee;

Running the above query will return the data from the employee table:

Use the following query to apply SELF JOIN on the employee table:
    
    
    SELECT
      a1.first_name || ' ' || a1.last_name employee,
      a2 .first_name || ' ' || a2 .last_name manager
       FROM
      employee a1
       INNER JOIN employee a2 ON a2 .employee_id = a1.manager_id
     ORDER BY manager;

Here in the above code block:

\- The **SELECT** query is used to fetch the data from the **first_name** and **last_name** columns of the **employee** table with their aliases assigned to them.  
\- **INNER JOIN** applies **SELF JOIN** on the employee table using the **ON** condition on the employee_id and manager_id.  
\- It adds to the condition using **ORDER BY** to display the result according to the **manager** hierarchy:

That’s all about using SELF JOIN in PostgreSQL.

 **Conclusion**

In PostgreSQL, SELF JOIN allows the user to apply SELF JOIN to the table using JOINs like INNER, LEFT, etc. to get the reference to itself. The **ON** condition can be used with the **INNER** and **LEFT** JOIN to apply **SELF JOIN** on the table to join a table using hierarchy distribution. The tables and columns used in the SELF JOIN should contain their **alias** names for the query execution. This guide has explained the use of SELF JOIN in the PostgreSQL tables.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-self-join-in-postgresql/)

---

# How to Connect a DB Instance Running on PostgreSQL in AWS RDS

> Create an AWS RDS DB instance from the service dashboard and use PostgreSQL as its engine. Use Endpoint and username in the “psql” command to connect to it.

A database instance on the AWS platform acts as the building block to build an environment for creating multiple databases on the cloud. A Database instance contains many databases on the cloud which is an isolated database environment for the user. The user can connect to the DB instance running on the PostgreSQL using the AWS CLI command.

This guide will explain connecting a DB instance running on PostgreSQL in AWS RDS.

 **How to Connect a DB Instance Running on PostgreSQL in AWS RDS?**

To create a DB instance, Visit the “ **RDS** ” service by clicking its name from the AWS Management Console:

Click on the “ **Create database** ” to start the configuration of the database:

Select the database creation method from the “ **Standard create** ” and “ **Easy create** ” methods:

Select the “ **PostgreSQL** ” engine to run the DB instance on it:

Select the engine version of PostgreSQL and select the “ **Free tier** ” template:

Type the name of the database instance with its username:

Set the password for the user and confirm it also:

Configure the DB instance by selecting its class and type:

Locate the storage section and configure its settings from the platform:

Set the connectivity of the compute resource and network type:

Select the VPC and subnet group of the database instance with public accessibility:

Set the security groups with inbound rules attached to them:

Set the password authentication as the password has been set for the user previously:

Specify the Retention period and AWS KMS key in the Monitoring section:

Review the configurations of the DB instance and click on the “ **Create database** ” button to complete the creation process:

The database has been created successfully now click on its name to access the summary:

Click on the “ **Connectivity & security**” section under the Summary section:

Copy the “ **Endpoint** ” to be used in the AWS CLI command to connect to it:

Use the following command to connect to it and simply change the endpoint and Username according to your DB instance:
    
    
    psql -h database.c6d50j4forkq.ap-southeast-1.rds.amazonaws.com -U postgres

Running the above command will ask the user to provide the password in order to connect to the PostgreSQL DB Instance:

That’s all about connecting to the DB instance running on the PostgreSQL in AWS RDS.

 **Conclusion**

To connect to the DB instance on PostgreSQL in AWS RDS, create a database instance from its dashboard. Configure the DB instance by choosing the PostgreSQL engine type and then add Username with a password attached to it. Once the database is created, use the endpoint, Master Username in the “psql” command and specify the password for the user. This guide has demonstrated the process of connecting to the DB instance running on PostgreSQL in AWS RDS.

---
[View this page online](https://www.commandprompt.com/education/how-to-connect-a-db-instance-running-on-postgresql-in-aws-rds/)

---

# How to Connect to My Amazon RDS for PostgreSQL Using IAM Authentication

> Create an RDS database with IAM authentication enabled. Attach the IAM role to the EC2 instance and connect to it to generate the SSH key.

AWS allows the user to create DB instances using the Amazon RDS dashboard and connect them to the pgAdmin or other clients. It also allows the user to create a secure connection using either a user password or an IAM authentication key. The key is usable for only 15 minutes and after that, the user needs to create a new key to be able to connect to the server.

This guide will explain the use of IAM credentials to connect the AWS RDS PostgreSQL database.

 **How to Connect PostgreSQL AWS RDS Database Using IAM Authentication?**

To connect to the IAM identification, visit the RDS dashboard from the AWS Management Console:

After that, head into the database instance by clicking on its name:

Head into the “ **Configuration** ” section from the database page:

Make sure that the IAM DB authentication is “ **Enabled** ”:

Visit the IAM dashboard from the AWS dashboard:

Click on the “ **Roles** ” page from the left panel:

Create an IAM role for the RDS:

Use the following policy for the IAM role by simply changing the resource section containing the Account ID and DB Resource ID:
    
    
    {
      "Version": "2012-10-17",
      "Statement": [
      {
      "Effect": "Allow",
      "Action": [
      "rds-db:connect"
      ],
      "Resource": [
      "arn:aws:rds-db:ap-southeast-1:***********3:dbuser:<DB   Resource ID>/Master <Username>"
      ]
      }
      ]
       }

After that, visit the “ **Connectivity & security**” section and copy the Endpoint:

Use the following command by changing the username and endpoint copied from the RDS page:
    
    
    psql -h database-1.c6d50j4forkq.ap-southeast-1.rds.amazonaws.com -U postgres

Create a new user named “ **iamuser** ” using the LOGIN keyword:
    
    
    CREATE USER iamuser WITH   LOGIN;

After that, grant the IAM role to the user created previously:
    
    
    GRANT rds_iam TO iamuser;

The role has been created and attached to the user:

Visit the EC2 dashboard and create an EC2 instance:

Select the instance and expand the “ **Actions** ” menu, hover over the “ **Security** ” list, and select the “ **Modify IAM role** ” button:

Select the role and click on the “ **Update IAM role** ” button:

Once the role is attached to the instance, select it and click on the “ **Connect** ” button:

Copy the command provided in the “ **SSH client** ” section:

Paste the command on the terminal and change the path of the key pair file:

Use the following commands to get the password used to connect to the PostgreSQL database:
    
    
    export RDSHOST="aurorapg-ssl.cluster-XXXXXXXXXXX.us-west-2.rds.amazonaws.com"
     export PGPASSWORD="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --region   ap-southeast-1 --username iamuser)"
       echo $PGPASSWORD

The above command will provide the SSL token password:

Open the pgAdmin client from the local system and click on the “ **Add New Server** ” button:

Type the name of the server and turn off the “ **Connect now** ” button from the “ **General** ” tab:

Head into the “ **Connection** ” tab to type the Hostname and username of the DB instance from AWS RDS:

Visit the “ **Parameter** ” page to change the SSL mode value to “ **require** ” and click on the “ **Save** ” button:

Execute the database server and paste the password obtained from connecting to the EC2 instance and click on the “ **OK** ” button:

The connection has been established successfully:

That’s all about connecting to the AWS RDS PostgreSQL database using IAM authentication.

 **Conclusion**

To connect to the DB instance using IAM authentication, create an RDS database instance with IAM authentication enabled. Create an IAM role with a policy allowing the DB connection using IAM and then attach it to the EC2 instance. Connect to the EC2 instance using its command from the SSH client and get the password from there. Use the obtained password to connect to the AWS RDS on the pgAdmin client application from the local system.

---
[View this page online](https://www.commandprompt.com/education/how-to-connect-to-my-amazon-rds-for-postgresql-using-iam-authentication/)

---

# How Does LEFT JOIN Work With PostgreSQL

> LEFT JOIN is used in the PostgreSQL database to return all the records from the left table and matched records from the right table.

JOINs hold a very important place in the field of the database as they can be used to combine multiple tables on the DB. They are used in both relational and sequel databases as they carry the same importance in both types of databases. **LEFT JOIN** is the type of JOINs that combines tables and returns all data from the left table and gets only the corresponding records of the right table.

This guide will explain the working of LEFT JOIN with PostgreSQL.

 **How Does LEFT JOIN Work With PostgreSQL?**

LEFT JOIN is used in the PostgreSQL database to return data from the left table and corresponding records from the right table. For instance, “A” is the left table and “B” is the right table, applying LEFT JOIN will return all the records from table A and only matched ones from table B.

 **Syntax**

The following code block contains the syntax to apply the LEFT JOIN in the PostgreSQL database:
    
    
    SELECT <Columns> 
    FROM <TableA>
     LEFT JOIN <TableB>   
     ON TableA.Column_x = TableB.Column_y;

The above code suggests:

\- **SELECT** is a statement used to choose one or more **Columns** of the given table and the “ ***** ” is used to select all columns from the table which in this case is the left table or table A.  
\- The **LEFT JOIN** keeps the name of the table to be joined with the “TableA”.  
\- The **ON** keyword is used to define the joining condition.

 **Example 1: Combine Tables Using LEFT JOIN**

The following example takes two tables from the PostgreSQL database and applies LEFT JOIN to them. This query will be used to get all the data from the “ **car** ” table as it uses “ ***** ” for columns to get the complete table:
    
    
    SELECT * FROM car;

The above query returns all the data and columns available on the car table:

Another sample table named “ **person** ” is created with different records. Execute the given query to get all its records:
    
    
    SELECT * FROM person;

Running the above query return the data from the person table:

 **SideNote** : The last column which is the “ **car_id** ” in the above snippet acts as the foreign key of the car table.

The following query is used to apply LEFT JOIN:
    
    
    SELECT * FROM person
     LEFT JOIN car ON car.id = person.car_id;

Here in the above code snippet:

\- The SELECT query is used to fetch all the data from the **person** table based on the PK and FK which is the **car_id** column.  
\- The condition for the LEFT JOIN is defined using the **ON** keyword which takes the **id** column from the **car** table:

The output shows that the result set contains all the records of the **person** table and matching records of the **car** table.

 **Example 2: Using WHERE Clause With LEFT JOIN**

Use the following query to return only null values in the “car” table indicating that they don't have a car:
    
    
    SELECT * FROM person
     LEFT JOIN car ON car.id =   person.car_id
     WHERE car.* IS NULL;

The above code contains one additional condition to the previous query which goes like this:

\- Select all records from the person table and apply **LEFT JOIN** on the car table.  
\- The **WHERE** condition limits the returning record as it only asks for the record that doesn’t have a value in the car table:

That’s all about the working of the LEFT JOIN with the PostgreSQL database.

 **Conclusion**

In PostgreSQL, LEFT JOIN is used to return all data from Table A or the Left only the matched values from the right table or Table B. The **ON** keyword is used with the **LEFT JOIN** to define the joining condition. Moreover, the WHERE clause can be used with the LEFT JOIN to combine the filtered data. This guide has explained the working of the LEFT JOIN in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-does-left-join-work-with-postgresql/)

---

# How to Use RIGHT JOIN in PostgreSQL

> In PostgreSQL, RIGHT JOIN is used to merge two tables in the database and return all records of the Right table and only matched records from the left one.

Various JOINS are used in the PostgreSQL database to fetch joined records from multiple tables. For instance, the " **RIGHT JOIN** " joins the data from the right table and only the corresponding values from the left table. It retrieves Null for all the records on the left that do not contain any value or don’t match with the right table.

This guide will explain how to use RIGHT JOIN in PostgreSQL.

 **How to Use RIGHT JOIN in PostgreSQL?**

Databases use RIGHT JOIN to merge or combine multiple tables in the PostgreSQL database by applying different queries to them. It is required to have knowledge about the structure of the tables, like which one is the right table and which is the left one. Applying RIGHT JOIN will return all the data available on the right table and corresponding data from the left one.

 **Syntax**

The following code snippet illustrates the syntax of Postgres’ RIGHT JOIN:
    
    
    SELECT <Columns>
    FROM <TableA>
     RIGHT JOIN <TableB>
     ON <TableA.Column_x> = <TableB.Column_y>;

The above code block contains the following information:

\- It selects the list of columns present in the right table. Use the “ ***** ” sign with the SELECT statement to fetch all columns in the said table.  
\- Specify the right table or Table A in the FROM clause.  
\- Specify the **RIGHT JOIN** followed by the name of the left table or Table B which needs to be merged with the right table or Table A.  
\- **ON** clause contains the condition on which the tables will be combined.

 **Example 1: Combine Tables With RIGHT JOIN Using ON Clause**

The example displays the RIGHT JOIN being applied on two tables created in the PostgreSQL database using the following query to fetch data from the person table:
    
    
    SELECT * FROM person;

Running the above query will display all records from the table person:

Another table named “vehicle” containing records about vehicles can be accessed using the following query:
    
    
    SELECT * FROM vehicle;

The above query returns the records available in the vehicle table:

Use the following query to apply RIGHT JOIN on the given tables:
    
    
    SELECT * FROM vehicle
    RIGHT JOIN person ON vehicle.id = person.vehicle_id;

The above code suggests the following:

\- The SELECT keyword with a “*” will get all the data from the vehicle table.  
\- **RIGHT JOIN** is used on the person table with conditions specified using the **ON** clause.  
\- The specified condition states that match the values from the **id** column on the vehicle table with **vehicle_id** from the person table:

The output displays all the records of the **vehicle** table and the matching records of the **person** table.

 **Example 2: RIGHT JOIN With USING Clause**

RIGHT JOIN with USING condition combines the tables having the same column name between them. In the following example, the join condition is specified in the RIGHT JOIN via the “USING” clause:
    
    
    SELECT * FROM vehicle
     RIGHT JOIN person USING(id);

The above code applies RIGHT JOIN on the “vehicle” and “person” tables based on the “id” column:

 **Example 3: Using RIGHT JOIN With WHERE Clause**

The following query contains another example of the RIGHT JOIN with the additional condition using the **WHERE** clause:
    
    
    SELECT * FROM vehicle
     RIGHT JOIN person USING(id)
     WHERE vehicle_id IS NULL;

The above query will only return records that don’t contain any value in the vehicle-id column:

That’s all about using RIGHT JOIN in the PostgreSQL database.

 **Conclusion**

In PostgreSQL, **RIGHT JOIN** is used to merge two tables in the database and return all records of the Right table and only matched records from the left one. The user is allowed to add conditions with the help of **ON** and **USING** clauses to apply RIGHT JOIN. Additional conditions can be applied to get specific records using the WHERE clause with the RIGHT JOIN. This guide has explained the use of RIGHT JOIN in PostgreSQL tables.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-right-join-in-postgresql/)

---

# How to Create an INDEX in PostgreSQL

> In PostgreSQL, indexes can be created using the CREATE INDEX statement followed by the index name and then providing the table name inside the ON condition.

Databases store a huge amount of data daily for millions of companies across the globe which is then used to get useful information. PostgreSQL allows the user to query the data and find their information from the database created on it. It can take a lot of time to locate the required data from the pool of big data available in the database. To save time and energy by fetching data quickly, PostgreSQL allows the user to create indexes for tables and columns on a database.

This guide will explain how to create an index in PostgreSQL.

 **How to Create an INDEX in PostgreSQL?**

Creating indexes allows the user to mark the location of a certain table or column which are used frequently in their queries. Using indexes, the database remembers the location of the column or table and fetches it every time the user runs the query. Without indexes, the query optimizer has to search from the whole table to find the exact match and load it for the user which can take time.

 **Syntax**

The following is the syntax to create an index in the PostgreSQL table:
    
    
    CREATE INDEX <index_name>
     ON <tab> <USING method>
       (
      column_name [ASC | DESC] [NULLS {FIRST | LAST }],
      ...
       );

Here the syntax contains:

\- The **CREATE INDEX** command contains the name of the index to be created. It can be any valid name; however, it is a good practice to specify an easy-to-remember “index name”.  
\- Type the name of the table within the **ON** condition which should contain the index.  
\- Provide the index method such as “ **btree** ”, “ **gin** ”, “ **hash** ”, etc. with the table name and it uses “ **btree** ” as a default method.  
\- The index method should contain the name of the column on which the index should be applied and specify its order like ASC or DESC. It is optional to specify the order so if the user skips the order, Postgres uses ascending by default.

 **Example 1: Create an Index**

Follow this example to find out how to create an index in the PostgreSQL table, start by accessing the **employees** table:
    
    
    SELECT * FROM employees;

The employees' table does not contain any data for now but contains multiple columns:

The following command will be used to explain how the query optimizer applies the query on the table:
    
    
    EXPLAIN SELECT * FROM employees
     WHERE department = 'Null';

It scans the complete table to find the **department** column containing a **Null** value:

Use the following query to create an index named “ **idx_department** ” on the **department** column of the “ **employees** ” table:
    
    
    CREATE INDEX idx_department 
     ON employees (department);

Again check the explanation of the query by adding EXPLAIN before it:
    
    
    EXPLAIN SELECT * FROM employees
     WHERE department = 'Null';

Now the query optimizer only scans the column using the index to find its referenced value:

 **Example 2: Create Multiple Indexes**

The next example explains how to create multiple indexes by separating them using a comma as shown below:
    
    
    CREATE INDEX idx_department_age 
     ON employees (department, age);

The query has created two indexes for the **department** and **age** column from the “employees” table:

Check both the indexes available in the “ **Indexes** ” section under the “ **employees** ” table:

That’s all about creating Indexes in the PostgreSQL table.

 **Conclusion**

In PostgreSQL, the indexes are used to fetch data quickly and efficiently from a huge pool of data in a specific database. The user can create one index at a time or multiple indexes by separating them using commas. The query optimizer uses indexes to locate the exact match from the tables and without indexes it simply looks at the whole table to find the data. This guide has explained the Index in databases and its creation in the PostgreSQL databases.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-an-index-in-postgresql/)

---

# How to Create a Materialized View in PostgreSQL

> To create a materialized view in Postgres, execute the CREATE MATERIALIZED VIEW statement along with the AS keyword followed by the base query.

Applying queries to the database for getting data stored on it can become complex when using large and complicated queries. The research mechanism also takes up time as it scans all the fields of the tables to get specific results. Views can be used to create virtual tables that lie under/beneath the actual tables to scan specific fields upon querying.

This guide will explain the process for the creation of a materialized view in the PostgreSQL database.

 **How to Create/Use a Materialized View in PostgreSQL?**

Materialized views are helpful while accessing data quickly and efficiently that’s why they are used in data warehouses and databases. They are used to combine multiple tables to get those fields that are desired by the user to run queries on. For instance, if the user wants to get the view of the performance of people who have been working for more than 10 years can be done using Materialized view.

 **Syntax: Creating Materialized View**

Use the following syntax which is used in the PostgreSQL database to create a materialized view with a query having data of the tables:
    
    
    CREATE MATERIALIZED VIEW view_name
     AS
     query
     WITH [NO] DATA;

The above-provided snippet states:

\- Type the name of the view after the **VIEW** keyword inside the **CREATE MATERIALIZED** clause.  
\- The **AS** keyword contains the query fetching data from tables.  
\- Use **WITH DATA** clause to load data into materialized view while viewing creation.  
\- **WITH NO DATA** makes data unreadable and needed to load before reading it.

 **Syntax: Refreshing Data for Materialized View**

 **REFRESH MATERIALIZED VIEW** can be used to refresh/replace the data of materialized view:
    
    
    REFRESH MATERIALIZED VIEW view_name;

Use the **CONCURRENTLY** clause to avoid locking the table while executing queries on it:
    
    
    REFRESH MATERIALIZED VIEW CONCURRENTLY view_name;

 **Example 1: Create Materialized View**

Use the following query to access data from the “ **mytable** ” table:
    
    
    SELECT * FROM mytable;

Running the above query will display the data from the table named mytable:

Create a materialized view of the table with name and age columns containing the value of age greater than 18:
    
    
    CREATE MATERIALIZED VIEW myview AS
     SELECT name, age
     FROM mytable
     WHERE age > 18;

Now execute the following “SELECT” query to display the VIEW:
    
    
    SELECT * FROM myview;

The above code doesn't display any data on the table so let’s refresh the selected materialized view. To do that, execute the given query:
    
    
    REFRESH MATERIALIZED VIEW myview;

Utilize the below query again to fetch data for myview:
    
    
    SELECT * FROM myview;

Running the above query will display the data of people above 18 age:

That’s all about creating and refreshing a materialized view in PostgreSQL.

 **Conclusion**

In PostgreSQL, some tables are very complex, and queries to access their data can become complicated. PostgreSQL allows the user to create a materialized view containing data for the underlying tables. The materialized view takes specific columns from multiple tables to create a new virtual table and apply queries on their values. This guide has demonstrated the creation of a materialized view in the PostgreSQL database with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-materialized-view-in-postgresql/)

---

# How to Alter an INDEX in PostgreSQL

> The index can be changed in PostgreSQL using an ALTER INDEX statement containing the name of the index and then adding conditions to be applied to change it.

PostgreSQL is used to create databases, store massive data, and then access it from tables using different queries. Queries scan the complete table to fetch data for the query/code run by the user and might be time-consuming as it has to run through massive data. To save time and effort for the query optimizer, PostgreSQL allows the user to create indexes which helps in scanning the data.

This guide will explain how to alter an index in PostgreSQL.

 **How to Alter an INDEX in PostgreSQL?**

Index creation in the PostgreSQL database can be very helpful in accessing data quickly from complex databases. The PostgreSQL DBMS enables the user to change the configurations of the existing indexes by running **ALTER INDEX** statement with different clauses. It can be used to change multiple aspects of the index such as its name, setting tablespace, etc.

 **Syntax**

The following code block contains multiple syntaxes to use the Alter index in PostgreSQL.
    
    
    ALTER INDEX [ IF EXISTS ] index_name RENAME TO modified_name;
     ALTER INDEX [ IF EXISTS ] index_name SET TABLESPACE   modifies_tablespace;
     ALTER INDEX index_name [ NO ] DEPENDS ON EXTENSION   new_extension_name;
     ALTER INDEX [ IF EXISTS ] index_name SET (storage_parameter [= value] [,   ... ] );
     ALTER INDEX [ IF EXISTS ] index_name RESET (storage_parameter [, ... ] );
     ALTER INDEX ALL IN TABLESPACE index_name [OWNED BY role_name [, ... ] ]
      SET TABLESPACE   new_tablespace_name [ NOWAIT ];

Here:

\- **ALTER INDEX** statement is used to change the name of the index by using the **RENAME TO** clause containing the new name of the index in it.  
\- It can be used with the **SET TABLESPACE** clause to alter/attach the tablespace to the index.  
\- A **DEPENDS ON EXTENSION** clause is used to mark the dependency of the index to the extension or a **NO** behind it ends the dependency.  
\- **SET** or **RESET** clauses can be used to attach storage parameters like fill factor to the index which is used for fine-tuning the index.

 **Example 1: Change Index Name**

Execute the following query to create an index in the PostgreSQL database:
    
    
    CREATE INDEX idx_country 
     ON person (country);

Type the name of the index to be created after the **CREATE INDEX** statement, apply it to the selected table using the ON clause, and specify the column_name within the small braces:

Use the given code to change the name of the index:
    
    
    ALTER INDEX idx_country 
    RENAME TO new_country_idx;

Type the name of the index to be altered after the **ALTER INDEX** statement and then use **RENAME TO** clause containing the new name of the index:

 **Example 2: Set Tablespace**

Use the following query to alter the tablespace of the selected index:
    
    
    ALTER INDEX new_country_idx 
     SET TABLESPACE pg_default;

The above command will set the tablespace as “pg_default”:

 **Example 3: Set Storage Parameters**

Use the following query to change the storage parameters of a Postgres index:
    
    
    ALTER INDEX new_country_idx
     SET (fillfactor = 70);

The above query uses **ALTER INDEX** statement along with the **SET** keyword to set the fill factor parameter of the storage to 70:

That’s all about altering an index in PostgreSQL.

 **Conclusion**

ALTER INDEX statement is used to make changes to the existing indexes created on the PostgreSQL database tables. Indexes are created to ease the work of the query optimizer by just scanning the indexes for accessing the data rather than going through the complete table. This guide has explained how to alter the index in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-alter-an-index-in-postgresql/)

---

# What Does the nextval() Function Do in PostgreSQL

> In PostgreSQL, the nextval() function fetches the next value from the sequence to add the incremented value to the existing value of the sequence.

The nextval() is a built-in function in PostgreSQL that allows the use of sequences on the database to automatically set values by incrementing the set of default values. Sequences are the storage type that can be used to manage data efficiently on the databases and also store data on them.

This post will demonstrate the use of the nextval() function in PostgreSQL.

 **What Does the nextval() Function Do in PostgreSQL?**

In PostgreSQL, the purpose of the nextval() function is to generate the next available value from a sequence when it is invoked/called. The sequence is the series of values or a list of integers containing values in ascending or descending order. The sequence is different if the order of numbers is different from each other for instance {1,2,3} and {3,2,1} are two different sequences.

 **Syntax**

Use this syntax/code to create a sequence in PostgreSQL:
    
    
    CREATE SEQUENCE [ IF NOT EXISTS ] seq_name
      [ AS { SMALLINT | BIGINT | INTEGER } ]
      [ INCREMENT [ BY ] increment_value ]
      [ MINVALUE minimum_value | NO MINVALUE ] 
      [ MAXVALUE maximum_value | NO MAXVALUE ]
      [ START [ WITH ] initial_val ] 
      [ CACHE allocated_cache_size ] 
      [ [ NO ] CYCLE ]
      [ OWNED BY { t_name.col_name | NONE } ]

Here:

\- The query starts with **CREATE SEQUENCE** keywords followed by the name of the sequence.  
\- Set the data type contained by the **AS** keyword however, if the user doesn't set any data type the default datatype is ‘ **BIGINT** ’ for sequence.  
\- **The INCREMENT** keyword is used to increase the value by adding it to the current value.  
\- The user can set **MAXVALUE** and **MINVALUE** to mark the end of the sequence but it takes the default value if **NO MINVALUE** or **NO MAXVALUE** is selected.  
\- The **START** keyword specifies where the sequence starts from.  
\- **CACHE** is an optional operator which explains how many preallocated sequence numbers are available in the memory.  
\- If **CYCLE** is specified, the sequence will start again from the **MINVALUE** once the **MAXVALUE** is reached. If not specified, calling **nextval()** after reaching the MAXVALUE will result in an **error**.  
\- **OWNED BY** specifies which table and column should " **own** " the sequence, which means that the sequence will be automatically dropped if the owning table or column is dropped.

 **Example 1: Creating Ascending Sequence to Use nextval() Function**

Use the following query to create the sequence in PostgreSQL:
    
    
    CREATE SEQUENCE firstsequence
     INCREMENT 10
     START 50;

This code suggests:

\- It creates a sequence by providing the name of the sequence.  
\- The starting value will be 50 and for each increment 10 will be added to the current sequence:

Use the following query to check the value of the sequence:
    
    
    SELECT nextval('firstsequence');

Running the above query will display the starting value of the sequence:

Run again the same query to find the next value after incrementing to the previous value which in this sequence is “ **60** ”:

 **Example 2: Creating Descending Sequence to Use nextval() Function**

Use the following query to create a descending sequence that adds “ **-5** ” on every increment to the current value starting from the 5:
    
    
    CREATE SEQUENCE five
     INCREMENT -5
     MINVALUE 1 
       MAXVALUE 10
     START 5
     CYCLE;

The sequence has been created successfully which starts at 5 and ends at 1 and increments -5. The **CYCLE** clause determines that the sequence never stops as it will start from 1 upon reaching 10 every time. So the sequence will contain values like **{5, 10, 5, 10, 5, 10,...}** and the cycle keeps on going:

Use the following query to get the starting value of the sequence:
    
    
    SELECT nextval('five');

The above query will generate value 5 which is the starting value of the sequence:

Running the function again will increment "-5", which ideally should display 0. However, since it exceeds the defined bounds, the function displays 10:

Running the query again will display value 5 after incrementing -5 in the current value which is 10:

 **Example 3: Sequence With Table to Use nextval() Function**

Use the following query to create a new table and then create a sequence on its field:
    
    
    CREATE TABLE customer (
      id integer PRIMARY KEY,
      name varchar(50),
      age integer,
      email varchar(50)
       );

The table named **customer** has been created successfully with multiple columns such as **id** , **name** , **age** , and **email** :

Use the following query to create a sequence named **customer_id_seq** which starts from 1 and everything else is the default:
    
    
    CREATE SEQUENCE customer_id_seq   
    START 1;

The sequence has been created successfully:

Use the following query to attach the sequence to the **id** column of the **customer** table:
    
    
    ALTER TABLE customer 
     ALTER COLUMN id SET DEFAULT nextval('customer_id_seq');

Once the seq is set to the id column, there is no need to insert values in it as it automatically takes value by incrementing on inserting values on the table:
    
    
    INSERT INTO   customer (name, age, email) 
     VALUES ('John Doe', 35, 'johndoe@example.com'), 
      ('Jane Smith', 42, 'janesmith@example.com'), 
      ('Bob Johnson', 28, 'bobjohnson@example.com');

Use the following query to fetch all columns with data from the table customer:
    
    
    SELECT * FROM customer;

The values have been added to the table and it automatically uses the **sequence** to set values in the **id** column:

That’s all about the nextval() function in PostgreSQL.

 **Conclusion**

The nextval() function in PostgreSQL is used to access the next value in the list/sequence by incrementing or adding the value to the existing one. The sequence can be created in ascending or descending order containing the incremental value to be added to the sequence on invoking the nextval() function. This guide has explained the use of the nextval() function in PostgreSQL with multiple examples.

---
[View this page online](https://www.commandprompt.com/education/what-does-the-nextval-function-do-in-postgresql/)

---

# How to Drop an INDEX in PostgreSQL

> In PostgreSQL, indexes can be dropped using the DROP INDEX command followed by the index name or names for dropping multiple indexes using a single query.

In PostgreSQL databases, indexes are vital to locate and fetch required data from a huge amount of data efficiently. The query has to scan the complete table to find a single value if there were no indexes created on the table. Indexes enable the query optimizer to directly fetch data using the index of the table or column.

This guide will explain how to drop an index in PostgreSQL.

 **How to Drop an INDEX in PostgreSQL?**

Indexes are immensely important for fetching data quickly from tables created on the database but in some cases, they lose their significance. Query optimizer finds it easy to locate data by scanning the complete table rather than looking for the index and using it. In that case, PostgreSQL allows the user to drop that index which simply doesn't serve any purpose.

 **Syntax**

The following is the syntax for dropping an index in the PostgreSQL database:
    
    
    DROP INDEX [CONCURRENTLY]
       [ IF EXISTS ] index_name 
       [ CASCADE | RESTRICT ];

Here:

\- The **DROP INDEX** clause is used to drop an index from the PostgreSQL table.  
\- The use of the **CONCURRENTLY** option blocks access to the table while dropping the index.  
\- After that, type the name of the index with the **IF EXISTS** clause which checks the existence of the index in the table.  
\- The **CASCADE** clause is used to drop the dependent objects of the index and the RESTRICT clause refuses to drop the index in case any dependent object is found.

 **Syntax to Drop Multiple Indexes**

To drop multiple indexes in the PostgreSQL database simply separate indexes with commas as depicted in the following syntax:
    
    
    DROP INDEX   index_name, index_name2,... ;

 **Example 1: DROP INDEX From the Table**

Let’s first create an index on the country column of the table person using the following query:
    
    
    CREATE INDEX idx_person_country 
     ON person(country);

Use the following query to fetch a record from the indexed column:
    
    
    SELECT * FROM person
     WHERE country = 'UK';

Running the above code will display the record from the person table containing the desired data:

Use the following query to check if the query used the index or not for fetching the table’s data:
    
    
    EXPLAIN SELECT * FROM person
     WHERE country = 'UK';

The query optimizer has scanned the complete table which means that the index we created earlier has no purpose here:

Use the following code to drop the index created earlier as it is not being used by the query optimizer:
    
    
    DROP INDEX   idx_person_country;

Running the above query has dropped the index successfully:

That’s all about dropping an INDEX in the PostgreSQL table.

 **Conclusion**

In PostgreSQL, indexes are used to optimize the performance of the database as it is used by the query to fetch data quickly. Without them, the query simply has to scan the complete table to fetch a single row which can be a lot more time-consuming. Sometimes the query scans the complete table in the presence of the index as it deems it more effective. In these cases, it is better to drop indexes rather than keeping them in the database as this guide has explained with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-an-index-in-postgresql/)

---

# How to Setup ODBC Drivers for PostgreSQL

> To set up ODBC drivers for PostgreSQL, download the executable file and install it on the system. After that, configure the driver by adding a data source to i…

PostgreSQL is an open-source platform supporting all features of RDBMS for almost 30 years since its release in the year 1996. ODBC leverages Open Database Connectivity Interface for PostgreSQL. It is the official driver for PostgreSQL. It supports connectivity with the PostgreSQL using its data source by configuring it on the local system after its installation.

This guide will explain how to set up/configure ODBC drivers for PostgreSQL.

 **How to Setup ODBC Drivers for PostgreSQL**

To set up the ODBC drivers for the PostgreSQL database, check the client PostgreSQL details like the database name, server, user, and password:

 **Step 1: Download the ODBC Driver File**

To download the driver MSI, simply click [here](<https://www.devart.com/odbc/postgresql/download.html>) and click on the “ **Download** ” button to get the executable file on the local system:

Execute the file and click on the “ **Next >**” button to start the installation process:

Read the license agreement before choosing the accept option and then click on the “ **Next >**” button:

Set the path to install the driver and head to the Next step:

Select the components to install and click on the “ **Next** ” button:

Set the startup folder for ODBC Drivers:

Once the pre-installation requirements are complete, simply click on the “ **Install** ” button:

Click on the “ **Finish** ” button after the installation is done:

Once the installation process is done, move on to the configuration phase.

 **Step 2: Configure/Set up OBDC Drivers**

Search the ODBC file from the local system and click on the “ **Run as administrator** ” button:

Head into the “ **System DNS** ” tab to click on the “ **Add…** ” button from the right panel:

Select the “ **Devart ODBC Driver for PostgreSQL** ” data source and click on the “ **Finish** ” button:

Configure the Driver by providing the credentials for the source and clicking on the “ **Test Connection** ” button:

The “ **Connection successful** ” message indicates that the configuration is done correctly:

The data source has been added successfully:

That’s all about configuring ODBC drivers for PostgreSQL.

 **Conclusion**

To set up ODBC drivers for PostgreSQL, download the executable file on the local system from the official website. Execute the file to start the installation of the ODBC drivers on the system by selecting the pre-installation steps and clicking on the “ **Install** ” button. Once the drivers are installed on the system, simply configure the data source and test the connection to add the data source. This guide has demonstrated the process of configuring ODBC drivers for PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-setup-odbc-drivers-for-postgresql/)

---

# How Does ROLLUP Work in PostgreSQL

> The ROLLUP is the sub-clause of the GROUP BY in PostgreSQL which assumes the hierarchy among the columns to reduce the number of subsets in the report.

Databases are used to present raw data in a structured form of data and store it for later use. Getting information from the structured form of the data is easy compared to the raw form and the user can also generate reports from that. The ROLLUP clause is used inside the GROUP BY clause to get multidimensional reports on the PostgreSQL database.

This guide will explain the working of ROLLUP in PostgreSQL.

 **How Does ROLLUP Work in PostgreSQL?**

ROLLUP is the sub-clause of the GROUP BY clause and it assumes that there is a hierarchy in the columns available in the table. It is mainly used to generate subtotals of the columns for reporting purposes. It does not display all the subsets for the columns as it assumes the hierarchy among the columns. It will display only four grouping sets as mentioned below for the ROLLUP(column_1, column_2, and column_3) query:
    
    
    (column_1, column_2, column_3)
       (column_1, column_2)
       (column_1)
       ()

 **Syntax**

The following is the syntax for using the ROLLUP clause in the PostgreSQL database:
    
    
    SELECT
      column_1,
      column_2,
      column_3,
      aggregate(column_4)
     FROM
      table_name
       GROUP BY
      ROLLUP (column_1, column_2, column_3);

Here in the above query:

\- The **SELECT** statement will select the list of columns with the column on which the aggregate function will be applied.  
\- The **table_name** for the selected columns will be mentioned in the **FROM** keyword.  
\- **GROUP BY** clause will contain its sub-clause which is **ROLLUP** to select columns for generating grouping subsets.

It is also allowed to use partial ROLLUP in the PostgreSQL database:
    
    
    SELECT
      column_1,
      column_2,
      column_3,
      aggregate(column_4)
     FROM
      table_name
       GROUP BY
      column_1, 
      ROLLUP (column_2, column_3);

The partial ROLLUP query will take one column which will be used inside the GROUP BY clause to apply ROLLUP on the other columns to reduce the number of subsets.

 **Example 1: ROLLUP in PostgreSQL**

Use the following query to get the data from the sales table with the ORDER BY clause to sort the result according to the columns:
    
    
    SELECT * FROM sales
     ORDER BY continent, country, city;

Running the above query will display the data from the table sorted according to the columns from start to end:

The following query uses the ROLLUP clause on the sales table to generate multiple groups for its columns:
    
    
    SELECT continent, country, city, sum(units_sold)
     FROM sales
       GROUP BY ROLLUP (continent, country, city);

The above code explains that the data will be selected from the sales table containing columns continent, country, and city. The last column will be placed inside the aggregate function to perform sum() on it according to previously given columns. ROLLUP clause will simply generate grouping sets according to the columns mentioned inside it.

 **Output**

Running the above query generates all the subsets containing the sum for the complete data and also the sum of each continent individually. It also generates the sum of units_sold for each country and city from the sales table:

 **Example 2: Partial ROLLUP in PostgreSQL**

The following query uses a partial ROLLUP subclause to reduce the number of subsets:
    
    
    SELECT continent, country, city, sum(units_sold)
     FROM sales
       GROUP BY continent,
       ROLLUP (country, city);

The change from the previous example is that it takes the continent column from the ROLLUP clause and places it under the GROUP BY clause. It will reduce the column displaying the sum of all units_sold in the sales table.

 **Output**

The following screenshot displays the tables with multiple grouping sets of the sales table:

That’s all about the working of ROLLUP in PostgreSQL.

 **Conclusion**

ROLLUP is the sub-clause of the GROUP BY clause used in the structured query language to generate multiple grouping sets of the table. It assumes the hierarchy among the columns in the table to reduce the number of subsets for the columns in the table. PostgreSQL allows the use of ROLLUP and partial ROLLUP in the query to generate reports accordingly. This guide has explained the working of the ROLLUP clause in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-does-rollup-work-in-postgresql/)

---

# How to Use CROSS JOIN in PostgreSQL

> CROSS JOIN is used in the PostgreSQL database to return the cartesian product of the two tables on which the CROSS JOIN is applied.

Databases are an important aspect in the computing domain to manage raw data by storing it in the form of tables. Once the data is sorted and placed properly, gathering information and generating better decisions becomes useful and efficient. PostgreSQL databases allow the use of JOINs to join multiple tables and generate results accessed from multiple places.

This guide will demonstrate how to use CROSS JOIN in PostgreSQL.

 **How to Use CROSS JOIN in PostgreSQL?**

CROSS JOIN in PostgreSQL returns a paired combination of every row available on the first table and every row on the second. If Table A contains three rows and the second table contains the same number of rows. Applying CROSS JOIN will create a match of the first row with respect to the second to generate three matches in this situation and so on for other rows of the first table:

 **Syntax With CROSS JOIN**

The following syntax simply takes a list of columns from the first table and uses the CROSS JOIN condition on the second table:
    
    
    SELECT <Col_list>
     FROM <Tab_A>
     CROSS JOIN <Tab_B>;

 **Syntax Without CROSS JOIN**

The following syntax also generates the same results as the above query but without the use of the CROSS JOIN keyword:
    
    
    SELECT <Col_list>
     FROM <Tab_A>,   <Tab_B>;

 **Syntax Using INNER JOIN as CROSS JOIN**

INNER JOIN can also be used to get the results of the CROSS JOIN by using the following syntax. It takes columns of the first table and applies INNER JOIN with ON condition on the second table. It generates CROSS JOIN results when the condition is true for the second table:
    
    
    SELECT *
     FROM Tab_A
     INNER JOIN Tab_B ON true;

 **Example 1: Combine Tables With CROSS JOIN**

Start the example by using the following command to get the data from the colors table:
    
    
    SELECT * FROM colors;

Running the above code will return the data from the colors table:

Use the same query with the sizes table as written below:
    
    
    SELECT * FROM sizes;

The following screenshot displays the data from the sizes table:

Use the following CROSS JOIN query to join both tables:
    
    
    SELECT * FROM colors
     CROSS JOIN sizes;

Running the above query will match each record from the first table with the second table and generate the following result. It matches records of colors with sizes as it takes red and matches with all the sizes available on the table and so on for blue and green:

 **Example 2: Without Using CROSS JOIN**

The following query does not use the CROSS JOIN keyword in the query but still produces the same result:
    
    
    SELECT * 
     FROM colors, sizes;

It simply takes all the records from both tables and matches for their records which basically is the working of CROSS JOIN:

 **Example 3: Apply CROSS JOIN With INNER JOIN**

Another method to apply CROSS JOIN in PostgreSQL is using the INNER JOIN as mentioned in the following query:
    
    
    SELECT *
     FROM colors
     INNER JOIN sizes ON true;

This code contains the following:

\- It selects all the records from the colors table and applies INNER JOIN with the sizes table.  
\- The ON condition checks for each true record and joins both tables as a CROSS JOIN:

That’s all about using CROSS JOIN in PostgreSQL.

 **Conclusion**

The CROSS JOIN in PostgreSQL databases generates a cartesian product of two tables and joins them to produce one table. PostgreSQL allows the user to apply CROSS JOIN with multiple syntaxes such as using the CROSS JOIN keyword, without using CROSS JOIN, and using INNER JOIN with the condition. It matches each record of the first table with each record of the second table and creates another as this guide demonstrated in detail.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-cross-join-in-postgresql/)

---

# How to Calculate Percentiles in PostgreSQL

> PERCENT_CONT and PERCENT_DISC are analytic functions that are used to calculate the percentile/median in the PostgreSQL database.

Analytic functions in databases operate on top of rows to return a group of rows that can be further analyzed. The **PERCENT_CONT** is an analytic or Windows function that is used for continuous distribution in the PostgreSQL database. **PERCENT_DISK** is also an analytic function that is used to sort the percentile of the specific values for discrete distribution.

This guide will explain how to calculate percentiles in PostgreSQL.

 **How to Calculate Percentile/Median in PostgreSQL?**

The **PERCENT_CONT** function is used to calculate the percentile based on the continuous distribution of the column value in a table. The value after applying the percentile function can not be equal to any specific values from the table. The **PERCENTILE_DISC** function returns the percentile of the current row concerning the current partition.

 **Syntax**

The syntax to use the PERCENTILE_CONT in the PostgreSQL table is mentioned below:
    
    
    SELECT
     PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY column_name),
     PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY column_name),
     PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY column_name),
     PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY column_name)
     FROM table_name;

Here:

\- The query selects from the table to apply multiple percentile functions using the **ORDER BY** clause on the column.  
\- The **WITHIN GROUP** function is used for aggregation to combine multiple rows in the group of rows.  
\- The user can either apply a single **PERCENTILE_CONT** function with any of the percentile numbers or multiple functions as mentioned above.

The following is the syntax for using the **PERCENTILE_DISK** function in PostgreSQL:
    
    
    SELECT
     PERCENTILE_DISC(0.50) WITHIN GROUP (ORDER BY column_name)
     FROM table_name;

The above query is almost similar to the PERCENTILE_CONT with a simple keyword difference which in this query is PERCENTILE_DISK with percentile value as its parameter.

 **Example 1: PERCENTILE_CONT in PostgreSQL**

Use the following query to get the data from the **sales** tables using the ORDER BY clause on the sale column:
    
    
    SELECT * FROM sales
     ORDER BY sale;

The data is displayed in ascending order by **sale** column:

Use the following code to get the 25th percentile of the sale column:
    
    
    SELECT PERCENTILE_CONT(0.25) 
     WITHIN GROUP(ORDER BY sale) 
     FROM sales;

The above query will get the **25th** percentile of the **sale** column data from the **sales** table which aggregates the sale column to display only a single percentile value:

The following query simply uses multiple PERCENTILE_CONT functions in a single query to get percentiles of the sale column:
    
    
    SELECT 
     PERCENTILE_CONT(0.25) WITHIN GROUP(ORDER BY sale),
     PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY sale),
     PERCENTILE_CONT(0.75) WITHIN GROUP(ORDER BY sale)
     FROM sales;

The following screenshot displays 3 percentiles which are the **25th** , **50th** , and **75th** percentiles:

 **Example 2: PERCENTILE_DISC in PostgreSQL**

The following example displays the use of the PERCENTILE_DISK function in PostgreSQL on the sales table:
    
    
    SELECT * FROM sales
     ORDER BY sale;

The above query displays the data from the sales table which is ordered by the sale column:

The following query displays the 50th percentile of the sales row set:
    
    
    SELECT PERCENTILE_DISC(0.5) 
     WITHIN GROUP(ORDER BY sale) 
     FROM sales;

The following screenshot displays the 50th discrete percentile from the sale column:

That’s all about calculating percentiles in PostgreSQL.

 **Conclusion**

To calculate the median/percentiles in PostgreSQL, PERCENT_CONT, and PERCENT_DISC functions can be used. Both of these functions are analytic or Windows functions to evaluate continuous and discrete distributions of the data respectively. The user can also apply multiple CONT and DISC functions in a PostgreSQL query to find the median of the data. This guide demonstrated the process of calculating percentiles in the PostgreSQL database using multiple examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-calculate-percentiles-in-postgresql/)

---

# How to Use CONTINUE Statement in a Loop in PostgreSQL

> PostgreSQL supports a “continue” statement that lets us skip the loop’s current iteration and proceed to the subsequent iteration.

PostgreSQL supports a “continue” statement that lets us skip the loop’s current iteration and proceed to the subsequent iteration. This statement can be used with all types of loops, such as for, while, and unconditional loops. A continue statement can save time by skipping unnecessary data/iterations.

This guide will explain how to continue a loop in PostgreSQL.

##  **How to Use CONTINUE Statement in a Loop in PostgreSQL**

Loops are used to perform similar tasks again and again until the conditions remain true and it will immediately stop when it becomes false. The “continue” statement can be embedded with the loop statement to skip the iteration satisfying the condition and jump to the next one.

The given code/syntax demonstrates how to use the continue statement inside the loop in PostgreSQL:
    
    
    continue [label] [when condition]

 **Syntax Explanation** :

  * The continue keyword starts the statement, followed by the label of the loop in which the continue statement is being used.
  * After mentioning the label, type the condition statement/block for which the loop will continue/skip the iteration.



###  **Example 1: Iterate Using Continue Statement**

The following code uses a continue statement in the loop to print even numbers between 0-15:
    
    
    DO
    $$
    DECLARE
       num INTEGER = 0;
    BEGIN
      RAISE NOTICE 'Even Numbers Between 0-15 are ==>';
      LOOP
         num = num + 1;
     EXIT WHEN num > 15;
     CONTINUE WHEN mod(num,2) != 0;
     RAISE NOTICE '%', num;
      END LOOP;
    END;
    $$

 **Code Explanation**

  * First, we declare a variable “num” of type “INTEGER” and assign it with a value “0” (loop start point).
  * Next, we use the “RAISE NOTICE” statement to print a message “Even Numbers Between 0-15 are ==>”.
  * After this, we start a loop that increments the variable’s value by 1 in each iteration. Also, we use the “EXIT” keyword to exit/terminate a loop when the variable’s value exceeds 15.
  * Next, we use the “CONTINUE” statement that skips the value when it is completely divided by the number 2 (this way, the odd numbers will be skipped).
  * Finally, we use the “RAISE NOTICE” statement to print the even values between 0 and 15:



###  **Example 2: Use Continue on PostgreSQL Table**

Let’s learn how to use a continue statement inside the loop to iterate over a PostgreSQL table; but first, use the following query to get the data from the “ **bike_details** ” table:
    
    
    SELECT * FROM bike_details;

Use the following query to use a continue statement in a loop working on the PostgreSQL table:
    
    
    DO $$
    DECLARE
      price_details RECORD;
    BEGIN
      FOR price_details IN SELECT * FROM bike_details LOOP
       IF price_details.bike_price < 110000 THEN
       CONTINUE;
      END IF;
         RAISE NOTICE 'Bike Number: % Bike Price %', 
         price_details.bike_number, price_details.bike_price;
      END LOOP;
    END $$;

 **Code Explanation**

  * First, we declare a variable named “price_details” of type “RECORD”.
  * Next, we use a for loop to iterate over each row retrieved by the SELECT query. It selects all columns from a table named "bike_details" and assigns each row to the "price_details" variable.
  * After this, we use the If statement to filter bike_details based on bike_price. It is such that, if the bike_price is less than 110000, the loop continues to the next iteration.
  * Finally, we use the “RAISE NOTICE” statement to print the bike_number and bike_price:



That’s all about using a “CONTINUE” statement in PostgreSQL.

##  **Conclusion**

In PostgreSQL, loops are used in the queries to perform single code/statements for multiple rows in the table. The continue statement can be integrated with the loop to skip the values that satisfy the condition mentioned in the block of the statement This guide has explained the use of a continue statement in PostgreSQL with the help of multiple examples.

---
[View this page online](https://www.commandprompt.com/education/continue-statement-postgresql/)

---

# PL/pgSQL Exit Statement: How to Terminate a Loop

> Terminating the loop before its actual ending point or condition can be done using the “Exit” statement in the PostgreSQL query.

Loops in PostgreSQL databases are used to repeat the same query multiple times to fetch data from the PostgreSQL table. Loops should contain the starting and ending range to limit the iterations so they can fetch data from tables to stop it from going indefinitely. But in some conditions, the user wants to stop the loop before the ending condition which can be done with the help of the “ **Exit** ” statement.

This post demonstrates the process to use the exit statement to terminate a loop in PostgreSQL.

 **PL/pgSQL Exit Statement: How to Terminate a Loop**

The EXIT statement can be used to terminate the body of the loop before the actual ending of the loop by providing some conditions to this statement. The exit statement generally uses boolean expressions as the condition statement but it is optional as the use of loop label with it. Additionally, it provides control to the looping structures and conditional statements by providing them with the exact point of exit.

 **Syntax**

This is the syntax for the exit statement used in PostgreSQL:
    
    
    exit [label] [when boolean_expression];

The above code contains the **exit** keyword and label of the loop with the condition on which the loop will be terminated.

The following code block contains the exit keyword with the when clause containing the variable name and the condition. It suggests that the loop will terminate as soon as the value of the counter variable reaches 10:
    
    
    exit when counter > 10;

The following code can be used to terminate the block which is contained inside the **begin..end** keyword:
    
    
    if counter > 10 then
      exit;
       end if;

 **Example 1: Using Exit Statement to Terminate a Loop**

Use the following code which terminates the loop before the end of its actual conditions:
    
    
    DO $$
     DECLARE
      a INTEGER := 1;
     BEGIN
      WHILE a <= 10 LOOP
      RAISE NOTICE 'Variable value: %', a;
      IF a = 5 THEN
      EXIT;
      END IF;
      a := a + 1;
      END LOOP;
     END $$;

Here:

\- Code starts with the loop variable named “ **a** ” having value **1** stored in it and begins the loop with a condition to be set at **10**.  
\- It starts executing the iterations but the exit statement suggests that the loop should be terminated at **5**.  
\- The loop was supposed to end when the variable value exceeds 10 but the exit statement forced to terminate the loop when the value reached 5 and printed on the screen:

 **Example 2: Using Exit Statement to Terminate a Nested Loop**

The following query will terminate a loop while there are nested loops in progress and print values on the screen:
    
    
    DO $$
     DECLARE
      outer_counter INTEGER;
      inner_counter INTEGER;
     BEGIN
      FOR outer_counter IN 1..3 LOOP
      RAISE NOTICE 'Outer Counter: %', outer_counter;
      
      FOR inner_counter IN 1..4 LOOP
      RAISE NOTICE 'Inner Counter: %', inner_counter;
      
      IF inner_counter = 3 THEN
      EXIT;
      END IF;
      END LOOP;
      
      IF outer_counter = 2 THEN
      EXIT;
      END IF;
      END LOOP;
     END $$;

Here in the above code:

\- Two variables have been declared named **outer_counter** and **inner_counter** for outer and inner loops respectively.  
\- The outer loop is supposed to run from **1 to 3** and the inner loop is to execute inside the outer loop from **1 to 4**.  
\- The exit statement suggests that the outer loop runs twice and inside it, the inner loop will run from 1 to 3.  
\- So, each time the outer loop runs the inner loop will execute three times and the output will be printed on the screen:

 **Example 3: Using Exit Statement to Terminate a Loop in PostgreSQL Table**

Use the following query to get data from the orders table and then use the exit statement in the table:
    
    
    SELECT * FROM orders;

Running the above code will display all the data from the **orders** table:

The following code will be used to apply the **EXIT** statement on the PostgreSQL table:
    
    
    DO $$
     DECLARE
      cust_id integer;
      total_revenue numeric;
     BEGIN
      FOR cust_id IN SELECT DISTINCT customer_id FROM orders LOOP
      SELECT SUM(order_total)   INTO total_revenue FROM orders WHERE customer_id =   cust_id;
      RAISE   NOTICE 'Customer   % total revenue: %', cust_id, total_revenue;
      
       -- Check for the exit condition
      IF cust_id = 2 THEN
      EXIT;
      END IF;
      END LOOP;
     END $$;

Let’s comprehend the above code stepwise:

\- It creates two variables named **cust_id** and **total_revenue** for storing values of **customer_id** and **order_total** respectively.  
\- It will calculate the **order_total** from each customer and store its sum in the **total_revenue** variable.  
\- The loop is supposed to get each customer's revenue but the exit statement stops it when the **cust_id** variable has the value **2**.  
\- It will print the data for only two customers and will leave the revenue for the third customer:

That’s all about using the exit statement to terminate a loop.

 **Conclusion**

In PostgreSQL, the loops are used to run a single query multiple times with the given range that refers to their starting and ending point. The loop is given an ending point called condition and only runs the statements until it reaches that point. However, sometimes the user needs to stop the loop before the endpoint, here comes the exit statement to terminate the loop. This guide has explained the use of exit statements in PostgreSQL with multiple examples.

---
[View this page online](https://www.commandprompt.com/education/plpgsql-exit-statement-how-to-terminate-a-loop/)

---

# How to Use While Loop in PostgreSQL

> While loop is used in PostgreSQL to apply multiple iterations on the query by checking the condition for each iteration before executing the body of the loop.

PostgreSQL is used to store data by creating databases in the form of tables and then connecting them using relationships between them. In PostgreSQL, loops are used to iterate over a set of rows/records or run statements repeatedly until the said condition becomes false. Postgres supports various types of loops, one such loop is the “While” loop.

This guide will explain how to use the While loop in PostgreSQL.

 **How to Use While Loop in PostgreSQL?**

While loop runs the query until the condition remains true and it stops execution as soon as the condition is false. The condition will be evaluated during each iteration, and the code specified within the loop's body will be executed as long as the condition remains true.

 **Syntax**

The following is the syntax for the while loop in PostgreSQL:
    
    
    [ <<label>> ]
     while condition loop
      statements;
     end loop;

Here:

\- The loop is executed after checking the condition after each iteration and runs until the condition remains true.  
\- There should be a false condition in the While loop to terminate the loop, otherwise, the loop will run indefinitely without stopping it.  
\- After pretesting the condition, the loop runs the statements inside the loop body and again checks the condition for a new value.

 **Example 1: Iterating Using While Loop**

The following code is the basic example of While loop execution which will print the first 10 integers on the screen:
    
    
    do $$
     declare 
      counter integer := 1;
     begin
      while counter <= 10 loop
      raise notice 'Counter %', counter;
       counter := counter + 1;
      end loop;
     end$$;

The above code will declare a variable and assign it the starting value to start the iterations of the loop. After that, provide the condition which will be checked before running the statements inside the loop body. It will increment the value by adding 1 to the previous value of the variable:

 **Example 2: Reverse Iteration Using While Loop**

The following is the code that will print the first ten numbers in the reverse order starting from 10:
    
    
    do $$
     declare 
      counter integer := 10;
     begin
      while counter >= 1 loop
      raise notice 'Counter %', counter;
       counter := counter - 1;
      end loop;
     end$$;

The above code will simply change the starting point and the condition value to reverse the order of the printing values. It will subtract 1 from the existing value as it starts from 10 and it will keep executing by subtracting 1 in each iteration until it becomes less than 1:

 **Example 3: Customizing Steps Using While Loop**

Use the following code to print the multiples of two starting from 1 using the while loop in PostgreSQL:
    
    
    do $$
     declare 
      counter integer := 1;
     begin
      while counter <= 10 loop
      raise notice 'Counter %', counter;
       counter := counter *2;
      end loop;
     end$$;

The above code creates a variable for the while loop containing value 1 and it will multiply the value with two until it becomes greater than 10. It starts with 1, multiplies it with 2, and so on until the loop terminates:

 **Example 4: While Loop in PostgreSQL Table**

Run the following code to get data from the orders table:
    
    
    SELECT * FROM orders;

Use the following query to get the total revenue from each customer:
    
    
    DO $$
       DECLARE
      cust_id integer;
      total_revenue numeric;
     BEGIN
      cust_id := 1;
      WHILE cust_id <= (SELECT MAX(customer_id) FROM orders) LOOP
      SELECT SUM(order_total) INTO total_revenue FROM orders WHERE customer_id = cust_id;
      RAISE NOTICE 'Customer %   total revenue: %', cust_id, total_revenue;
      cust_id := cust_id + 1;
      END LOOP;
     END $$;

The above query contains:

\- It creates two variables named “cust_id” and “total_revenue” to be used in the while loop.  
\- Starting value for the “cust_id” is given so the loop can check the condition using it.  
\- The “cust_id” variable will contain the value of the current “customer_id” on which the loop is being applied.  
\- The “total_revenue” variable will be used to store the sum of the values from the order-total column of each customer.  
\- It will print the total revenue on the screen for each customer individually by adding it using iterations of the loop:

That’s all about using a While loop in PostgreSQL.

 **Conclusion**

In PostgreSQL, a While loop is used to perform multiple iterations on the same query by checking the condition before each iteration. The while loop is also called a pre-tested loop because it checks the condition before executing the query for each iteration. This guide has explained the While loop in PostgreSQL using multiple examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-while-loop-in-postgresql/)

---

# How to Use For Loop in PostgreSQL

> The for loop in Postgres is used to iterate/traverse over a specific range or a result set. You can use and customize it according to your requirements.

A database in Postgres can store a gigantic amount of data. Therefore, traversing through the PostgreSQL database to fetch the desired data may take some time. This becomes more hectic when a user has to execute a specific query again and again to achieve a specific purpose. To avoid these complexities, PostgreSQL offers loops that can iterate through the entire table, a range of integers, etc.

Among these loops, the most convenient and frequently used is the **“for” loop** which will be discussed in this article along with suitable examples.

##  **How to Use For Loop in PostgreSQL**

 **In PostgreSQL, the FOR loop is used for iterating over a range of values or a result set**. The below figure shows the working flow of the FOR loop in PostgreSQL:

###  **Syntax**

It works similarly to traditional programming language “for” loops; however, its syntax is a little bit different, as shown below:
    
    
    [loop]
      FOR <varName> in [reverse] from.. to [BY step] LOOP
      body
      END LOOP [loop];

Here:

  * for is a keyword/statement that executes according to the specified loop definition.
  * The “varName” represents any valid integer variable. This variable will be accessible within the loop(only).
  * After each iteration, the loop increments the **step** by a factor of “1”.
  * “reverse” is optional, if enabled, the loop decrements the step by 1 after each iteration.
  * “from..” represents the lower bound/range while “to” indicates the upper bound/range.
  * The for loop will iterate/traverse according to the specified “from..” and “to” expressions.



The loop will keep working/iterating until the condition is satisfied and will immediately stop when the condition becomes false.

###  **Example 1: Iterating Using For Loop**

Let’s use a for loop to iterate and display a statement five times:
    
    
    DO $$
      BEGIN
      FOR count IN 1..5 LOOP
      RAISE NOTICE 'Welcome to Commandprompt';
      END LOOP;
     END; 
    $$

In this code, we use the for loop to iterate over a range “1-5”. Within the loop, we use the “raise notice” statement to display a message of our choice each time the loop iterates. Here is the resultant outcome:

###  **Example 2: Iterating an Array Using For Loop**

The below code block shows how to iterate over an array using a for loop:
    
    
    DO $$
      DECLARE arr TEXT[] = '{"welcome", "to", "commandprompt", ".com"}';
      BEGIN
      FOR count IN 1..4 LOOP
      RAISE NOTICE '==> %', arr[count] ;
      END LOOP;
     END; 
    $$

In this code, we create a TEXT array that contains four elements. After this, we iterate over the given array via a for loop and display all array elements using a “RAISE NOTICE” statement:

###  **Example 3: Iterating For Loop in Reverse Order**

Specifying the “REVERSE” keyword in for loop’s definition allows us to iterate in reverse order:
    
    
    DO $$
      DECLARE arr TEXT[] = '{"welcome", "to", "commandprompt", ".com"}';
      BEGIN
      FOR count IN REVERSE 4..1 LOOP
      RAISE NOTICE '==> %', arr[count];
      END LOOP;
     END; 
    $$

In this code, we use the for loop to iterate over the given array in reverse order. The loop starts iterating from the 4th index and keeps going until it reaches the first element:

###  **Example 4: Iterating For Loop With Customized Steps**

Postgres allows us to customize the steps in the for loop according to our needs. For this purpose, simply specify the “step” using the “BY” keyword, as demonstrated below:
    
    
    DO $$
      BEGIN
      FOR count IN 0..20 BY 5 LOOP
      RAISE NOTICE 'count %', count;
      END LOOP;
     END; 
    $$

In this code, we specify the step size as “5”, which means in each iteration, the loop increments by a factor of “5”:

###  **Example 5: Iterating For Loop Over a Result Set**

Postgres also allows us to iterate a for loop over a result set. This practice allows us to iterate and fetch the desired records from a result set according to our needs. For instance, the below snippet shows the data of a “product_info” table:

Now in the following code snippet, first, we declare a RECORD-type variable named “availability”:
    
    
    DO
       $$
     DECLARE availability RECORD;
     BEGIN
     FOR availability IN SELECT pro_name, is_available 
     FROM product_info 
     LIMIT 5
     LOOP 
     RAISE NOTICE '% %', availability.pro_name, availability.is_available;
      END LOOP;
     END;
       $$

We use the for loop to fetch the availability status of the top five products. We utilize the “RAISE NOTICE” statement to show the name and availability of the fetched products:

###  **Example 6: Iterating a Nested For Loop**

Let’s learn how to use the nested for loop in Postgres using the following code example:
    
    
    DO $$
     DECLARE
      emp TEXT[][] := '{{"Joseph",   "John", "Alex"}, {"Mike", "Henry",   "Matt"}, {"Roman", "Ambrose",   "Dean"}}';
     BEGIN
      FOR i IN 1..3 LOOP
      FOR j IN 1..3 LOOP
      RAISE NOTICE 'Emp At [%,%]: %', i, j,   emp[i][j];
      END LOOP;
      END LOOP;
     END 
    $$;

In this code, we are given a 2-D array of type text. We execute the for-loop in a nested structure to iterate and print each element of the given multi-dimensional array:

That’s all about using a for loop in PostgreSQL.

##  **Final Thoughts**

The for loop in Postgres is used to iterate/traverse over a specific range or a result set. You can use and customize it according to your requirements. For instance, you can iterate a loop in reverse order, set/change the step size, loop through only specific records of a result set, etc. Also, you can use the for loop in a nested structure to iterate over multidimensional or complicated data structures. This post has discussed all of the mentioned use cases with appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-for-loop-in-postgresql/)

---

# How to Use PERCENT_RANK in PostgreSQL

> In PostgreSQL, the PERCENT_RANK function can be used with PARTITION BY and ORDER BY clauses using ascending and descending order to get a rank for each row.

Fetching useful insights from the data available on the database created for the company is the sole purpose of data collection. Getting the list of all the employees from the database with their rankings according to their performances can be useful for decision-makers. Furthermore, ranking employees from all the departments of the company with their records can be helpful in making decisions about their future. For this purpose, the PERCENT_RANK function can be used in Postgres.

This guide will explain the use of PERCENT_RANK in PostgreSQL.

 **How to Use PERCENT_RANK in PostgreSQL?**

The PERCENT_RANK is an analytic function which is kind of a cumulative distributive function in the PostgreSQL database. It is used to calculate the rank of each row available on the table by evaluating the relative standing of their value. Each row gets a specific rank which is always greater than 0 and less than 1 according to the number of rows.

 **Syntax**

Use the following code as the syntax to use the **PERCENT_RANK** function in the PostgreSQL database:
    
    
    PERCENT_RANK()   OVER (
      [PARTITION BY partition_exp, ... ]
      ORDER BY   sort_exp [DESC | ASC], ...
       );

The above code snippet:

\- The **PERCENT_RANK** function is declared with No parameters assigned to it in its small parentheses.  
\- After that, use the **OVER** clause that contains two parameters such as **PARTITION BY** and **ORDER BY** clauses.  
\- **PARTITION BY** clause is an optional clause to create table partitions.  
\- The **ORDER BY** clause is a mandatory clause as it implements the formula for the **PERCENT_RANK** function in the query.

The following line explains that the value of the PERCENT_RANK function is always less than 0 and greater than 1. However, the first row of the table contains 0, and the last row has the value 0 in the percent_rank column:
    
    
    0 < VALUE <= 1

 **Example 1: PERCENT_RANK in PostgreSQL**

Use the following SELECT command to get data from the orders table:
    
    
    SELECT * FROM orders;

Running the above code will display the data from the orders table:

Execute the following code to use PERCENT_RANK in the PostgreSQL tables:
    
    
    SELECT
      id,
      customer_id,
      product_name,
      price,
     percent_rank() OVER (ORDER BY price DESC) AS percent_rank
     FROM orders;

The above code selects the list of columns from the orders table and applies the **PERCENT_RANK** function. The **PERCENT_RANK** function uses an **OVER** clause on the **price** column and displays its rank in descending order:

 **Example 2: PERCENT_RANK With PARTITION BY Clause**

Use the given command to fetch the “ **students** ” table records:
    
    
    SELECT * FROM students;

Executing the above code will display the data from the “ **students** ” table:

Use the following query to apply the **PERCENT_RANK** function with **PARTITION BY** clause in PostgreSQL:
    
    
    SELECT
      student_id,
      student_name,
      class_name,
      score,
      percent_rank() OVER (PARTITION BY   class_name ORDER BY score ASC) AS percent_rank
     FROM
      students;

The above code selects **columns** from the “ **students** ” table to apply the **PERCENT_RANK** function using **PARTITION BY** and **ORDER BY** clauses. PARTITION BY clause is used to create a partition using **class_name** and **ORDER BY** clause is applied to the **score** column. As the above table is partitioned by class and each class has only two rows so the rank has been assigned **0** and **1** for each row:

That’s all about using PERCENT_RANK in PostgreSQL.

 **Conclusion**

To use the PERCENT_RANK function in the PostgreSQL database, simply start the query with the PERCENT_RANK keyword with Null parameters. It has an OVER clause containing PARTITION BY and ORDER BY clauses inside it to apply rank on the table. ORDER BY clause is a mandatory clause but the PARTITION BY clause is an optional one. This guide has explained the use of PERCENT_RANK in PostgreSQL with and without PARTITION BY examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-percent_rank-in-postgresql/)

---

# How to Use PostgreSQL CUBE

> The CUBE clause in PostgreSQL can be used under the GROUP BY clause to apply an aggregate function on multilevel columns to generate reports.

PostgreSQL is used to structure the raw data in the form of tables which creates a database inside the DBMS to access it in the future. This data can be accessed using Structure Query Language or SQL queries for multiple purposes to find information. CUBE is used in the GROUP BY clause of the SQL query to get the aggregate of the column with other columns related to it.

This guide will explain how to use CUBE in PostgreSQL.  


 **How to Use PostgreSQL CUBE**

 **GROUP BY** clause is used to get the aggregate of the columns by using different functions like **sum()** , **avg()** , etc. The **GROUP BY** clause doesn’t provide aggregation on multiple levels, so to solve this problem **PostgreSQL** uses **CUBE**. PostgreSQL CUBE is generally used for reporting purposes in SQL databases with some applications like **PowerBi** , **Tableau** , etc.

 **Syntax**

The following is the syntax of the CUBE in PostgreSQL:
    
    
    SELECT
      c1,
      c2,
      c3,
      aggregate (c4)
     FROM
      table_name
       GROUP BY
      CUBE (c1, c2, c3);

The above syntax suggests:

\- It selects multiple columns from the table to perform some aggregation function on one of the columns with reference to the other column or columns in the table.  
\- After that, the resultant table is sorted for each of the columns that are mentioned in the **GROUP BY** clause using the **CUBE** clause.

 **Example 1: CUBE in PostgreSQL**

Use the following query to access the sales table which uses the **ORDER BY** clause to return the table according to the list of columns provided under it:
    
    
    SELECT * FROM sales
     ORDER BY continent, country, city;

Running the above query will display the data in the sales tables according to the **continent** , **country** , and **city** columns:

  
Use the following query to use **CUBE** in **PostgreSQL** under the **GROUP BY** clause:
    
    
    SELECT continent, country, city, sum(units_sold)
     FROM sales
     GROUP BY CUBE   (continent, country, city);

The above query will display the sum of all the **units_sold** and then provide the **sales** for each **continent** , **country** , and **city** individually. It also displays the sum of **units_sold** in each continent and then **units_sold** in every **country** :

 **Example 2: Partial CUBE in PostgreSQL**

The partial CUBE query is being used in the following code:
    
    
    SELECT continent, country, city, sum(units_sold)
     FROM sales
       GROUP BY continent,
     CUBE (country, city);

The above code will display the units_sold in each country and city according to each continent from the sales table:

  
That’s all about using the PostgreSQL CUBE clause within the GROUP BY clause.  


 **Conclusion**

PostgreSQL database allows the use of the CUBE clause inside the GROUP BY clause to apply aggregation function on multilevel. GROUP BY clause does not apply aggregation functions like sum(), avg(), etc on multilevel columns to provide reports. Postgres uses the CUBE clause to work with multiple columns and can also apply it on a partial level by providing one column to order the result accordingly. This guide has demonstrated the process of using CUBE in the PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-postgresql-cube/)

---

# How to Use PARTITION BY in PostgreSQL

> The PARTITION BY statement is used to create partitions in the tables to keep them efficient by dividing them into smaller tables for quick fetching of data.

Partition is crucial for the performance of databases with extensive tables and complicated schemas. The table's size can not exceed 32 GB in normal circumstances but before reaching that size performance issues may arise. In any case, partitioning is a good solution to keep the performance of the database up to date.

This guide will explain the use of PARTITION BY in PostgreSQL.

 **How to Use PARTITION BY in PostgreSQL**

Partition helps the database by dividing the large tables into smaller chunks to have better control and manageability over them. Using partitioning allows the query processor to scan smaller tables and indexes to fetch data more efficiently. It also helps PostgreSQL to scale by splitting large logical tables into smaller physical tables.

 **Syntax**

The following is the syntax containing the **PARTITION BY RANGE** statement with the name of the column on which the partition will be applied. RANGE partition will act on the given ranges and divides the tables according to these ranges:
    
    
    PARTITION BY RANGE(col_name);

The change in this query is just the keyword of **LIST** instead of RANGE which contains the **column name** and divides the table using that list:
    
    
    PARTITION BY LIST (col_name);

The **HASH** partition has the column name which acts as the hash key for the partitioning of the table:
    
    
    PARTITION BY HASH (col_name);

 **Example 1: PARTITION BY RANGE**

The following example creates a table with multiple fields to store data and apply to partition using the **created_at** column:
    
    
    CREATE TABLE my_partitioned_table (
      id INT,
      name VARCHAR(50),
      created_at TIMESTAMP
       ) PARTITION BY RANGE (created_at);

The **my_partitioned_table** has been created successfully:

Use the following query to create partitions in the table by giving ranges for the **created_at** column:
    
    
    CREATE TABLE my_partition_1 PARTITION OF my_partitioned_table
      FOR VALUES FROM ('2023-01-01') TO ('2023-06-30');

The above query creates a partition by giving the range of dates from the first of the year 2023 to mid of 2023:

The following query creates a second partition by providing the range from the mid of the year 2022 to the end of 2022:
    
    
    CREATE TABLE   my_partition_2 PARTITION OF   my_partitioned_table
      FOR VALUES FROM ('2022-07-01') TO ('2022-12-31');

The second partition has been created for the table:

Use the following query to insert data into the table:
    
    
    INSERT INTO my_partitioned_table (id, name, created_at)
     VALUES (1, 'Ambrose', '2022-07-15');

The data has been inserted successfully:

Use the following query to fetch all the data stored in the partition range less than the start of the year 2023 which is the second partition:
    
    
    SELECT * FROM my_partitioned_table
     WHERE created_at   < '2023-01-01';

The data stored in this range has been displayed on the screen:

 **Example 2: PARTITION BY LIST**

Use another example to create an **employee** table and apply **PARTITION BY LIST** on the **department** column:
    
    
    CREATE TABLE employee (
      id SERIAL,
      name VARCHAR(50),
      department VARCHAR(50),
      salary NUMERIC
       ) PARTITION BY LIST (department);

Provide values for the LIST partition while creating a partition to the employee table:
    
    
    CREATE TABLE   employee_it PARTITION OF employee
      FOR VALUES IN ('IT', 'Software');

The above query creates a partition with the list having “ **IT** ” and “ **Software** ” values:

Use the following query to create another partition containing a list having “ **HR** ” and “ **Admin** ” values:
    
    
    CREATE TABLE   employee_hr PARTITION OF employee
      FOR VALUES IN ('HR', 'Admin');

Insert the same values in the table and check if the first partition has any data stored in it:
    
    
    SELECT * FROM employee_it;

Executing the above query displays the data stored in the first partition:

Use this query to check the data from the second partition:
    
    
    SELECT * FROM employee_hr;

 **Example 3: PARTITION BY HASH**

Follow this example to create an employee table with the **PARTITION BY HASH** statement at the end of it:
    
    
    CREATE TABLE   employee (
      id SERIAL,
      name VARCHAR(50),
      department VARCHAR(50),
      salary NUMERIC
       ) PARTITION BY HASH (id);

The table has been created successfully having multiple columns but the partition will be applied on the id column:

Use the following code to create a **HASH** partition from the **employee** table using its **id** column:
    
    
    CREATE TABLE   employee_p1 PARTITION OF employee
      FOR VALUES WITH (MODULUS 4, REMAINDER 0);

The above code creates a partition with hash values containing **modulus** and the **remainder** on the id column. The modulus value determines the number of partitions a table will be divided into and the remainder determines where the row will be stored. The remainder value is calculated for each row using the hash value and then stores the row in the partition accordingly:

Use this code to create another partition of the employee table with a modulus value equal to 4 and 1 as the remainder:
    
    
    CREATE TABLE   employee_p2 PARTITION OF employee
      FOR VALUES WITH (MODULUS 4, REMAINDER 1);

Insert some data in the table and use this query to select data from the first partition:
    
    
    SELECT * FROM employee_p1;

Running the above code displays the data stored in the first partition:

Use the following query to get the data stored in the second partition:
    
    
    SELECT * FROM employee_p2;

That’s all about using PARTITION BY in PostgreSQL.

 **Conclusion**

Partitioning the tables in the database is very useful to keep them efficient and allows the query process to scan tables quickly. There are multiple methods of partitioning tables such as PARTITION BY RANGE, LIST, and HASH. This guide has explained the use of PARTITION BY statements in PostgreSQL with examples for each method.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-partition-by-in-postgresql/)

---

# How to Import Data into PostgreSQL on AWS RDS Database

> Create a PostgreSQL database on the Amazon cloud platform using RDS service and connect to it using its endpoint and import data in it from the local directory…

Amazon Relational Database Service or RDS is used to create databases on the cloud from the AWS platform dashboard. It allows the user to create the database using multiple engines like MySQL, PostgreSQL, Aurora, etc. The user can connect to the local client using the AWS RDS database created on the cloud.

This guide will explain how to import data into PostgreSQL on the AWS RDS database.

 **How to Import Data into PostgreSQL on AWS RDS Database?**

To import data into PostgreSQL on the AWS RDS database, visit the Amazon RDS service dashboard:

Click on the “ **Create database** ” button from the RDS dashboard:

Choose the “ **Standard Create** ” option as the database creation method:

Select “ **PostgreSQL** ” to run the database:

Select the version of the PostgreSQL engine and choose the “ **Free Tier** ” template:

Configure the database by providing the name of the database and specifying its master name as well:

Enter the password for the master user and confirm it by typing it twice:

Configure the storage section as the minimum storage allocation is 20GB and also select the maximum storage threshold:

Select VPC for the database and allow its public accessibility:

Keep the rest of the configuration default for the “ **Connectivity** ” section:

Select the password authentication to use the password set for the master user and configure the Monitoring section:

Once the configurations are complete for RDS, simply click on “ **Create database** ” to confirm its creation:

Click on the name of the database once it is created:

Head into the “ **Connectivity & security**” section:

Copy the “ **Endpoint** ” for the database provided by the platform:

Head into the “ **pgAdmin 4** ” dashboard from the local system and right-click on the server to register server:

Type the name of the server and then head into the “ **Connection** ” tab by clicking on it:

Paste the Endpoint for the AWS RDS in the “ **Host name/address** ” column, provide the password for the user, and click on the “ **Save** ” button:

Once the AWS RDS is connected, simply right-click on the user to click on the “ **Query Tool** ” button:

Create a table in the AWS RDS database using the following command in the Query Tool:
    
    
    CREATE TABLE persons (
      id SERIAL,
      name VARCHAR(30),
      date_of_birth DATE,
      email VARCHAR(255)
       )

 **SideNote:** Table creation is necessary to import data from the local database to the Amazon RDS PostgreSQL database:

After the creation of the table, simply right-click on the table to click on the “ **Import/Export Data…** ” button:

Select the “ **Import** ” option and enter the path for the file and click on the “ **Save** ” button:

That’s all about importing data into PostgreSQL on the AWS RDS database.

 **Conclusion**

To import the data into PostgreSQL on the AWS RDS database, create an RDS database on the AWS dashboard. Once the database is created, simply use the Endpoint provided by the platform for connecting to the local PostgreSQL client on the local system. Once the AWS RDS is connected to the PostgreSQL client, create a table and import data from the local directory. This guide has explained the process of importing data into PostgreSQL on the AWS RDS database.

---
[View this page online](https://www.commandprompt.com/education/how-to-import-data-into-postgresql-on-aws-rds-database/)

---

# How to Migrate Local PostgreSQL Database to AWS RDS

> Create a backup of the local PostgreSQL database and connect to the AWS RDS database. After that, simply restore the backup file to the RDS database.

AWS is the cloud computing service providing the platform with over 200 services to create different resources on the cloud. Its RDS service is used to create databases using multiple engines and that too with free tier-eligible resources. Setting up a new database for the AWS RDS can be a time taking process. Therefore, instead of creating or setting up a new database, Postgres users prefer to migrate the local database to the cloud RDS database.

This guide will demonstrate the migration of the local PostgreSQL database to the AWS RDS.

 **How to Migrate Local PostgreSQL Database to AWS RDS?**

To migrate the local PostgreSQL database, right-click on the local system database and select the “ **Backup…** ” button:

Click on the folder icon available in the file name section:

Type the name of the file and its format before clicking on the “ **Save** ” button:

Select the path of the file with its format and click on the “ **Backup** ” button:

The backup has been created successfully:

Head into the RDS dashboard from the AWS Management Console:

Visit the “ **Databases** ” page from the left panel:

Click on the name of the RDS database:

Copy the “ **Endpoint** ” of the RDS database from the “ **Connectivity & security**” section:

Head back to the “ **pgAdmin** ” dashboard to right-click on the servers button to register a new server:

Type the name of the server in the “ **General** ” page:

Head into the “ **Connection** ” page to paste the endpoint of the RDS database with username and password and click on the “ **Save** ” button:

Once the connection is established, right-click on the name of the database, and click on the “ **Restore…** ” button:

Type the format and path of the file to restore the database and click on the “ **Restore** ” button:

The process has been completed successfully and the database is restored:

The database has been migrated successfully from the local PostgreSQL to the AWS RDS:

That’s all about migrating the local PostgreSQL database to AWS RDS.

 **Conclusion**

To migrate the local PostgreSQL database to the AWS RDS, log into pgAdmin from the local system, and create a database backup. After that, connect to the AWS RDS database using its endpoint and restore the file from the local directory. This is how the database migration can be done from the local PostgreSQL to the AWS RDS.

---
[View this page online](https://www.commandprompt.com/education/how-to-migrate-local-postgresql-database-to-aws-rds/)

---

# What is PostgreSQL?

> PostgreSQL is the only Open Source database in the world that focuses on correctness first and extends that correctness to features such as NoSQL (JSON), ASYNC…

PostgreSQL is a powerful, open source object-relational database system. The current project has been operating since 1996 with the first release in 1997. The software can trace its heritage all the way back to University of California, Ingres. The lineage has the following software tree:
    
    
    Ingres->Postgres->Postgres95->PostgreSQL

With each being an individual project with different contributors and maintainers. PostgreSQL (also known as modernly as Postgres) is scalable, enterprise grade and extensible. It maintains proper ACID compliance and has a long history for providing enterprise class services to companies.

## Command Prompt heritage

Command Prompt has been a long time contributor to PostgreSQL, and since 1997 one the most vocal advocates of PostgreSQL in the enterprise production space. We wrote the first production class replication capabilities for PostgreSQL in the form of a former PostgreSQL distribution called Mammoth. As PostgreSQL matured into a truly Enterprise Grade Open Source database, Command Prompt switched its priorities to ensuring success with PostgreSQL deployments through support contracts, professional services and as a long term organizer of [Postgres Conference](<https://postgresconf.org/>). We also contribute to Psycopg3 (the Python Driver for PostgreSQL) and PgManage (a GUI for managing PostgreSQL).  


As the oldest of of the PostgreSQL companies it is uniquely positioned through extensive and comprehensive experience to provide support to any company wishing to have the greatest success with their PostgreSQL deployments. In North America there is no other company that [extends the life of PostgreSQL](<https://commandprompt.com/support/support-for-eol-versions-of-postgres/>) and related technologies (such as managed and cloud) to 8 years.

## The Amazon Incident

Although popular, PostgreSQL achieved a great boost in users when Amazon turned off its last Oracle (a legacy competitor to PostgreSQL) installation in favor of a PostgreSQL installation. A video of this momentous event [can be found here](<https://aws.amazon.com/blogs/aws/migration-complete-amazons-consumer-business-just-turned-off-its-final-oracle-database/>). Amazon has been a fantastic advocate of PostgreSQL and is in the top 4 of contributors to the project. In terms of cloud deployments, Amazon has the largest installations between its PostgreSQL forks including RDS for PostgreSQL, Aurora for PostgreSQL, DocumentDB, Redshift and of course, users operating in an EC2+PostgreSQL environment.

## PostgreSQL continues

PostgreSQL is the only Open Source database in the world that focuses on correctness first and extends that correctness to features such as NoSQL (JSON), ASYNC/SYNC Binary and Logical Replication. PostgreSQL also has features such as Horizontal partitioning, Stored Procedures and abilities to use replication to other legacy database systems such as MSSQL and Oracle.

PostgreSQL is available for free under the PostgreSQL License, which allows anyone to use, modify, and distribute the software without restriction. There are also many third-party tools and libraries available that extend the functionality of PostgreSQL and make it easier to work with.

## PostgreSQL Features

PostgreSQL is a truly Open Source Enterprise database. You can view the PostgreSQL feature matrix here and this is a brief list of the core features it supports:

  * ACID Compliance
  * Binary and Logical Replication (Async/Sync)
  * Legacy Database (Oracle, MSSQL, MySQL etc...) replication
  * Proper Typing
  * Extensive Date / Time support and related analysis and modification functions
  * GIS Support
  * Time Series Support
  * Horizontal Partitioning
  * UDFs and Procedures
  * Data Partitioning
  * Materialized Views
  * Multiple Index Concepts (Btree, Hash, GiST, GIN) and extensible Indexes
  * Multi Language Support (C, Python, Java, .Net, Go, Rust, PHP, Ruby etc...)
  * C, ODBC, .NET and JDBC connectivity
  * Custom Data Types
    * and on and on



## Resources:

  * Help with PostgreSQL
  * Download PostgreSQL
    * If you are running Linux, use your standard package manager (apt/yum/dnf) etc…
    * If you do not have access to Linux use the packages on [PostgreSQL.org](<https://www.postgresql.org/download/>).
  * PostgreSQL Education
    * Command Prompt [Education Portal](<https://commandprompt.com/education/>)
    * PostgreSQL.org [Docs](<https://www.postgresql.org/docs/>)
    * Postgres Conference [Youtube channel](<https://www.youtube.com/c/PostgresConference>)
    * PostgreSQL Training
  * Contact Command Prompt today



## PSA

To receive the most out of PostgreSQL it is advised that you deploy with Open Source PostgreSQL versions that do not force upgrades and break compatibility through removing extensibility.

---
[View this page online](https://www.commandprompt.com/education/what-is-postgresql/)

---

# PostgreSQL EOL (Extended Support)

> Postgres Support plus EOL

### **Support Policy**

Command Prompt with an appropriate support contract will provide 24x7x365 support for EOL versions of PostgreSQL up to 8 years from the initial release date. This extends the support lifecycle of a PostgreSQL release by 3 years and provides clients peace of mind when taking a mature and measured approach to upgrading in the future. Are you ready for a conversation? Contact us today.

###  **Versioning Policy**

The PostgreSQL Global Development Group releases a new major version containing new features about once a year. The standard lifespan of a community supported release of PostgreSQL is 5 years. Due to the community supported timeline, Cloud services and closed source products such as PostgreSQL Advanced Server will force an upgrade at or near the community EOL date.

Command Prompt Extended Support for EOL products extends this window by 3 years. This enables your enterprise to successfully not fix what isn't broken. It allows you to take your time properly, testing newer versions against your applications. It also generally decreases costs over time due to existing production quality deployments.  


Contact us today. We are a partner in your companies success.

###  **Supported Versions  
**

Command Prompt has options to support any version of PostgreSQL 9.6 or greater including related technologies:

  * EDB Postgres/Advanced Server
  * TimescaleDB
  * RDS or Aurora PostgreSQL
  * Google Cloud Postgres or AlloyDB
  * Azure Database for PostgreSQL



We are able to fully support these services and closed platforms through long tested and proven PostgreSQL Open Source technology.

You can read more about Command Prompt Extended Support for PostgreSQL here.

---
[View this page online](https://www.commandprompt.com/education/postgresql-support-eol/)

---

# How to Use for Loop to Iterate Over a Result Set in PostgreSQL

> Postgres allows us to utilize the for loop to loop through a query’s result set. A record-type variable can be declared to keep the rows of a result set return…

Iterating over a result set is a very crucial task in PL/pgSQL that can be achieved using loops. Loops are an essential part of programming that allows us to execute a block of code repeatedly. Among developers, the most popularly used loop is the “ **for** ” loop which is used for executing a block of code continually. Postgres allows us to utilize the for loop to loop through a query’s result set.

This blow demonstrates how to use a for loop to iterate over a result set of a Postgres query.

 **PL/pgSQL: Iterating Over a Query’s Result Set Using For Loop**

Use the provided syntax to iterate over the query’s result set:
    
    
    [label]
    for count IN query 
    LOOP
       statements
    END LOOP[ label ];

In the above query the “count” represents a RECORD-TYPE variable that will keep the rows of a result set.

Consider the following examples for a profound understanding of the PL/pgSQL for-loop.

 **Example: Iterating Over a Query’s Result Set**

In this example, we will utilize the “product_details” table whose content is enlisted in the following snippet:

Now we will utilize the for loop to fetch the product names of the top 3 cheapest products:
    
    
    DO
    $$
    DECLARE rec RECORD;
    BEGIN
    FOR rec IN SELECT pro_name, pro_price 
    FROM product_details 
    ORDER BY pro_price, pro_name
    LIMIT 3
    LOOP 
    RAISE NOTICE '% %$', rec.pro_name, rec.pro_price;
       END LOOP;
    END;
    $$

In the above snippet:

  * A record type variable named “rec” is declared that will keep/hold the rows of a result set returned by the SELECT query.
  * The table’s data is sorted according to the “pro_price” and “pro_name” columns.
  * The LIMIT clause makes sure to get only three records from the result set.
  * The RAISE NOTICE is used with the loop to iterate over the result set and print the respective results.



The output shows that the for loop has successfully iterated over the result set.

 **Conclusion**

Postgres allows us to utilize the for loop to loop through a query’s result set. A record-type variable can be declared to keep/hold the rows of a result set returned by the SELECT query. The RAISE NOTICE can be used within the loop to iterate over the result set and print the desired results. This post has illustrated the detailed procedure to iterate over a result set in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-for-loop-to-iterate-over-a-result-set-in-postgresql/)

---

# How Do I Get the Current Time Without Time Zone in PostgreSQL

> In Postgres, the “LOCALTIME” function is used to get the current time without zone information. It is executed without parentheses.

In PostgreSQL, a wide range of in-built functions are available that provide the current time, such as NOW(), CURRENT_TIME(), LOCALTIME, LOCALTIMESTAMP, etc. Some of them retrieve the current time along with the date while some don’t. Similarly, some functions provide only current time while some of them provide current time with zone information.

In this blog post, we will discuss how to get the current time without the zone offset in Postgres.

 **How Do I Get the Current Time Without Time Zone in Postgres?**

In Postgres, the “LOCALTIME” function is used to get the current time without zone information. It is executed without parentheses; however, you can use the parentheses if you have to get the time with a particular precision. The below snippet displays the syntax of the stated function:
    
    
    LOCALTIME(pre);

“pre” represents precision which is optional and can be omitted.

 **Example 1: Getting Current Time Using LOCALTIME**

In the following snippet, we will utilize the LOCALTIME function without a precision parameter:
    
    
    SELECT LOCALTIME;

The stated function will retrieve the current time without zone offset:

The first two digits “09” represent hours, and the next two digits “06” represent minutes. Similarly, “27” represents seconds while “835257” represents fractional seconds.

 **Example 2: Using LOCALTIME With Precision**

Below is the example code of utilizing the LOCALTIME function with a precision parameter:
    
    
    SELECT LOCALTIME(0);

The output depicts that passing “0” to the stated function trims the fractional seconds from the retrieved time.

 **Note:** Both CURRENT_TIME and LOCALTIME functions retrieve current time however, the first one provides time zone information while the second one doesn’t.

 **Example 3: Using LOCALTIME With Table’s Data**

Execute the SELECT query with the “*” wildcard to fetch all records of the “e_data” table:
    
    
    SELECT * FROM e_data;

Let’s execute the “INSERT” query to add the current time to the “e_data” table:
    
    
    INSERT INTO e_data(e_name, sign_in)
    VALUES ('John', LOCALTIME(0));

A new record has been successfully inserted into the “e_data” table, which can be verified by executing the following query:
    
    
    SELECT * FROM e_data;

The output snippet depicts that the current time has been successfully inserted into the selected table using the LOCALTIME function.

 **Conclusion**

In Postgres, the “LOCALTIME” function is used to get the current time without zone information. It is executed without parentheses; however, you can use the parentheses if you have to get the time with particular precision. This post has presented a comprehensive guide on getting current time without time zone offset.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-get-the-current-time-without-time-zone-in-postgresql/)

---

# How Does the ORDER BY Clause Deal With the NULL Values in PostgreSQL

> In PostgreSQL, the ORDER BY clause treats the null entries as the largest values. So, when a table is sorted ascendingly, then the null values will come at the…

In PostgreSQL, the **ORDER BY** clause allows us to sort the table’s data ascendingly or descendingly. A table can have non-null as well as null values. When it comes to NULL values, the ORDER BY clause treats them as the largest values. So, by default, the null values will be placed at the end/bottom of the table.

This blog will demonstrate the use of the ORDER BY clause with respect to null values.

 **How Does ORDER BY Clause Deal With the NULL Values in Postgres?**

The ORDER BY clause treats the null entries as the largest values. So, when a table is sorted ascendingly, then the null values will come at the bottom of the table. On the other hand, when the table is sorted descendingly, the null values will be placed at the start of the table.

 **Example 1: ORDER BY Ascending**

We will utilize the ORDER BY clause on the following “author_info” table:
    
    
    SELECT * FROM author_info;

Let’s utilize the ORDER BY clause on the “author_exp” column of the given table:
    
    
    SELECT * FROM author_info
    ORDER BY author_exp;

Null values are treated as the largest values by the ORDER BY clause.

 **Example 2: ORDER BY Descending**

Let’s utilize the ORDER BY clause with the “author_exp” column of the “author_info” table. However, this time we will sort the “author_info” table descendingly:
    
    
    SELECT * FROM author_info
    ORDER BY author_exp DESC;

This is how the ORDER BY clause works with the NULL values.

 **Conclusion**

In PostgreSQL, the ORDER BY clause treats the null entries as the largest values. So, when a table is sorted ascendingly, then the null values will come at the bottom of the table. On the other hand, when the table is sorted descendingly, the null values will be placed at the start of the table. This write-up has demonstrated the usage of the ORDER BY clause with NULL values.

---
[View this page online](https://www.commandprompt.com/education/how-does-the-order-by-clause-deal-with-the-null-values-in-postgresql/)

---

# How Do I Get the Week Number From a Specific Date in PostgreSQL

> Use the EXTRACT() or DATE_PART() function along with the “week” argument to get a week number from a particular date or timestamp.

While working with a Postgres database you may come across a situation where you need to get or extract a specific field from a date or timestamp. This may be because of sorting tables based on a specific date field, calculating experience/age in terms of specific fields, or any other reason. Whatever the reason is, when it comes to extracting a date field, the best suitable options are the **EXTRACT()** function and the **DATE_PART()** function.

This Postgres blog will guide you on getting the week number from a given date or timestamp.

 **How Do I Get the Week Number From a Specific Date or Timestamp in Postgres?**

Use the EXTRACT() or DATE_PART() function along with the “week” argument to get a week number from a particular date or timestamp:
    
    
    DATE_PART('week', date|timestamp);

Alternatively, the EXTRACT() function will be used as follows:
    
    
    EXTRACT('week' FROM date|timestamp);

Let’s learn it using the following examples.

 **Example 1: Getting Week From Date**

In the following example, we will execute both the DATE_PART() and EXTRACT() functions to fetch the week from the given date:
    
    
    SELECT DATE_PART('week', DATE '2018-06-08'),
    EXTRACT('week' FROM DATE '2018-06-08');

The output shows that it's the 23rd week of the year.

 **Example 2: Getting Week From Table’s Data**

We will use the EXTRACT() and DATE_PART() functions on the “emp_data” table, whose content is listed in the following snippet:
    
    
    SELECT * FROM emp_data;

Let’s execute the DATE_PART() and EXTRACT() functions on the “joining_date” column to find the joining week number of each employee:
    
    
    SELECT emp_id, emp_name, joining_date,
    EXTRACT('WEEK' FROM joining_date) AS joining_week_number,
    DATE_PART('WEEK', joining_date) AS emp_joining_week_number
    FROM emp_data;

The result set demonstrates the joining week number of each employee.

That’s all about getting the week number from a particular date in PostgreSQL.

 **Conclusion**

Use the EXTRACT() or DATE_PART() function along with the “week” argument to get a week number from a particular date or timestamp. The stated functions can extract the week number of the year from the date value or timestamp. This post has discussed a couple of methods to fetch the week number from the given date or timestamp.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-get-the-week-number-from-a-specific-date-in-postgresql/)

---

# How to Use GROUP BY Clause on Multiple Columns in PostgreSQL

> In PostgreSQL, multiple columns can be used with the GROUP BY clause. Specify a comma between the columns to be grouped when using the GROUP BY clause on multi…

In Postgres, the **GROUP BY** clause is utilized to group the table’s data based on single or multiple columns. Grouping the table’s data offers various features like removing redundancy, improving code readability, helping in performing analytics, and so on. By grouping multiple columns, we can calculate different statistics for a group of records.

This write-up will illustrate the working of the GROUP BY clause on multiple columns in Postgres.

 **How to Use GROUP BY Clause on Two or More Columns in PostgreSQL?**

In PostgreSQL, multiple columns can be used with the GROUP BY clause. It helps us aggregate/collect data into groups. You must specify a comma between the columns to be grouped when using the GROUP BY clause on multiple columns:
    
    
    SELECT "col_1", "col_2", "col_N"
    FROM "tab_name"
    WHERE condition
    GROUP BY "col_1", "col_2", "col_N"
    ORDER BY "col_name";

The columns defined in the SELECT query must be utilized in the GROUP BY clause, otherwise, you can face unwanted circumstances.

 **Sample Table**

We will utilize the “emp_bio” table in the upcoming examples, whose data is shown in the following snippet:
    
    
    SELECT * FROM emp_bio;

Let’s head toward the practical examples.

 **Example 1: Group by a Single Column**

Assume that we have to group the employee’s data with respect to their joining date. To do this, we will utilize the COUNT() function and the GROUP BY clause as follows:
    
    
    SELECT joining_date,
    COUNT(e_id) AS total_employees
    FROM emp_bio
    GROUP BY joining_date;

The output shows that three employees joined in 2021 while the rest of two joined in 2022.

 **Example 2: Group by Multiple Columns**

Now let’s suppose we have to group the employee’s data based on their date of joining and salaries. For this purpose, we need to specify the “joining_date” and “emp_sal” columns in the GROUP BY clause as follows:
    
    
    SELECT joining_date, emp_sal
    FROM emp_bio
    GROUP BY joining_date, emp_sal;

The output shows that the employees have been grouped based on the selected columns.

 **Conclusion**

In PostgreSQL, multiple columns can be used with the GROUP BY clause. You must specify a comma between the columns to be grouped when using the GROUP BY clause on multiple columns. The columns defined in the SELECT query must be utilized in the GROUP BY clause, otherwise, you can face unwanted circumstances. This post has explained the use of the GROUP BY clause on two or more columns.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-group-by-clause-on-multiple-columns-in-postgresql/)

---

# How to Fix the “must appear in the GROUP BY clause” Error in PostgreSQL

> A &quot;must appear in the GROUP BY clause&quot; error occurs in PostgreSQL when a column is specified in the SELECT statement but it is not utilized in the GROUP BY cla…

In PostgreSQL, grouping the table’s data helps us in removing redundancy. It can be done by utilizing the GROUP BY clause. However, while working with the GROUP BY clause, users often encounter a “must appear in the GROUP BY clause” error. The stated error can occur because of inappropriate use of the GROUP BY clause or aggregate functions.

This article will present a detailed guide on fixing the “must appear in the GROUP BY clause” Error in PostgreSQL.

 **How to Fix the “must appear in the GROUP BY clause” Error in Postgres?**

In PostgreSQL, the stated error appears because of the following reason: a column is specified in the SELECT statement but it doesn’t appear in the GROUP BY clause or any aggregate function.

Here is a simple example that shows the stated error:
    
    
    SELECT joining_date,
    COUNT(emp_id) AS total_employees
    FROM emp_info
    GROUP BY emp_id;

To fix this error, the columns that are listed in the SELECT LIST must appear in the GROUP BY clause or they must appear within an aggregate function. For example, specifying the “joining_date” column in the GROUP BY clause will rectify the stated error:
    
    
    SELECT joining_date,
    COUNT(emp_id) AS total_employees
    FROM emp_info
    GROUP BY joining_date;

In the above code, we utilized the “emp_id” in an aggregate function named “COUNT()”, so it wouldn’t cause any error. However, if we used it in the SELECT statement without any aggregate function and also we didn’t utilize it in the GROUP BY clause, then it will result in an error:

The output snippet confirms that the employees have been successfully grouped based on the joining_date column.

 **Conclusion**

A "must appear in the GROUP BY clause" error occurs in PostgreSQL when a column is specified in the SELECT statement but it is not utilized in the GROUP BY clause or any aggregate function. To fix this error, the columns that are listed in the SELECT LIST must be included in the GROUP BY clause or they must be utilized with an aggregate function. This article has explained the possible reason and the suitable solution for the “must appear in the GROUP BY clause” error.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-the-must-appear-in-the-group-by-clause-error-in-postgresql/)

---

# What Does JUSTIFY_INTERVAL() Function Do in PostgreSQL?

> JUSTIFY_INTERVAL() is a built-in DateTime function that utilizes the JUSTIFY_DAYS() and JUSTIFY_HOURS() functions with sign adjustments to adjust the intervals…

For any database developer, converting or adjusting days into months and hours into days is routine work. To do this, Postgres users use different built-in functions. For instance, the **JUSTIFY_HOURS()** function adjusts hours to days while the **JUSTIFY_DAYS()** function adjusts days to months. When it comes to adjusting intervals, it can be done using the **JUSTIFY_INTERVAL()** function.

This blog demonstrates how to adjust intervals using the JUSTIFY_INTERVAL() function in PostgreSQL.

 **What Does JUSTIFY_INTERVAL() Function Do in PostgreSQL?**

 **JUSTIFY_INTERVAL()** is a built-in DateTime function that utilizes the JUSTIFY_DAYS() and JUSTIFY_HOURS() functions with sign adjustments to adjust the intervals.
    
    
    JUSTIFY_INTERVAL(input_interval);

The return type of the JUSTIFY_INTERVAL() is an interval.

 **Example 1: Adjusting Intervals**

The following snippet demonstrates the basic usage of the JUSTIFY_INTERVAL() function in Postgres:
    
    
    SELECT JUSTIFY_INTERVAL(INTERVAL '1 Month 29 Days 84 hours');

The specified hours have been successfully adjusted to days and days have been adjusted to months. One more example is illustrated in the following snippet that explains the use of the JUSTIFY_INTERVAL() function with an additional sign adjustment:
    
    
    SELECT JUSTIFY_INTERVAL(INTERVAL '1 Month 2 Days -84 hours');

The given interval has been adjusted to the appropriate days and hours.

 **Example 2: Using JUSTIFY_INTERVAL() on Table’s Data**

Use the “SELECT *” query to fetch all data of the “article_record” table:
    
    
    SELECT * FROM article_record;

Let’s use the JUSTIFY_INTERVAL() function on the selected table to adjust the intervals appropriately:
    
    
    SELECT *, JUSTIFY_INTERVAL(article_published)
    FROM article_record;

That’s all about the JUSTIFY_INTERVAL() function.

 **Conclusion**

 **JUSTIFY_INTERVAL()** is a built-in DateTime function that utilizes the JUSTIFY_DAYS() and JUSTIFY_HOURS() functions with sign adjustments to adjust the intervals. Its return type is an interval. This post presented a thorough understanding of adjusting hours and days to appropriate intervals using Postgres’ JUSTIFY_INTERVAL() function.

---
[View this page online](https://www.commandprompt.com/education/what-does-justify_interval-function-do-in-postgresql/)

---

# How to Use JUSTIFY_HOURS() Function in PostgreSQL

> In PostgreSQL, a built-in DateTime function named JUSTIFY_HOURS() is used to adjust the 24-hour time periods to days.

Adjusting days to months and hours to days is a routine task for any database developer. The need of adjusting hours to days arises while working with intervals. For instance, we may receive an interval that has any number of hours greater than “24”. In such cases, the additional hours must be adjusted to the days. To deal with this, the **JUSTIFY_HOURS()** function can be used in Postgres.

This blog demonstrates how to adjust the hours to days using the JUSTIFY_HOURS() function.

 **What Does JUSTIFY_HOURS() Function Do in PostgreSQL?**

In PostgreSQL, a built-in DateTime function named JUSTIFY_HOURS() is used to adjust the 24-hour time periods to days. The stated function accepts an interval as an argument and adjusts the given hours to months if the specified hours are greater than 24 hours:
    
    
    JUSTIFY_HOURS(input_interval);

The return type of the JUSTIFY_HOURS() is an interval.

 **Example 1: Adjusting Hours to Days**

The following snippet demonstrates the basic usage of the JUSTIFY_HOURS() function in Postgres:
    
    
    SELECT JUSTIFY_HOURS(INTERVAL '84 hours');

The specified hours have been successfully adjusted to respective days. We will consider one more example for a profound understanding of the JUSTIFY_HOURS() function:
    
    
    SELECT JUSTIFY_HOURS(INTERVAL '2 Days 57 Hours');

The given interval has been adjusted to the days based on the 24-hour time period.

 **Example 2: Using JUSTIFY_HOURS() on Table’s Data**

Use the “SELECT *” query to fetch all data of the “article_record” table:
    
    
    SELECT * FROM article_record;

The above snippet illustrates that a couple of intervals need to be adjusted to days. To do that, we will apply the JUSTIFY_HOURS() function on the “article_published” column of the selected table:
    
    
    SELECT *, JUSTIFY_HOURS(article_published)
    FROM article_record;

The output confirms that the hours have been successfully adjusted to days.

That’s all about the JUSTIFY_HOURS() function.

 **Conclusion**

In PostgreSQL, a built-in DateTime function named JUSTIFY_HOURS() is used to adjust the 24-hour time periods to days. The stated function accepts an interval as an argument and adjusts the given hours to months if the specified hours are greater than 24 hours. Its return type is an interval. This post presented a thorough understanding of adjusting hours to days using Postgres’ JUSTIFY_HOURS() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-justify_hours-function-in-postgresql/)

---

# PostgreSQL CLOCK_TIMESTAMP() Function

> In PostgreSQL, the “CLOCK_TIMESTAMP()” function helps us in getting the current DateTime of a database that may change during query execution.

PostgreSQL offers numerous DateTime functions that retrieve today’s current date and time. Among them, a commonly used function is the “ **CLOCK_TIMESTAMP()** ” to get the current DateTime that may change during query execution. Users often use the CLOCK_TIMESTAMP() function with the pg_sleep() function to note the delay time between two statements.

This article will explain the use of the CLOCK_TIMESTAMP() function using different examples.

 **PostgreSQL CLOCK_TIMESTAMP() Function**

The CLOCK_TIMESTAMP() doesn’t accept any argument. To use this function, all you need to do is, invoke it with the SELECT statement, and the rest will be tackled by the function itself. It can also be used with the INSERT query to add the system’s DateTime to a specific table:
    
    
    CLOCK_TIMESTAMP();

The return type of the stated function is TIMESTAMPTZ, which means it also provides zone information.

 **Example 1: Using CLOCK_TIMESTAMP() in Postgres**

In the following snippet, the CLOCK_TIMESTAMP() function is utilized with the SELECT statement to fetch the current DateTime of the database:
    
    
    SELECT CLOCK_TIMESTAMP();

The output demonstrates that it's the “1st of May 2023” and the current time is “02:58:27”. While “07” indicates the time zone.

 **Example 2: Using CLOCK_TIMESTAMP() With pg_sleep in Postgres**

The following snippet illustrates the usage of CLOCK_TIMESTAMP() with the pg_sleep() function:
    
    
    SELECT CLOCK_TIMESTAMP(),
    pg_sleep(2),
    CLOCK_TIMESTAMP(),
    pg_sleep(2),
    CLOCK_TIMESTAMP();

That's all about the CLOCK_TIMESTAMP() function in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “ **CLOCK_TIMESTAMP()** ” function helps us in getting the current DateTime of a database that may change during query execution. To use this function, all you need to do is, invoke it with the SELECT statement, and the rest will be tackled by the function itself. It can also be used with the INSERT query to add the system’s DateTime to a specific table. The return type of the stated function is TIMESTAMPTZ, which means it also provides zone information. This post has covered various use cases of the Postgres’ CLOCK_TIMESTAMP() function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-clock_timestamp-function/)

---

# What Does JUSTIFY_DAYS() Function Do in PostgreSQL

> In PostgreSQL, a built-in DateTime function named JUSTIFY_DAYS() is used to adjust the 30-day time periods to months.

While working with date time values in Postgres, we often encounter a situation where we need to adjust the interval’s values. For instance, we may receive an interval that has any number of days greater than “30”. In such situations, we need to adjust the number of days according to the 30-day time period to represent them as months. To do this, the **JUSTIFY_DAYS()** function can be used in Postgres.

This blog demonstrates how to adjust the days to months using the JUSTIFY_DAYS() function.

 **What Does JUSTIFY_DAYS() Function Do in PostgreSQL?**

In PostgreSQL, a built-in DateTime function named **JUSTIFY_DAYS()** is used to adjust the 30-day time periods to months. It accepts an interval and adjusts the given days to months if its day field is greater than 30 days:
    
    
    JUSTIFY_DAYS(input_interval);

The return type of the JUSTIFY_DAYS() is an interval.

 **Example 1: Adjusting Days to Months**

The following snippet demonstrates the basic usage of the JUSTIFY_DAYS() function in Postgres:
    
    
    SELECT JUSTIFY_DAYS(INTERVAL '84 days');

The output shows that the days have been successfully adjusted to the months. Let’s consider one more example to understand the working of the JUSTIFY_DAYS() function better:
    
    
    SELECT JUSTIFY_DAYS(INTERVAL '2 Months 57 days');

The given interval has been adjusted to the months based on the 30-day time period.

 **Example 2: Using JUSTIFY_DAYS() on Table’s Data**

Use the SELECT command with the “*” wildcard to fetch all data of the “article_record” table:
    
    
    SELECT * FROM article_record;

In the above table, there are some intervals that need to be adjusted to months. So for this purpose, we will execute the JUSTIFY_DAYS() function on the article_published column of the given table:
    
    
    SELECT * , JUSTIFY_DAYS(article_published)
    FROM article_record;

The output demonstrates that the days have been successfully adjusted to months.

That was all about the JUSTIFY_DAYS() function.

 **Conclusion**

In PostgreSQL, a built-in DateTime function named JUSTIFY_DAYS() is used to adjust the 30-day time periods to months. It accepts an interval and adjusts the given days to months if its day field is greater than 30 days. Its return type is an interval. This post presented a thorough understanding of adjusting days to months using Postgres’ JUSTIFY_DAYS() function.

---
[View this page online](https://www.commandprompt.com/education/what-does-justify_days-function-do-in-postgresql/)

---

# How to Check Sequence Details in PostgreSQL

> In PostgreSQL, the “\d” command and “information_schema.sequences” are used to describe a specific sequence.

In PostgreSQL, sequences are used to create an auto-incremented series of integers. Sequences can be associated with a table’s column to define an auto-increment column. Various options/parameters are available in Postgres that can be used with the CREATE SEQUENCE command to create a customized sequence. However, while working with an already existing sequence, it's important to check its details before proceeding. To do this, a couple of approaches are used in Postgres.

This write-up will demonstrate how to check the sequence details in Postgres using:

\- “\d” Command  
\- Information_schema

So, let’s start with the “\d” command.

 **How to Check Sequence Details Using “\d” Command?**

“\d” is a metadata command that is usually used to describe a specific table, however, it can also be used to check the details of a particular sequence. For this purpose, the “\d” command must be followed by the sequence name:
    
    
    \d seq_name;

 **Example: Describing a Sequence**

First, let’s execute the “\ds” command to list the available sequences:
    
    
    \ds;

Now, utilize the “\d” along with the sequence name, let’s say “example_seq”:
    
    
    \d example_seq;

The stated command retrieves all the details of the selected sequence, including type, start value, minimum value, etc.

 **How to Check Sequence Details Using information_schema?**

Another useful way of checking the sequence details is the “information_schema” which can be executed with the help of the SELECT command from any interface like CLI or GUI:
    
    
    SELECT sequence_name, data_type, start_value, minimum_value, maximum_value, increment, cycle_option
    FROM information_schema.sequences 
    WHERE sequence_name='example_seq';

In the above query:

\- All the columns to be fetched are specified within the SELECT statement.  
\- The “information_schema” is used with the “sequences” view in the FROM clause.  
\- While the name of the selected sequence is specified in the WHERE clause.

The output proved that the “information_schema” successfully retrieves all the sequence details.

 **Conclusion**

In PostgreSQL, the “\d” command and “information_schema” are used to describe a specific sequence. Run the “\d” command followed by the sequence name to get sequence details using SQL Shell. While the “information_schema” can be used with the help of the SELECT command to get all the necessary details regarding the selected sequence. This post has explained a couple of methods to describe the sequence details in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-sequence-details-in-postgresql/)

---

# How to Find Maximum and Minimum Values From a PostgreSQL Table

> In PostgreSQL, the MIN() and MAX() functions can be utilized to retrieve the minimum and maximum values among the list of given values.

PostgreSQL offers various functions to compute and analyze the data. The **MIN()** and **MAX()** are built-in aggregate functions in Postgres that help us find the least and greatest values among the list of values. These functions can be applied to any data like strings, numbers, dates, etc. to quickly retrieve the minimum or maximum values.

This post will explain how to use the MIN() and MAX() functions to find the lowest and highest values among the given list of values.

 **How to Find/Get Maximum and Minimum Values From a PostgreSQL Table?**

The MIN() and MAX() functions accept a set of values as arguments, compute the minimum and maximum of the given non-null values, and retrieve the least and greatest value among the given list respectively.

Utilize the given syntax to get the least value:
    
    
    SELECT MIN(expression) 
    FROM tab_name;

Use the provided syntax to find the maximum value:
    
    
    SELECT MAX(expression) 
    FROM tab_name;

The return type of the MIN() and MAX() functions depends on the argument type.

 **Example 1: Finding Minimum and Maximum Values From a Postgres Table**

A table named “author_info” has already been created in our database. Let’s utilize the SELECT command with the “*” wildcard to fetch the table’s data:
    
    
    SELECT * FROM author_info;

Let’s utilize the MIN() and MAX() functions on the “author_exp” column of the “author_info” table to find the authors having the least and most experience:
    
    
    SELECT MIN(author_exp), MAX(author_exp)
    FROM author_info;

The output shows that in the above table, the author’s minimum experience is “1 year” and maximum experience is “11 years”.

Let’s consider one more example for a profound understanding of the stated functions.

 **Example 2: Find Minimum and Maximum Experience for Each Gender**

In the following example, we will utilize the MIN() and MAX() function to find the least and most experienced author. However, this time we will also utilize the GROUP BY clause to group the male and female authors separately:
    
    
    SELECT gender, MIN(author_exp), MAX(author_exp)
    FROM author_info
    GROUP BY gender;

The output shows that the most experienced female author has eleven years of experience while a male author has seven years of experience. Similarly, the least experienced female has one year of experience and the least experienced male has two years.

 **Conclusion**

In PostgreSQL, the MIN() and MAX() functions can be utilized to retrieve the minimum and maximum values among the list of given values. The MIN() and MAX() functions accept a set of values as arguments, compute the minimum and maximum of the given non-null values, and retrieve the least and greatest value among the given list respectively. This post has explained the use of MIN() and MAX() functions in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-maximum-and-minimum-values-from-a-postgresql-table/)

---

# How to Upgrade PostgreSQL on CentOS 7?

> To Upgrade PostgreSQL on CentOS 7, add the appropriate repository, stop PostgreSQL, upgrade PostgreSQL, restart PostgreSQL, verify the upgrade, and test the ap…

In CentOS, upgrading the PostgreSQL version can bring substantial improvements in performance, security, and access to new features. Nevertheless, it is crucial to plan and execute the upgrade process with utmost care to prevent the loss of data or any system downtime. It is also necessary to identify any potential compatibility issues that may arise with third-party applications and plugins that rely on PostgreSQL.

This article illustrates the step-by-step procedure for upgrading PostgreSQL 9 to 13 on CentOS.

 **How to Upgrade PostgreSQL on CentOS 7?**

Upgrading the PostgreSQL version to CentOS ensures that the system is secure, stable, and efficient. To upgrade PostgreSQL from version 9 to version 13 on CentOS, follow these steps:

 **Step 1: Verify Upgrade:**

Users can verify the existing PostgreSQL version using the following command:
    
    
    $ postgres --version

 **Note** : It is essential to back up your current PostgreSQL database before upgrading to version 13. To create a backup of the current PostgreSQL database utilizing the pg_dump command.

 **Step 2: Disable Access to the PostgreSQL**

Before upgrading, users must disable access to the PostgreSQL database. This can be done by stopping the PostgreSQL service:
    
    
    $ sudo systemctl stop postgresql.service

This command stops the PostgreSQL service.

 **Step 3: Add the PostgreSQL 13 Repository**

To upgrade to PostgreSQL version 13, users need to add the PostgreSQL 13 repository to their system.
    
    
    $ sudo yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

This command adds the PostgreSQL 13 repository to the system.

 **Step 4: Install PostgreSQL 13**

After adding the PostgreSQL 13 repository, users can install PostgreSQL 13:
    
    
    $ sudo yum -y install postgresql13 postgresql13-server

This command installs PostgreSQL 13 on the system.

 **Step 5: Initialize PostgreSQL**

After installing PostgreSQL 13, users need to initialize the database.
    
    
    $ sudo /usr/pgsql-13/bin/postgresql-13-setup initdb

This command initializes the PostgreSQL 13 database.

 **Step 6: Start PostgreSQL**

Users can start the PostgreSQL 13 service via the below script:
    
    
    $ sudo systemctl start postgresql-13

This command starts the PostgreSQL 13 service.

 **Step 7: Verify the Upgrade**

Users can verify the upgrade by checking the status.

This command displays that PostgreSQL version 13 is in a running state.

That's it! You have successfully upgraded your PostgreSQL database from version 9 to version 13.

 **Conclusion**

To Upgrade PostgreSQL on CentOS 7, it is essential to add the appropriate repository, stop PostgreSQL, upgrade PostgreSQL, restart PostgreSQL, verify the upgrade, and test the application compatibility. Performing regular upgrades can improve system performance, security, and provide new features, therefore it is essential to keep your system up to date.

---
[View this page online](https://www.commandprompt.com/education/how-to-upgrade-postgresql-on-centos-7/)

---

# How to Fix “nextval: reached maximum value of sequence” Error in PostgreSQL

> In PostgreSQL, a commonly faced error “nextval: reached maximum value” error occurs when a sequence reaches its maximum value and the user is still trying to g…

In PostgreSQL, a commonly faced error “ **nextval: reached maximum value** ” error occurs when a sequence reaches its maximum value and the user is still trying to generate a new value. Postgres offers various methods to deal with the stated issue, such as resetting the sequence, altering the maximum value of the sequence, repeating the sequence, and so on.

This post will explain some useful methods to rectify the “nextval: reached maximum value” error in PostgreSQL.

 **How to Fix the “nextval: reached a maximum value of sequence” Error in Postgres?**

We have created a sequence name example_seq whose details are enlisted in the following snippet:
    
    
    \d example_seq;

Let’s execute the nextval() function to see how the stated error occurs in Postgres:
    
    
    SELECT nextval('example_seq');

To fix the “nextval: reached a maximum value” error, the below-listed approaches can be used in Postgres:

\- Method 1: Use Cycle Option  
\- Method 2: Alter the Sequence Maximum Value  
\- Method 3: Remove the MAXVALUE Option From the Sequence  
\- Method 4: RESTART the Sequence

 **Method 1: Use Cycle Option**

Specifying the cycle option will restart the sequence once it reaches the maximum limit:
    
    
    ALTER SEQUENCE example_seq
    CYCLE;

Let’s confirm the sequence structure using the following command:
    
    
    \d example_seq;

The output confirms that the “CYCLE” option has been enabled successfully. Let’s run the nextval() function once more:
    
    
    SELECT nextval('example_seq');

The output shows that the sequence has been restarted from the starting value.

 **Method 2: Alter the Sequence Maximum Value**

Increasing the maximum value of the sequence will also rectify the stated error:
    
    
    ALTER SEQUENCE example_seq
    MAXVALUE 500;

Now the stated error wouldn’t appear until the sequence reaches the specified maximum value.

 **Method 3: Remove the MAXVALUE Option From the Sequence**

Removing the MAXVALUE option from the sequence will set the maximum value to the default(i.e. Default maximum value of the specified data type).
    
    
    ALTER SEQUENCE example_seq
    NO MAXVALUE;

In this case, the stated error wouldn’t appear until the sequence reaches the maximum value of the specified data type.

 **Method 4: RESTART the Sequence**

Resetting the sequence value will restart the sequence from the beginning. To do this, utilize the ALTER SEQUENCE command with the RESTART argument:
    
    
    ALTER SEQUENCE example_seq
    RESTART;

The output verifies that the sequence has been reset successfully.

 **Conclusion**

In PostgreSQL, a commonly faced error “ **nextval: reached maximum value** ” error occurs when a sequence reaches its maximum value and the user is still trying to generate a new value. In Postgres, various methods such as the “Cycle” option, “Altering the Maximum Value”, “Removing the MAXVALUE” option, and RESTART option are used. This post has provided several methods to fix the “nextval: reached maximum value” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-nextval-reached-maximum-value-of-sequence-error-in-postgresql/)

---

# How to Query Data From a Specific Table in PostgreSQL

> To query data from a PostgreSQL table, open SQL Shell, and execute the “SELECT *” command followed by the table name.

The term “query data” refers to a process of fetching or retrieving data from single or multiple tables. While working with RDMS like PostgreSQL, querying the data from a table is a very common but crucial task that can be done by a “ **SELECT** ” statement. The stated command can be utilized for different purposes, such as querying all data of a table, some specific records of a table, fetching some specific columns from a table or selecting various columns from multiple tables.

This article will demonstrate:

\- How to Query Table Data Using SQL Shell?  
\- How to Query Table Data Using pgAdmin?

 **How to Query Table Data Using SQL Shell?**

The “ **SELECT** ” query is used with the “*” symbol to query all the data of a particular table of the selected database. To utilize the “ **SELECT** ” query in Postgres, follow the provided syntax:
    
    
    SELECT * FROM tab_name;

The stated command will fetch all records of the specified “ **tab_name”**.

 **Example 1: How to Query All Data From a Postgres Table?**

Open the “SQL Shell” and run the following metadata command to enlist the available tables in the current database:
    
    
    \dt

Now, utilize the SELECT * command along with the table name to fetch all of its content:
    
    
    SELECT * FROM author_info;

Here in this query, the “ **SELECT** ” command is utilized to query the data of the selected table. The “ ***** ” represents a wildcard that helps us select all columns of a table. While “ **FROM** ” is a keyword used to specify the table from which the data will be fetched or retrieved:

The output shows that all data from the specified table has been successfully queried.

 **Example 2: How to Query Specific Data in Postgres?**

To query specific data from a Postgres table, use the “ **WHERE** ” clause with the “ **SELECT** ” query as follows:
    
    
    SELECT * FROM 
    tab_name 
    WHERE condition;

The “WHERE” clause will restrict the SELECT statement to query only those records that meet the specified condition. For example, the below piece of code will query only those authors whose experience is more than five years:
    
    
    SELECT * FROM author_info
    WHERE author_exp > 5;

The table records that meet the specified condition have been successfully queried.

 **How to Query Table Data Using pgAdmin?**

The “ **View/Edit Data** ” option of the pgAdmin assists us in querying the data of a particular table. It directs us to the Query tool, where we can edit the query to perform specific operations, such as filtering the selected table, adding new rows, updating an existing row, etc.

 **Example 2: Querying Table Data Using pgAdmin**

To query the table data using pgAdmin, first, extend the “ **Servers** ” list, select a desired database, and then navigate to “ **Schemas** ”:

Now search for the “ **public** ” section and then navigate to the “ **Tables** ” section:

Select the table from the available list of the selected database:

Right-click on the selected table, and choose the “ **All Rows** ” option from the “ **View/Edit Data** ” option:

Consequently, the selected table will be queried:

That was all about querying the data from a specific table in Postgres.

 **Conclusion**

To query data from a Postgres table, open SQL Shell, and execute the “ **SELECT *** ” command followed by the table name. While, in the case of pgAdmin, first, expand the “Servers” tree, select a database, select a schema, and then select a table from the available list. After that, right-click on the selected table and choose the “ **View/Edit Data** ” option. This article presented various methods to query the table data in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-query-data-from-a-specific-table-in-postgresql/)

---

# How to Resolve “MINVALUE must be less than MAXVALUE” Error in PostgreSQL

> In PostgreSQL, the “MINVALUE must be less than MAXVALUE” error can be resolved by increasing the value of the “MAXVLAUE” option and decreasing the value of the…

While working with the Postgres sequences, users often encounter a “ **MINVALUE must be less than MAXVALUE** ” error. This error occurs at the time of sequence creation. A common issue that causes the stated error is setting inappropriate values for the “MINVALUE” and “MAXVALUE” options while creating a sequence.

This article will present an easy fix to rectify the “MINVALUE must be less than MAXVALUE” error in Postgres.

 **How to Resolve “MINVALUE must be less than MAXVALUE” Error in Postgres?**

As the name itself depicts, the stated error occurs in Postgres if a user specifies the value of the “MINVALUE” option is more than or equal to the “MAXVALUE” option. The below snippet will help you understand how this error occurs in Postgres:
    
    
    CREATE SEQUENCE example_sequence
    MINVALUE 100
    MAXVALUE 100;

In the above snippet, we encounter an error because the value of MINVALUE and MAXVALUE were equal. Similarly, if the “MAXVALUE” is less than the “MINVALUE”, then we will face the same error as follows:

In the case of descending sequence, we can also experience the same error if we didn't specify the MAXVALUE explicitly:
    
    
    CREATE SEQUENCE example_sequence
    INCREMENT -3
    MINVALUE 10;

This error can be resolved by increasing the value of the “MAXVLAUE” option and decreasing the value of the “MINVALUE” option or both at the same time:
    
    
    CREATE SEQUENCE example_sequence
    MINVALUE 100
    MAXVALUE 200;

The above output proves that increasing the value of the “MAXVALUE” option resolves the stated error. Similarly, in the case of descending sequence, specifying the MAXVALUE option will resolve this error:
    
    
    CREATE SEQUENCE example_sequence_1
    INCREMENT -3
    MINVALUE 10
    MAXVALUE 100;

The stated error has been rectified successfully.

 **Conclusion**

In PostgreSQL, the “MINVALUE must be less than MAXVALUE” error can be resolved by increasing the value of the “MAXVLAUE” option and decreasing the value of the “MINVALUE” option or both at the same time. In the case of descending sequence, we can also experience the same error if we didn't specify the MAXVALUE explicitly. However, it can be fixed by explicitly specifying the MAXVALUE. This post explained how to fix the “MINVALUE must be less than MAXVALUE” error in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-resolve-minvalue-must-be-less-than-maxvalue-error-in-postgresql/)

---

# How to Pause Query Execution in PostgreSQL

> In PostgreSQL, various in-built functions like pg_sleep(), pg_sleep_until(), and pg_sleep_for() are used to pause or delay the query’s execution for a specific…

PostgreSQL provides various in-built functions to pause or delay the query’s execution for a specific period. For example, the **pg_sleep()** , **pg_sleep_until()** , and **pg_sleep_for()** are popularly used functions that allow us to pause the execution of a statement halfway. All the stated functions are very similar, but they work a little differently.

This blog will illustrate how to pause the query’s execution for a specific time period in PostgreSQL.

 **How to Pause Query Execution in PostgreSQL?**

In Postgres, the below-enlisted functions are used to pause the execution of a statement for a certain time period:

\- **Method 1:** pg_sleep()  
\- **Method 2:** pg_sleep_until()  
\- **Method 3:** pg_sleep_for()

 **How to Pause Query Execution pg_sleep() Function?**

In Postgres, the pg_sleep() function delays the query’s execution for a certain number of seconds:
    
    
    SELECT CLOCK_TIMESTAMP(),
    pg_sleep(2),
    CLOCK_TIMESTAMP(),
    pg_sleep(2),
    CLOCK_TIMESTAMP();

A delay of 2 seconds can be noticed in the execution time of each CLOCK_TIMESTAMP.

 **How to Pause Query Execution pg_sleep_until() Function?**

Postgres pg_sleep until() function accepts a sleep time as an argument and puts the query execution on sleep until the wake-up time reaches:
    
    
    SELECT CLOCK_TIMESTAMP(),
    pg_sleep_until('11:59:02.1234'),
    CLOCK_TIMESTAMP();

The output shows that the query’s execution resumes when the pg_sleep_until() reaches the specified time.

 **How to Pause Query Execution pg_sleep_for() Function?**

The pg_sleep_for() function accepts an interval as an argument and delays the query’s execution based on the specified interval. It is used to put larger delays between the query’s execution:
    
    
    SELECT CLOCK_TIMESTAMP(),
    pg_sleep_for('1 minute 05 seconds'),
    CLOCK_TIMESTAMP(),
    pg_sleep_for('1 minute 05 seconds'),
    CLOCK_TIMESTAMP();

This way, you can specify the larger delays between the query execution using the pg_sleep_for() function.

 **Conclusion**

In PostgreSQL, various in-built functions are used to pause or delay the query’s execution for a specific period. For example, the pg_sleep(), pg_sleep_until(), and pg_sleep_for() are frequently used functions that allow us to pause the query’s execution halfway. The pg_sleep_for() function is used to put larger delays between the query’s execution. This post has shown various methods to pause the query execution in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-pause-query-execution-in-postgresql/)

---

# How to Get Query Results as a Comma Separated List in PostgreSQL

> The PostgreSQL users can transform a string or a query result into a comma-separated list using a built-in aggregate function named STRING_AGG().

In databases, users may encounter a situation where query’s each value is supposed to be output in a single row with a specific delimiter. For this purpose, the Postgres **STRING_AGG()** function can be utilized. The PostgreSQL users can transform a string or a query result into a comma-separated list using a built-in aggregate function named STRING_AGG().

This post will demonstrate how to get query results as a Comma Separated List in Postgres.

 **How to Get Query Results as a Comma-Separated List in PostgreSQL?**

To get the query results as a comma-separated list, all you need to do is pass the query to be aggregated as an argument to the STRING_AGG() function. Moreover, you are also required to specify the delimiter or separator:
    
    
    STRING_AGG(expression, separator);

The expression can be a table column while the separator can be anything like a string, character, or symbol.

 **Example1: Getting Query Result as a List of Comma-Separated Values**

We have a sample table named “product_details” with the following records:
    
    
    SELECT * FROM product_details;

Now, we will execute the SELECT query with the STRING_AGG() function to get the query result as a comma-separated list:
    
    
    SELECT STRING_AGG(pro_name, ',') AS products
    FROM product_details;

The above snippet depicts that the query results have been successfully retrieved as a comma-separated list.

 **Example2: Grouping Query Result as a List of Comma-Separated Values**

Mostly, the STRING_AGG() function is used with the GROUP BY clause to group the query result as a comma-separated list:
    
    
    SELECT pro_quantity, STRING_AGG(pro_name, ',') AS products
    FROM product_details
    GROUP BY pro_quantity;

The output shows that the products are grouped based on the “pro_quantity” column and each group contains a list of comma-separated products.

That was all about getting the query results as a comma-separated list in Postgres.

 **Conclusion**

The PostgreSQL users can transform a string or a query result into a comma-separated list using a built-in aggregate function named **STRING_AGG()**. For this purpose, all you need to do is pass the query to be aggregated as a first argument and a delimiter as a second argument to the STRING_AGG() function. This post has explained a detailed procedure for getting the results as a comma-separated list in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-query-results-as-a-comma-separated-list-in-postgresql/)

---

# What are the Steps to Restart the PostgreSQL Server on CentOS 7

> To restart the PostgreSQL server on CentOS 7, execute the “sudo systemctl restart postgresql” command. It is recommended to periodically restart the PostgreSQL…

PostgreSQL is a popular DBMS that is widely utilized for its scalability and robustness. To keep the PostgreSQL server running smoothly, it may be necessary to restart it periodically. Restarting the PostgreSQL server on CentOS 7 is a straightforward process that can be accomplished through the command line interface.

This article will illustrate the steps to successfully restart the PostgreSQL server on CentOS 7.

 **What are the Steps to Restart the PostgreSQL Server on CentOS 7?**

Here are the detailed steps to restart the PostgreSQL server on CentOS 7:

 **Step 1: Check PostgreSQL Status**

The first step is to evaluate the actual status of the PostgreSQL server to ensure it is running or not. To do so, execute the below script in the terminal:
    
    
    $ sudo systemctl status postgresql

If the output shows that the PostgreSQL service is active and running, then users can proceed to the next step. If it is inactive or not running, users need to start it first using the command:
    
    
    $ sudo systemctl start postgresql

 **Step 2: Stop PostgreSQL Server**

Before restarting the PostgreSQL server, it is necessary to stop it first. For instance, execute the below script in the terminal:
    
    
    $ sudo systemctl stop postgresql

 **Step 3: Restart PostgreSQL Server**

Now that the PostgreSQL server is stopped, users can restart it utilizing the below script:
    
    
    $ sudo systemctl restart postgresql

This will initiate the restart process for the PostgreSQL server.

 **Step 4: Verify PostgreSQL Status**

After restarting the PostgreSQL server, users should verify that it has started successfully. For instance, execute the below script in the terminal:
    
    
    $ sudo systemctl status postgresql

The above figure shows that the service of PostgreSQL is running.

 **Step 5: Start PostgreSQL Server**

Finally, if the PostgreSQL server was not running prior to the restart, users can start it using the following command:
    
    
    $ sudo systemctl start postgresql

This ensures that the PostgreSQL is in a running state and ready to accept connections.

 **Conclusion**

To restart the PostgreSQL server on CentOS 7, execute the “ **sudo systemctl restart postgresql** ” command. By stopping and restarting the PostgreSQL service, users can ensure that the server is running smoothly and ready to accept connections. It is recommended to periodically restart the PostgreSQL server to prevent any issues that may arise from long periods of continuous operation. With the steps outlined in this guide, users can easily restart the PostgreSQL server on CentOS 7 and keep the database running at optimal performance.

---
[View this page online](https://www.commandprompt.com/education/what-are-the-steps-to-restart-the-postgresql-server-on-centos-7/)

---

# How to Create Updatable Views in PostgreSQL

> Any view that has at least one updatable column is referred to as an updatable view. An updatable view can have updatable as well as non-updatable columns.

In Postgres, a view is a virtual table that can represent a subset of an ordinary table. It can be created based on a single or multiple tables. Views can be updatable or non-updatable. In Postgres, a view is referred to as an updatable view if it has at least one updatable column. Users can modify the records of original/base tables using updatable views.

This post will explain how to create and use an updatable view in Postgres using suitable examples.

 **How to Create Updatable Views in Postgres?**

Any view that has at least one updatable column is referred to as an updatable view. Users must follow the following rules to create an updatable view in Postgres:

\- An updatable view can have updatable as well as non-updatable columns. However, Non-updatable columns cannot be altered by users; if they attempt to, Postgres will issue an error.  
\- Users must specify only one table or an updatable view in the FROM clause of a query for a specific view.  
\- Users can’t specify a window, aggregate, or set-returning function in the selection list of a view.  
\- Users can’t specify the clauses like LIMIT, GROUP BY, OFFSET, HAVING, UNION, EXCEPT, INTERSECT, DISTINCT, and WITH at the top level.  
\- The view's invisible rows(rows that don’t meet the criteria specified in the WHERE clause) can also be modified. However, this rule can be bypassed by using the CHECK OPTION when defining the view.

 **Syntax**

Utilize the following syntax to create an updatable view in Postgres:
    
    
    CREATE OR REPLACE VIEW view_name AS
    SELECT col_list
    FROM tab_name
    WHERE [condition];

The above query will create a new updatable view based on the specified table.

 **Example 1: Creating an Updatable View**

We have created a sample table with the following records:

Suppose we want to create an updatable view based on the “employee_tab” view. To do this, we will use the following query:
    
    
    CREATE OR REPLACE VIEW employee_view AS
    SELECT id, emp_name,emp_age 
    FROM employee_tab
    WHERE emp_age <= 30;

Use the “SELECT” query to fetch the data from the newly created view:
    
    
    SELECT * FROM employee_view;

All those employees with ages less than are equal to 30 are inserted into the “employee_view”. Let’s update the view by inserting a new record into it:
    
    
    INSERT INTO employee_view(id, emp_name, emp_age)
    VALUES (14, 'Joe', 26 );

The view has been successfully modified. You check the updated/inserted record using the following query:
    
    
    SELECT * FROM employee_view;

The output proves that the insert operation is successfully performed on the given updatable view. The above-applied modifications will also be made to the base table since the given view is updatable. You can confirm the modification in the base table by executing the following command:
    
    
    SELECT * FROM employee_tab;

From the output, you can observe that the base table has also been updated.

 **Conclusion**

Any view that has at least one updatable column is referred to as an updatable view. An updatable view can have updatable as well as non-updatable columns. However, Non-updatable columns cannot be altered by users; if they attempt to, Postgres will issue an error. Moreover, users must specify only one table or an updatable view in the FROM clause of the view’s defining query. This post has illustrated a detailed procedure to create and use an updatable view in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-updatable-views-in-postgresql/)

---

# How to Create an Auto-increment Column Using SEQUENCES in PostgreSQL

> In PostgreSQL, a sequence can be linked with a table’s column to create an auto-incremented column. For this, use the “CREATE SEQUENCE” command along with the …

In PostgreSQL, sequences are a popularly used concept that allows users to generate a series of unique integers. Sequences can be created using a **CREATE SEQUENCE** command. The stated command can accept a variety of options such as START, INCREMENT, MINVALUE, CYCLE, etc. Using these options a user can create a customized sequence. Moreover, a sequence can be linked with a table’s column to create an auto-incremented column.

This post will explain how to use a SEQUENCE to create an auto-incremented column in Postgres.

 **How to Create an Auto-increment Column Using SEQUENCES in Postgres?**

In PostgreSQL, usually, a sudo data type named [SERIAL](<https://www.commandprompt.com/education/postgresql-serial-how-to-create-auto-increment-columns/>) is used to create an auto-incremented column. However, the same functionality can be achieved in a more effective manner by associating a sequence with a specific table’s column. Use the following syntax to create an auto-incremented column via a Postgres sequence:
    
    
    CREATE SEQUENCE seq_name
    OWNED BY tab_name.column;

Consider the following example to understand this concept in a better way.

 **Example: Creating an Auto-increment Column Using a SEQUENCE**

In the following code snippet, a table named “ **employee_tab** ” is created with the following columns: “id”, “emp_name”, and “emp_age”.
    
    
    CREATE TABLE employee_tab(
    id SMALLINT, 
    emp_name TEXT,
    emp_age SMALLINT
    );

Now create a sequence named “ **employee_seq** ” and associate it with the “ **employee_tab** ” table:
    
    
    CREATE SEQUENCE employee_seq
    START 11
    INCREMENT 2
    MINVALUE 10
    OWNED BY employee_tab.id;

In the above query, START, INCREMENT, and MINVALUE options are used to specify the starting value, increment value, and minimum value of the sequence. Lastly, the OWNED BY clause is used to associate the “employee_seq” sequence with the “id” column of the “employee_tab” table:

The sequence has been successfully created and associated with the “employee_tab” table. Now, execute the following query to insert the data into the “employee_tab” table:
    
    
    INSERT INTO employee_tab(id, emp_name, emp_age)
    VALUES (nextval('employee_seq'), 'Dean', 35),
    (nextval('employee_seq'), 'Joseph', 29),
    (nextval('employee_seq'), 'Tim', 25);

Here we utilized the “nextval()” function along with the INSERT statement to get the value from the “employee_seq” sequence and insert it into the “employee_tab” table:

The output verifies that the specified rows have been added to the “employee_tab” table. Now, we will utilize the SELECT query to populate all the data of the selected table:
    
    
    SELECT * FROM employee_tab;

That was all about creating an auto-incremented column using a Postgres SEQUENCE.

 **Conclusion**

In PostgreSQL, a sequence can be linked with a table’s column to create an auto-incremented column. For this purpose, use the “CREATE SEQUENCE” command along with the “OWNED BY” clause. Using this command users can create a customized sequence. This post has explained a detailed procedure for creating an auto-incremented column using a Postgres sequence.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-an-auto-increment-column-using-sequences-in-postgresql/)

---

# How to Use ALTER SEQUENCE Command in PostgreSQL

> In PostgreSQL, the ALTER SEQUENCE command allows us to alter the defined parameters of an already existing sequence.

In Postgres, sequences are used to create the auto-incremented integers. A sequence can be created with various parameters using the CREATE SEQUENCE statement. These parameters include the START, MINVALUE, INCREMENT, CYCLE, and so on. All these parameters define the behavior of a sequence and are used/set at the time of the sequence creation. However, Postgres allows us to modify the parameters of an already created sequence using the **ALTER SEQUENCE** statement.

This post will explain the use of the ALTER SEQUENCE statement in PostgreSQL using relevant examples.

 **How to Use ALTER SEQUENCE Command in PostgreSQL?**

In PostgreSQL, the **ALTER SEQUENCE** command allows us to alter the defined parameters of an already existing sequence. To use the ALTER SEQUENCE statement in Postgres, users are advised to follow the provided syntax:
    
    
    ALTER SEQUENCE seq_name
    parameter_name value;

 **Example 1: Alter Sequence Maximum Value**

Let’s use the “ **\ds** ” command to get the list of available sequences:
    
    
    \ds;

Suppose we want to alter the “example_1” sequence. For this purpose, first, we will see the structure of the selected sequence using the following command:
    
    
    \d example_1;

Suppose we want to change the value of the maximum parameter from “60” to “100”. For this, we will use the ALTER SEQUENCE command as follows:
    
    
    ALTER SEQUENCE example_1
    MAXVALUE 100;

Let’s describe the structure of the selected sequence using the following command:
    
    
    \d example_1;

The output shows that the selected sequence has been altered successfully.

 **Example 2: Alter Sequence Start Value**

Let’s execute the ALTER SEQUENCE command one more time to modify the sequence start value from “40” to “10”:
    
    
    ALTER SEQUENCE example_1
    START 10;

Let’s confirm the sequence altered parameter using the following command:
    
    
    \d example_1;

 **Example 3: Restart a Sequence**

Users can restart a sequence using the ALTER SEQUENCE statement. To do that, first, let’s fetch the sequence data using the following command:
    
    
    SELECT * FROM author_info_author_id_seq;

Now utilize the ALTER SEQUENCE statement with the RESTART parameter to set the restart value of the sequence:
    
    
    ALTER SEQUENCE author_info_author_id_seq
    RESTART WITH 1;

Now run the “SELECT *” command to fetch the sequence data:
    
    
    SELECT * FROM author_info_author_id_seq;

That was all about the use of the “ALTER SEQUENCE” statement in PostgreSQL.

 **Conclusion**

In PostgreSQL, the **ALTER SEQUENCE** command allows us to alter the defined parameters of an already existing sequence. Using the ALTER SEQUENCE statement, users can modify the value of any sequence parameter such as START, MINVALUE, INCREMENT, CYCLE, and so on. This article has provided a thorough guide on how to use the ALTER SEQUENCE statement in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-alter-sequence-command-in-postgresql/)

---

# How to Fix Sequence “START Value can’t be Greater Than MAXVALUE” Error in PostgreSQL

> “START Value can’t be Greater Than MAXVALUE” error occurs because of two reasons: if the start value is greater than the maximum value or if the user specified…

Sequences are a widely used concept in PostgreSQL that allows us to create a unique series of integers. For this purpose, the **CREATE SEQUENCE** command is used in Postgres. The stated command supports various options, such as **START** , **INCREMENT** , **MAXVALUE** , etc. to specify the starting value, increment value, maximum value, etc. However, these options must be used carefully, otherwise, users may face undesired consequences.

This post will explain what are the possible reasons and suitable solutions for the “START Value can’t be Greater Than MAXVALUE” Error in PostgreSQL.

 **How to Fix Sequence “START Value can’t be Greater Than MAXVALUE” Error in Postgres?**

While working with Postgres sequences, users may encounter the “START Value can’t be Greater Than MAXVALUE” error. It may be because of various reasons.

The possible reasons and respective solutions are described below:

 **Reason 1: Start Value is Greater Than the Maximum Value**

At the time of sequence creation, the user specified a start value greater than the maximum value:
    
    
    CREATE SEQUENCE example_1
    INCREMENT 2
    START 50
    MAXVALUE 40;

In the above code snippet, the **MAXVALUE** is less than the start value, as a result, we will encounter an error stating that the start value can’t be greater than the maximum value:

 **Solution 1: Modify the Value of START and MAXVALUE Options**

Make sure that the value of the “ **START** ” option is less than the “ **MAXVALUE** ” option. For example, to fix the stated error, we specify the value of the **START** option as less than the value of the **MAXVALUE** option:
    
    
    CREATE SEQUENCE example_1
    INCREMENT 2
    START 40
    MAXVALUE 60;

The error-free output indicates that the sequence has been successfully created.

 **Reason 2: Out of the Range Value**

Specifying a value out of the range of the specified data type may also cause the stated problem. Consider the following snippet for a better understanding of this concept:
    
    
    CREATE SEQUENCE example_1 AS SMALLINT
    START 72000;

In the above code snippet, we created a sequence with the **SMALLINT** data type and set its initial value as “72000”, which is out of the range of the specified data type. Consequently, we will get the following result:

 **Solution 2: Use the Appropriate Data Type**

Use an alternate data type that has a greater range or specify a value within the range of the specified data type. An example of fixing the stated error is provided in the following snippet:
    
    
    CREATE SEQUENCE example_1 AS INTEGER
    START 72000;

The value “72000” lies within the range of the “ **INT** ” data type. So, executing the above query will produce the following result:

The output shows that the sequence has been successfully created without causing any errors.

 **Conclusion**

In Postgres, the “START Value can’t be Greater Than MAXVALUE” error occurs because of two reasons: if the start value is greater than the maximum value or if the user specified an out-of-the-range value. To fix the stated error, make sure that the value of the “ **START** ” option is less than the value of the “ **MAXVALUE** ” option. This post has explained a couple of fixes to rectify the “START Value can’t be Greater Than MAXVALUE” error in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-sequence-start-value-cant-be-greater-than-maxvalue-error-in-postgresql/)

---

# How Do I List Sequences in PostgreSQL

> In PostgreSQL, the “\ds” command, “information_schema”, and “pg_class” catalog are used to get the list of available sequences.

A sequence in Postgres is nothing more than an ordered list of integers. In databases, sequences are used to generate a sequence/series of numeric values. However, while working with databases, developers may encounter a situation where they need to get the list of available sequences. For this purpose, Postgres supports various approaches, such as the “ **\ds** ” command, “ **information_schema** ”, etc.

This blog post will explain how to show the list of available sequences in Postgres:

\- Using \ds Command  
\- Using information_schema  
\- Using pg_class

Let’s begin with the “\ds” command.

 **How Do I List Sequences in Postgres Using \ds Command?**

“ **\ds** ” is a psql supported command that helps us get the list of available sequences:
    
    
    \ds

The output shows the list of sequences containing sequence name, schema name, and owner.

 **How Do I List Sequences in Postgres Using information_schema?**

In PostgreSQL, the “information_schema” is an inbuilt schema that assists us in getting information regarding database objects. The “information_schema” can be utilized with the “sequences” view to get the list of available sequences:
    
    
    SELECT sequence_name
    FROM information_schema.sequences;

Here, “sequence_name” is a column that keeps the names of available sequences:

The output shows that the information_schema retrieves the list of available sequences. Moreover, you can specify the column names like “start_value”, “minimum_value”, and “maximum_value” to get additional information like the sequence’s start value, minimum value, maximum value, etc.

 **How Do I List Sequences in Postgres Using pg_class?**

The " **pg_class** " catalog, which stores the information about the database objects, can also be used to find the list of available sequences:
    
    
    SELECT relname
    FROM pg_class
    WHERE relkind = 'S';

The above-stated command will retrieve all the sequences available in the current database:

The output proved that the “pg_class” has successfully retrieved the list of available sequences.

 **Conclusion**

In PostgreSQL, the “ **\ds** ” command, “ **information_schema** ”, and “ **pg_class** ” catalog are used to get the list of available sequences. The “\ds” can only be executed from the psql, however, the “pg_class” catalog and “information_schema” can be used along with the SELECT statement from any interface/tool like pgAdmin, psql, etc. This post has discussed various ways to get the list of available sequences in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-list-sequences-in-postgresql/)

---

# How to Update a View in PostgreSQL?

> In PostgreSQL, an already created view can be altered by utilizing the UPDATE query followed by the view name and then specifying the column to be updated in t…

In PostgreSQL, a view is a named query that helps us manipulate and retrieve data quickly. It can be created based on single or multiple tables. Views are helpful for wrapping a complex query, retrieving data quickly, etc. In Postgres, a new view can be created using the CREATE VIEW statement while an already created view can be updated using the UPDATE command.

This post will illustrate a practical guide on updating a View in PostgreSQL.

 **How to Update a View in Postgres?**

Postgres UPDATE query can be utilized to modify or alter an updatable view. More specifically, you need to use the UPDATE query followed by the view name and then specify the column to be updated in the SET clause:
    
    
    UPDATE view_name
    SET col_name = modified_value;

Follow the provided steps to learn how to update a Postgres view:

 **Step 1: Sample Table**

We have created a sample table with the following records:

 **Step 2: Create a View**

Use the below query to define a new view based on the “employee_tab” table:
    
    
    CREATE OR REPLACE VIEW employee_view_1 AS
    SELECT id, emp_name,emp_age 
    FROM employee_tab;

Use the “SELECT” query to fetch the data from the newly created view:
    
    
    SELECT * FROM employee_view;

 **Step 3: Update View**

Use the update query along with the SET clause to update the “employee_view_1”:
    
    
    UPDATE employee_view_1
    SET emp_age = 25;

 **Step 4: Verify Updated Data**

Let’s fetch the view’s data using the following “SELECT” command:
    
    
    SELECT * FROM employee_view_1;

The output snippet authenticates that the given view has been updated.

 **Conclusion**

In PostgreSQL, an already created view can be altered or updated using the UPDATE command. For this purpose, you need to utilize the UPDATE query followed by the view name and then specify the column to be updated in the SET clause. This post has illustrated the step-by-step guide on how to update a view in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-update-a-view-in-postgresql/)

---

# How to Sort a Table by Month Name in PostgreSQL

> To sort a table by month name use the ORDER BY clause alongside the EXTRACT() and TO_DATE() functions. &#x27;Month&#x27; must be specified as an argument to the EXTRACT(…

PostgreSQL offers an **ORDER BY** clause that helps us sort a table ascendingly or descendingly. It sorts the table based on a specific column or multiple columns. However, when it comes to sorting a table by month name, the ORDER BY clause doesn’t provide the expected results. This is because the ORDER BY clause treats the month name as a string, so it sorts the month name alphabetically instead of sorting it in proper month ordering/numbering.

This write-up will illustrate a detailed procedure to sort a table by month name in Postgres.

 **How to Sort a Table By Month Name in Postgres?**

We all know that the “N” comes before “O”, however, the “November” comes after “October”. So, using a simple ORDER BY clause will sort the month names alphabetically. This means the ORDER BY clause will sort November before October, April before January, and so on. So how to tackle such issues?

Well! In Postgres, to sort a table by month name, the **ORDER BY** clause is used alongside the **EXTRACT()** and **TO_DATE()** functions. Moreover, 'Month' must be used as an argument to the EXTRACT() and TO_DATE() functions. Here is a simple syntax to order the table’s data by month name:
    
    
    SELECT col_list
    FROM tab_name
    ORDER BY EXTRACT(MONTH FROM TO_DATE(col_name, 'Month'));

In the above syntax:

\- The TO_DATE() function will convert the month name to the respective date(i.e. Equivalent month number).  
\- Next, the EXTRACT() function will extract/pull the month from the converted date value.  
\- Finally, the ORDER BY clause will sort the table’s data into ascending/descending order based on the extracted month.

You can also use the “DESC” option to sort the table’s data from higher month to lower month.

 **Example: Sort Table By Month**

Follow the given instructions to sort the table by month in ascending or descending order:

 **Step 1: Sample Table**

Execute the provided command to populate all the data of the “emp_dat” table:
    
    
    SELECT * FROM emp_dat;

The above table maintains the default insertion order.

 **Step 2: Sort By Month Name in Ascending Order**

Use the below SELECT command to sort the table’s data with respect to the month name:
    
    
    SELECT *
    FROM emp_dat
    ORDER BY EXTRACT(MONTH FROM TO_DATE(joining_month, 'Month'));

From the above snippet, you can observe that the table’s data has been successfully sorted(ascendingly) according to the month's name.

 **Step 3: Sort By Month Name in Descending Order**

Use the DESC option to sort the table in descending format:
    
    
    SELECT *
    FROM emp_dat
    ORDER BY EXTRACT(MONTH FROM TO_DATE(joining_month, 'Month')) DESC;

From the above result set, you can clearly notice that the table’s data has been successfully sorted (descendingly) according to the month name.

 **Conclusion**

To sort a table by month name use the ORDER BY clause alongside the EXTRACT() and TO_DATE() functions. 'Month' must be specified as an argument to the EXTRACT() and TO_DATE() functions. The “ASC” or “DESC” options can be utilized to sort the table’s data ascendingly or descendingly. This post has demonstrated a detailed procedure to sort a table by month name in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-sort-a-table-by-month-name-in-postgresql/)

---

# How to Use UPDATE RETURNING Clause in PostgreSQL

> In PostgreSQL, the UPDATE RETURNING clause not only updates the selected rows but also retrieves the modified rows.

In PostgreSQL, the UPDATE query is used to update specific or all records of a table. Once the query is executed successfully, the user can confirm the updated records using the SELECT command. However, Postgres offers an **UPDATE RETURNING** clause that extends the functionalities of the standard UPDATE command and can be used to get the updated records.

This write-up will discuss what is UPDATE RETURNING and how to use it in PostgreSQL.

 **How to Use the UPDATE RETURNING Clause in PostgreSQL?**

In PostgreSQL, the UPDATE RETURNING clause not only updates the selected rows but also retrieves the updated rows. The basic syntax of using the UPDATE RETURNING clause is illustrated in the below snippet:
    
    
    UPDATE tab_name
    SET col_name = val
    WHERE condition
    RETURNING *;

Here in the above syntax, the “RETURNING *” signifies that all the updated records will be retrieved on successful execution of the “UPDATE RETURNING” clause.

 **Example 1: How to Retrieve All Updated Records in Postgres?**

Suppose we have a table named “emp_data” that contains the following records:
    
    
    SELECT * FROM emp_data;

Suppose the user wants to update the joining date of all those employees whose id is greater than or equal to five. Also, the user wants to retrieve the updated records so that he can confirm the modified records. Both these functionalities can be achieved using a single “UPDATE RETURNING” clause as follows:
    
    
    UPDATE emp_data
    SET joining_date = CURRENT_DATE
    WHERE id >= 5
    RETURNING *;

In the above snippet, the CURRENT_DATE function is used within the UPDATE command to set today’s date as the joining date of employees whose id is greater than or equal to 5:

The output shows that the UPDATE RETURNING clause has successfully updated and retrieved the selected records.

 **Example 2:** **How to Retrieve Only Specific Columns From the Updated Records in Postgres?**

The UPDATE RETURNING clause can be used to modify the selected records and retrieve only specific columns:
    
    
    UPDATE emp_data
    SET joining_date = CURRENT_DATE
    WHERE emp_id = 4
    RETURNING emp_name;

The above-stated query will update all those employees that fulfill the described condition. However, instead of returning all columns, the RETURNING clause will retrieve only the employee names from the “emp_name” column:

That was all about the use of the UPDATE RETURNING clause in Postgres.

 **Conclusion**

In PostgreSQL, the **UPDATE RETURNING** clause not only updates the selected rows but also retrieves the modified rows. It saves a lot of time for the user as it modifies and retrieves the selected rows in one go. The UPDATE RETURNING clause can also be used to update the selected records and retrieve only specific columns. This post has explained the use of the UPDATE RETURNING clause in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-update-returning-clause-in-postgresql/)

---

# How to Drop a Sequence in PostgreSQL

> To remove a Postgres sequence, execute the “DROP SEQUENCE” command followed by the sequence name to be dropped.

A sequence in Postgres is nothing more than a database object that generates an ordered list of integers. In Postgres, sequences can be created using a “ **CREATE SEQUENCE** ” command. However, when a sequence is no longer needed it can be dropped/removed from the database using a “ **DROP SEQUENCE** ” command. Sequences that are linked to a table's column will be automatically removed/dropped when the table or even if that particular column is removed.

This post will explain how to drop single or multiple sequences using suitable examples.

 **How to Drop a Sequence in PostgreSQL?**

To drop single or multiple sequences in Postgres, use the **DROP SEQUENCE** command. To remove a single Postgres sequence, execute the “ **DROP SEQUENCE** ” command followed by the sequence name to be dropped:
    
    
    DROP SEQUENCE [IF EXISTS] seq_name
    [CASCADE | RESTRICT];

Here in the above syntax:

\- The “IF EXISTS”, “CASCADE” and “RESTRICT” are optional features that are used with the DROP SEQUENCE statement to fulfill different tasks.  
\- For instance, "IF EXISTS" checks if the sequence to be dropped exists, then drops it if it does. While the CASCADE allows the users to delete the database objects that are dependent on a particular sequence.

Execute the “ **DROP SEQUENCE** ” command with the comma-separated syntax to drop multiple Postgres sequences:
    
    
    DROP SEQUENCE seq_name_1, seq_name_2, …;

Let’s head towards examples for a profound understanding of the “DROP SEQUENCE” command.

 **Example 1: How to Drop a Single Sequence in Postgres?**

Before dropping a sequence, first, let’s check the list of available sequences using the following “\ds” command:
    
    
    \ds

Suppose we want to drop a sequence named “std_seq”, for this, we will execute the DROP SEQUENCE command as follows:
    
    
    DROP SEQUENCE std_seq;

The output indicates that the selected sequence has been dropped successfully. You can confirm the sequence’s deletion by executing the following command:
    
    
    \ds;

The output snippet proves that the “std_seq” doesn’t exist in the list of available sequences.

 **Example 2: How to Drop Multiple Sequences in Postgres?**

In the following example, we will use the **DROP SEQUENCE** command to drop more than one sequence:
    
    
    DROP SEQUENCE example_seqence, example_seqence_1;

Let’s verify the sequences’ deletion by executing the “ **\ds** ” command:
    
    
    \ds;

The output demonstrates that the selected sequences have been removed from the list of available sequences.

 **Conclusion**

To drop single or multiple sequences in Postgres, use the **DROP SEQUENCE** command. To remove a single Postgres sequence, execute the “DROP SEQUENCE” command followed by the sequence name to be dropped. Execute the stated command with the comma-separated syntax to drop multiple sequences in one go. This post has demonstrated various use cases of the **DROP SEQUENCE** command in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-sequence-in-postgresql/)

---

# How to List Constraints of a Table in PostgreSQL?

> In PostgreSQL, the “\d” command and “pg_catalog” schema with the “pg_constraint” and “pg_class” views are used to get the list of table constraints.

PostgreSQL is a popularly used open-source relational database that allows us to specify a set of rules on the table’s data. These rules can be added to a table using various **CONSTRAINTS** , such as **PRIMARY KEY** , **FOREIGN KEY** , **UNIQUE** , etc. Using these constraints users can insert the restricted data into tables. Therefore, for better data manipulation, users are required to get the list of available table constraints. To do that, various approaches are used in Postgres.

This blog post will explain how to list table constraints in Postgres using:

\- \d Command  
\- pg_catalog

So, let’s get started with the “\d” command.

 **How to Find Table Constraints in Postgres Using \d Command?**

“\d” is a metadata command that must be executed from the SQL Shell. It helps us describe the table’s structure including the column names, data types, constraints, and so on. The stated command has a very simple syntax as depicted in the following snippet:
    
    
    \d tab_name;

From the syntax, you can observe that the stated command must be followed by the table’s name.

 **Example: Finding Table Constraints Using the “\d” Command**

Use the “\d” command along with the table name to list the table constraints:
    
    
    \d employee_information;

The output shows that the “employee_information” table has a primary key named “employee_info_pkey”.

 **How to Find Table Constraints in Postgres Using pg_catalog?**

In PostgreSQL, the “ **pg_catalog** ” schema can be used with the “ **pg_constraint** ” and “ **pg_class** ” views to get the list of table constraints. More specifically, join both views and utilize the “relname” column to specify the name of the selected table:
    
    
    SELECT conname AS constraint_name, 
    contype AS constraint_type
    FROM pg_catalog.pg_constraint cons
    JOIN pg_catalog.pg_class t ON t.oid = cons.conrelid
    WHERE t.relname ='employee_information';

The constraint type will be denoted by their initials, such as “p” representing the primary key constraint, “c” representing the check constraint, “f” denoting the foreign key constraint, and so on.

The output proves that the pg_catalog.pg_constraint successfully retrieves the constraint name and its respective type.

 **Conclusion**

In PostgreSQL, the “\d” command and “pg_catalog” schema are used to get the list of table constraints. The “\d” command must be used along with the table name to list the table constraints. While the “pg_catalog” schema can be used with the “pg_constraint” and “pg_class” views to get the list of table constraints. This blog has explained a couple of methods to list the table constraints in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-list-constraints-of-a-table-in-postgresql/)

---

# How to Select One Row From Each Group in PostgreSQL?

> In PostgreSQL, the “SELECT DISTINCT ON” statement is used to select one row per group. The stated command selects and retrieves a random row from each group.

While working with databases, users often come across a situation where they need to select one row from each group. PostgreSQL provides a “ **SELECT DISTINCT ON** ” statement to deal with such scenarios. Using this statement, users can get a random row, or a specific row, from each group,

This post will walk you through the practical usage of the SELECT DISTINCT ON statement in PostgreSQL.

 **How to Select One Row From Each Group in PostgreSQL?**

Use the Postgres’ “ **SELECT DISTINCT ON** ” statement to select one row per group. The stated statement selects and retrieves a random row from each group. However, the ORDER BY clause can be utilized along with the “SELECT DISTINCT ON” statement to get a specific row from each group. The syntax to use the stated command is demonstrated in the following snippet:
    
    
    SELECT DISTINCT ON (col_name)
    FROM tab_name
    ORDER BY col_name ASC|DESC;

You can specify single or multiple columns in the SELECT DISTINCT ON statement.

 **Example: How to Use the SELECT DISTINCT ON Statement in Postgres?**

In this example, we will utilize a sample table name “emp_info” that we have already created with the following records:
    
    
    SELECT * FROM emp_info
    ORDER BY emp_id;

Let’s suppose we want to select only one employee for each joining_date. For this purpose, we will utilize the following query:
    
    
    SELECT DISTINCT ON (joining_date) joining_date, emp_id, emp_name
    FROM emp_info;

The output proves that a random employee is selected for each joining date. Use the SELECT DISTINCT ON statement with the ORDER BY clause to select a specific employee from each group:
    
    
    SELECT DISTINCT ON (joining_date) joining_date, emp_id, emp_name
    FROM emp_info
    ORDER BY joining_date, emp_id ASC;

The above query will select one row from each group but this time the employees will be selected from each group based on their ids:

That was all about selecting one row from each group in Postgres.

 **Conclusion**

In PostgreSQL, the “ **SELECT DISTINCT ON** ” statement is used to select one row per group. The stated command selects and retrieves a random row from each group. However, the ORDER BY clause can be utilized along with the “SELECT DISTINCT ON” statement to get a specific row from each group. This post has presented an in-depth overview of selecting one row from each group in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-select-one-row-from-each-group-in-postgresql/)

---

# How Do I Use FILTER Clause to Have Multiple Counts in PostgreSQL?

> In PostgreSQL, the FILTER clause can be used with the COUNT() function to do multiple counts on a particular table.

Postgres supports various aggregate functions such as COUNT(), AVG(), SUM(), etc. Among them, the most popularly used is the **COUNT()** function which counts the number of rows of a table. While the **FILTER** is a handy clause that can be used with the COUNT() function to do multiple counts on a particular table.

This article will teach you how to do multiple counts on a particular table using the FILTER clause.

 **How Do I Utilize the FILTER Clause to Do Multiple Counts in Postgres?**

In PostgreSQL, users can utilize the following syntax to do multiple counts on a specific table:
    
    
    SELECT COUNT(1),
    COUNT(1) FILTER (criteria_1),
    COUNT(1) FILTER (criteria_2),
    …
    FROM tab_name;

The **COUNT()** function will count the table rows based on the specified criteria.

 **Example: How to Use FILTER Clause With the COUNT() Function?**

In this example, we will utilize a sample table named “author_info” that we have already created with the following records:
    
    
    SELECT * FROM author_info
    ORDER BY author_id;

Suppose we want to do multiple counts on the “ **author_info** ” table. To do that, we will utilize the provided query:
    
    
    SELECT COUNT(1) AS total_authors,
    COUNT(1) FILTER (
    WHERE gender = 'M') AS male_authors,
    COUNT(1) FILTER (
    WHERE gender = 'F') AS female_authors
    FROM author_info;

Here in the above query:

\- The first COUNT() will count all authors from the given table.  
\- The second count will count only male authors.  
\- The final COUNT() will count only female authors.

That was all about using the FILTER clause to have multiple counts in Postgres.

 **Conclusion**

In PostgreSQL, the **FILTER** clause can be used with the COUNT() function to do multiple counts on a particular table. The **COUNT()** function will count the table rows based on the specified criteria. This article has explained the working of the COUNT() function along with the FILTER clause to do multiple counts on a specific Postgres table.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-use-filter-clause-to-have-multiple-counts-in-postgresql/)

---

# How Does the CONCAT_WS() Work in PostgreSQL

> The CONCAT_WS() is an inbuilt string function and an extended form of the CONCAT() function which allows the users to put a specific separator between the stri…

PostgreSQL offers a wide range of inbuilt string functions that allows us to work efficiently with string manipulation. In Postgres, the **CONCAT()** is a popularly used string function that combines multiple strings into one. It is executed without any separator, which means all the strings will be merged with each other. If a user desires to add a separator between the concatenated strings, then he can use the CONCAT_WS() function instead of the CONCAT() function.

This blog post is going to explain the use of the COCAT_WS() function along with suitable examples.

 **How Does the CONCAT_WS() Work in Postgres?**

The **CONCAT_WS()** is nothing more than an extended form of the CONCAT() function which allows the users to put a specific separator between the strings to be concatenated. Users must follow the provided syntax to utilize the CONCAT_WS() function in PostgreSQL:
    
    
    CONCAT_WS(sep, str_1, str_2,..., str_n);

Replace the “sep” argument with any symbol, character, string, etc. of your choice.

 **Example1: Concatenating Multiple Strings With a Specific Separator**

In the following example, we utilize the “-” symbol as a separator between the given strings:
    
    
    SELECT CONCAT_WS('-', 'Hello John', 'Welcome to the USA');

The output signifies that the given strings have been joined/concatenated using the “-” symbol.

 **Example2: How CONCAT() Differs From CONCAT_WS()?**

In this example, we will use the CONCAT() and CONCAT_WS() functions side-by-side to explain the difference between the stated functions:
    
    
    SELECT CONCAT('Hello John', 'Welcome to the USA'),
    CONCAT_WS('-', 'Hello John', 'Welcome to the USA');

The CONCAT() function combines the given values without any separator while the CONCAT_WS() function combines them according to the specified separator.

 **Example3: Concatenating Multiple Columns With a Specific Separator**

We have created a sample table named “emp_info” with the following data:
    
    
    SELECT * FROM emp_info
    ORDER BY emp_id;

Suppose we want to concatenate the table’s column with a specific string. We will utilize a string as a separator:
    
    
    SELECT CONCAT_WS(' Join on: ', emp_name, joining_date)
    FROM emp_info;

The output depicts that the string “join on:” has been successfully used as a separator between the concatenated columns.

 **Conclusion**

The **CONCAT_WS()** is an inbuilt string function and an extended form of the CONCAT() function which allows the users to put a specific separator between the strings to be concatenated. The “separator” can be any symbol, character, string, etc. The only difference between the CONCAT() and CONCAT_WS() is that the first one combines the given values without any separator while the other one combines them according to the specified separator. This post has presented an in-depth understanding of the CONCAT_WS() function.

---
[View this page online](https://www.commandprompt.com/education/how-does-the-concat_ws-work-in-postgresql/)

---

# How to Get the Age in Years in PostgreSQL

> In PostgreSQL, the AGE() function must be used with the DATE_PART() or the EXTRACT() function to get the age in years.

In PostgreSQL, the **AGE()** function is used to get the age or date difference based on the specified dates. The stated functions retrieve the age as an interval. This works okay until unless you only want the age to be returned in years. However, if you have to get the age in years instead of the whole interval, then the AGE() function must be used with the DATE_PART() or the EXTRACT() function.

This blog will present a profound understanding of getting the age in years in Postgres.

 **How to Get the Age in Years in Postgres?**

The DATE_PART() and EXTRACT() functions are used to get a specific date field such as a year, month, etc. Therefore, both these functions can be used with the AGE() function to extract the year from the returned value of the AGE() function. Utilize the below syntax to get the age in years:
    
    
    SELECT DATE_PART('YEAR', AGE(First_DATE, Second_DATE));

Specify the date values to the AGE() function to get the age as an interval. After that, the DATE_PART() function will extract the year from the interval retrieved by the AGE() function.

 **Example 1: Getting Age in Years Using DATE_PART() Function**

In the following snippet, we will utilize the AGE() function along with the DATE_PART() function to get the age in years:
    
    
    SELECT DATE_PART('YEAR', AGE(CURRENT_DATE, '1996-01-11'));

From the output, it can be clearly noticed that the age is retrieved in years.

 **Example 2: Getting Age in Years Using EXTRACT() Function**

Alternatively, the EXTRACT() function can be utilized with the AGE() function to get the age in years:
    
    
    SELECT EXTRACT('YEAR' FROM AGE('2020-01-01', '1996-01-11'));

The output shows that the use of the EXTRACT() function along with the AGE() function retrieves the desired results.

 **Example 3: Getting Age in Years From the Table’s Data**

Suppose we want to calculate the employees’ experience in years. To do that, we can utilize the AGE() function along with the EXTRACT() or DATE_PART() functions. We will pass the targeted date column and CURRENT_DATE() functions as arguments to the AGE() function:
    
    
    SELECT emp_name, joining_date,
    EXTRACT('YEAR' FROM AGE(CURRENT_DATE, joining_date)) AS experience
    FROM emp_info;

The output shows that the stated functions successfully retrieved the experience in years.

That was all about getting the age in years.

 **Conclusion**

In PostgreSQL, the **AGE()** function must be used with the **DATE_PART()** or the **EXTRACT()** function to get the age in years. The AGE() function retrieves the age as an interval while the DATE_PART() and EXTRACT() functions are used to get a specific date field such as a year, month, etc. AGE() retrieves an interval which is passed as an argument to the DATE_PART() or EXTRACT() function; the stated functions will extract the year from the interval retrieved by AGE(). This post has provided a thorough guide on getting age in years.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-age-in-years-in-postgresql/)

---

# How to Get the Year Month and Day From an INTERVAL in PostgreSQL

> In PostgreSQL, the DATE_PART() and EXTRACT() functions are used to get a specific date field such as a year, month, etc. from any date, timestamp, or interval.

Database users often encounter a situation where they need to fetch a specific field from an interval. This may be because of various reasons, such as calculating employees’ experience in years, months, etc., sorting table data based on a specific field, and so on. Postgres offers various inbuilt functions that can help us in such scenarios, such as DATE_PART() and EXTRACT().

This blog will present a profound understanding of getting days, months, and years from an interval in Postgres.

 **How to Get/Extract Years, Months, and Days From an INTERVAL in Postgres?**

The DATE_PART() and EXTRACT() functions are used to get a specific date field such as a year, month, etc. from any date, timestamp, or interval. Utilize the below syntax for the DATE_PART() function to get the days, months, or years from a given interval:
    
    
    DATE_PART('date_field', interval);

Specify the field to be extracted in place of “date_field”.

Alternatively, you can also use the EXTRACT() function with the following syntax to accomplish the same task:
    
    
    EXTRACT('date_field' FROM interval);

Let’s learn this concept using the following examples.

 **Example 1: Getting Years, Months, and Days From an INTERVAL Using DATE_PART() Function**

In the following snippet, we will utilize the **DATE_PART()** function on an interval to get days, months, and years fields from the given interval:
    
    
    SELECT DATE_PART('DAY', INTERVAL '10 year 6 month 15 day') AS days,
    DATE_PART('MONTH', INTERVAL '10 year 6 month 15 day') AS months,
    DATE_PART('YEAR', INTERVAL '10 year 6 month 15 day') AS years;

From the output, it can be clearly noticed that the desired date fields have been fetched from the given interval.

 **Example 2: Getting Years, Months, and Days From an INTERVAL Using EXTRACT() Function**

Alternatively, the EXTRACT() function can be utilized with the selected date fields to get the desired results:
    
    
    SELECT EXTRACT('DAY' FROM INTERVAL '1 year 2 month 15 days') AS days,
    EXTRACT('MONTH' FROM INTERVAL '10 year 4 month 15 day') AS months,
    EXTRACT('YEAR' FROM INTERVAL '10 year 6 months 15 day') AS years;

The output shows that the use of the EXTRACT() function retrieves the desired results.

 **Example 3: Getting Date Fields From the Table’s Data**

We have an “article_record” table that contains the following data:
    
    
    SELECT * FROM article_record;

Suppose we want to find the articles’ age in years, months, and days from the given interval. To do that, we can utilize the EXTRACT() or DATE_PART() function as follows:
    
    
    SELECT article_title, article_published,
    EXTRACT('YEAR' FROM article_published) AS year,
    EXTRACT('MONTH' FROM article_published) AS month,
    EXTRACT('DAY' FROM article_published) AS day
    FROM article_record;

Similarly, users can utilize the DATE_PART() function instead of the EXTRACT() function to get the same functionality.

 **Conclusion**

In PostgreSQL, the DATE_PART() and EXTRACT() functions are used to get a specific date field such as a year, month, etc. from any date, timestamp, or interval. Pass the desired date field and the interval as arguments to the EXTRACT() or DATE_PART() functions to get year, month, and day from the given interval. This post has provided a thorough guide on getting days, months, and years from a specific interval.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-year-month-and-day-from-an-interval-in-postgresql/)

---

# How to RESET a SEQUENCE in PostgreSQL?

> In PostgreSQL, the ALTER SEQUENCE command is used with the RESTART WITH clause to reset the value of a specific sequence.

In PostgreSQL, the sequences are used to auto-generate a series of unique integers. A common use case of sequences is creating auto-increment primary keys or table columns. While working with sequences a need of resetting or changing the sequence’s value may arise. To deal with such a situation the **ALTER SEQUENCE** command is executed with an optional “ **WITH RESTART** ” clause.

This blog will demonstrate how to reset a sequence in PostgreSQL using practical examples.

 **How to RESET a SEQUENCE in Postgres?**

In PostgreSQL, the “ALTER SEQUENCE RESTART WITH” command allows us to change or reset the value of any sequence. To do that, the below syntax is used in Postgres:
    
    
    ALTER SEQUENCE seq_name
    RESTART WITH new_value;

The above query will reset the sequence according to the value specified in place of the “new_value”.

 **Example: Resetting Sequence Value**

Follow the given stepwise instructions to reset a sequence in Postgres:

 **Step 1: List Sequences**

Let’s utilize the “ **\ds** ” command to get the list of available sequences:
    
    
    \ds;

Suppose we want to alter the “product_details_pro_id_seq” sequence.

 **Step 2: Fetch Sequence Data**

Let’s fetch the sequence data using the following “SELECT” command:
    
    
    SELECT * FROM product_details_pro_id_seq;

The above snippet indicates that the sequence current value is “14”.

 **Step 3: Reset Sequence**

Now utilize the ALTER SEQUENCE command with the RESTART WITH clause to reset the value of the sequence:
    
    
    ALTER SEQUENCE product_details_pro_id_seq
    RESTART WITH 100;

The ALTER SEQUENCE command is executed successfully.

 **Step 4: Verify Sequence Modification**

Execute the “SELECT *” command to fetch the sequence data:
    
    
    SELECT * FROM product_details_pro_id_seq;

The sequence value has been successfully reset to 100.

 **Conclusion**

In PostgreSQL, the ALTER SEQUENCE command is used with the RESTART WITH clause to reset the value of a specific sequence. Once the sequence is altered, you can run the “SELECT *” command followed by the sequence name to verify the altered parameters. This blog post has explained how to reset or restart a sequence in PostgreSQL using the ALTER SEQUENCE command.

---
[View this page online](https://www.commandprompt.com/education/how-to-reset-a-sequence-in-postgresql/)

---

# MySQL’s GROUP_CONCAT() Equivalent in PostgreSQL

> In PostgreSQL, the STRING_AGG() function can be utilized as an alternative to the MySQL&#x27;s GROUP_CONCAT() function.

In relational databases like MySQL, MariaDB, etc. the **GROUP_CONCAT()** function is used to concatenate the strings from a group to one string or multiple rows into a single field. Although PostgreSQL does not support the **GROUP_CONCAT()** function, the **STRING_AGG()** can be used to achieve similar functionality.

This blog post will present a complete guide on GROUP_CONCAT() equivalent in Postgres.

 **GROUP_CONCAT() Equivalent in Postgres**

In PostgreSQL, the STRING_AGG() function can be utilized as an alternative to the GROUP_CONCAT() function. The STRING_AGG() function accepts an expression or strings to be concatenated and a delimiter/separator as arguments and concatenates the given strings using the specified separator:
    
    
    SELECT STRING_AGG(expression, 'separator') 
    FROM tab_name;

Let’s directly dive into the examples to get a profound understanding of the STRING_AGG() function.

 **Example: MySQL’s GROUP_CONCAT() Equivalent in PostgreSQL**

In the following example, we will utilize the STRING_AGG() function on an already created table named “dpt_info”:
    
    
    SELECT * FROM dpt_info;

We will utilize the STRING_AGG() function on the dpt_name column to get the department names as a comma-separated list:
    
    
    SELECT STRING_AGG(dpt_name, ',')
    FROM dpt_info;

This is how the functionality of the GROUP_CONCAT() can be achieved using the STRING_AGG() in Postgres.

 **Note:** Visit the [following guide](<https://www.commandprompt.com/education/postgresql-string_agg-function-with-examples/>) for a profound understanding of the STRING_AGG() function.

 **Conclusion**

In PostgreSQL, the STRING_AGG() function can be utilized as an alternative to the GROUP_CONCAT() function. The STRING_AGG() function accepts an expression or strings to be concatenated as a first argument and a delimiter/separator as a second argument; as a result, it retrieves a concatenated list of strings separated by a specified delimiter. This post has demonstrated a detailed guide on GROUP_CONCAT() equivalent in Postgres.

---
[View this page online](https://www.commandprompt.com/education/mysqls-group_concat-equivalent-in-postgresql/)

---

# Find Maximum Values From a Row in PostgreSQL

> Use the MAX() function along with a subquery to find a row having a maximum value in a given column. Users must use the subquery along with the WHERE clause to…

In PostgreSQL, finding the minimum or maximum value from a column is a common task. The aggregate functions like MAX() and MIN() are used to get the greatest or least value from a column. However, finding a row that keeps the maximum value in a given column is a real deal. To do this, the subquery can be used with a WHERE clause.

This blog will demonstrate the complete process of finding a row having a maximum value in a given column.

 **Find Maximum Values From a Row in Postgres**

Use the MAX() function along with a subquery to find a row having a maximum value in a given column:
    
    
    SELECT col_list
    FROM tab_name
    WHERE col_name = (SELECT MAX(col_name) FROM tab_name);

Here in this syntax, the WHERE clause with a subquery is utilized to show only those rows that have maximum values in the given column.

 **Example: How to Get a Row Having a Maximum Value**

We have already created a sample table named “product_details” whose data is enlisted in the following snippet using the SELECT query:
    
    
    SELECT * FROM product_details;

Suppose we want to check which product has the maximum quantity left. For this purpose, we will execute the MAX() function with a subquery as follows:
    
    
    SELECT pro_id, pro_name, pro_price, pro_quantity
    FROM product_details
    WHERE pro_quantity = ( SELECT 
    MAX(pro_quantity) 
    FROM product_details);

In the above query:

\- A SELECT query is used to fetch all columns of the “product_details” table.  
\- A subquery is created within the WHERE clause to get only those rows that have the maximum/highest quantity.  
\- Within the subquery, the MAX() function is applied to the “pro_quantity” column to get the rows with maximum quantity.

The output shows that the rows with the maximum quantity have been successfully retrieved.

That’s all about finding the rows having maximum values in a specific column.

 **Conclusion**

Use the MAX() function along with a subquery to find a row having a maximum value in a given column. A subquery will retrieve only those rows that have the maximum numeric values. Moreover, users must use the subquery along with the WHERE clause to get the filtered result set. This blog post has presented a detailed understanding of getting the rows having maximum values in a specific column.

---
[View this page online](https://www.commandprompt.com/education/find-maximum-values-from-a-row-in-postgresql/)

---

# How to Sort a Table By Month in PostgreSQL

> Use the ORDER BY clause alongside the EXTRACT() function to sort a table by month. &#x27;Month&#x27; must be passed as an argument to the EXTRACT() function.

PostgreSQL supports an **ORDER BY** clause to sort a table ascendingly or descendingly. It sorts the table based on a specific column or multiple columns. However, the "ORDER BY" clause wouldn't be sufficient to sort the table's data by month; instead, it must be executed with the EXTRACT() function to achieve the desired functionality.

This write-up will illustrate a detailed procedure to sort a table by month in Postgres.

 **How to Sort a Table By Month in Postgres?**

To sort a table by month use the ORDER BY clause alongside the EXTRACT() function. 'Month' must be passed as an argument to the EXTRACT() function. Here is a simple syntax to order the table’s data by month:
    
    
    SELECT col_list
    FROM tab_name
    ORDER BY EXTRACT('Month' FROM date_val);

You can also use the “DESC” option to sort the table’s data from higher month to lower month.

 **Example: Sort Table By Month**

Follow the given instructions to sort the table by month in ascending or descending order:

 **Step 1: Sample Table**

Execute the provided command to populate the “emp_data” table:
    
    
    SELECT *
    FROM emp_data;

The above table maintains the default insertion order.

 **Step 2: Sort By Month Ascending Order**

Use the following SELECT statement to sort the table’s data with respect to the month specified:
    
    
    SELECT *
    FROM emp_data
    ORDER BY EXTRACT('Month' FROM joining_date);

From the above snippet, you can observe that the table’s data has been successfully sorted(ascendingly) according to the month specified in the joining_date column.

 **Step 3: Sort By Month Descending Order**

Use the DESC option to sort the table in descending form:
    
    
    SELECT *
    FROM emp_data
    ORDER BY EXTRACT('Month' FROM joining_date) DESC;

From the above result set, you can clearly notice that the table’s data has been successfully sorted(descendingly) according to the month specified in the joining_date column.

 **Conclusion**

Use the ORDER BY clause alongside the EXTRACT() function to sort a table by month. 'Month' must be passed as an argument to the EXTRACT() function. The “ASC” or “DESC” options can be utilized to sort the table’s data ascendingly or descendingly. This post has demonstrated a detailed procedure to sort a table by month in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-sort-a-table-by-month-in-postgresql/)

---

# How to Get the Column Type Using pg_typeof() Function in PostgreSQL?

> To get the column’s type in Postgres all you need to do is simply pass the column name as an argument to the pg_typeof() function.

PostgreSQL provides a built-in function named “ **pg_typeof()** ” that helps us in getting the data type of a value or table’s column. It accepts a value or a column as an argument and retrieves the OID of the respective value or column. More specifically, it retrieves a “regtype” which is an OID alias type(doesn’t have operations of its own).

This article will guide you on how to get a column’s type using the **pg_typeof()** function.

 **How to Get the Column’s Type Using pg_typeof() Function in Postgres?**

To get the column’s type in Postgres all you need to do is simply pass the column name as an argument to the pg_typeof() function. The pg_typeof() function will handle the rest. Here is a basic syntax for using the pg_typeof() function in Postgres:
    
    
    SELECT pg_typeof(col_name)
    FROM tab_name
    LIMIT 1;

The “LIMIT 1” clause is used to limit/restrict the result set to 1 record only.

 **Example 1: How to Get the Type of a Specific Column?**

In this example, we will utilize an already created sample table named “author_info” that has the following records:
    
    
    SELECT * FROM author_info
    ORDER BY author_id;

Let’s apply the pg_typeof() function to the author_name column to get the data type of the specified column:
    
    
    SELECT pg_typeof(author_name) AS auth_name
    FROM author_info
    LIMIT 1;

The output reveals that the data type of the specified column is TEXT.

 **Example 2: How to Get the Type of a Specific Column?**

To get the data type of multiple columns, you must use multiple pg_typeof() functions with comma-separated syntax. An example of getting data type of various columns is illustrated in the following snippet:
    
    
    SELECT pg_typeof(author_name) AS auth_name,
    pg_typeof(author_exp) AS auth_name
    FROM author_info
    LIMIT 1;

The pg_typeof() function retrieves the data type of the given columns.

 **Conclusion**

To get the column’s type in Postgres all you need to do is simply pass the column name as an argument to the pg_typeof() function. The stated function will take care of the rest. It accepts a value or a column as an argument and retrieves the OID of the respective value or column. This post has demonstrated the use of the pg_typeof() function in PostgreSQL using appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-column-type-using-pg_typeof-function-in-postgresql/)

---

# How to Get a List of PostgreSQL Supported Timezones

> In Postgres, the pg_timezone_abbrevs() function, the “pg_timezone_names” view, and the pg_timezone_abbrevs view are used to get the list of PostgreSQL-supporte…

A timezone describes a region of the globe with a uniform standard time. PostgreSQL supports various temporal data types that assist us in storing, retrieving, or manipulating the DateTime values with or without a timezone. Therefore, while working with these temporal data types you may need to get the list of Postgres-supported time zones. Postgres provides various methods to achieve this task.

This write-up will present a profound understanding of getting the list of Postgres-supported Timezones using various methods.

 **How to Get/Return a List of PostgreSQL-Supported Timezones?**

In Postgres, you can use one of the following methods to get the list of Postgres-supported timezones:

\- **Method 1:** Using the “pg_timezone_names” View  
\- **Method 2:** Using the pg_timezone_abbrevs View  
\- **Method 3:** Using the pg_timezone_abbrevs() Function

Let’s start with the “pg_timezone_names” View.

 **How to Get Postgres-Supported Timezones Using the “pg_timezone_names” View?**

Use the “pg_timezone_names” view with the SELECT query to populate the list of Postgres-supported timezones:
    
    
    SELECT * FROM pg_timezone_names;

The “ **pg_timezone_names** ” successfully retrieves the list of Postgres-supported timezones.

 **How to Get Postgres-Supported Timezones Using the “pg_timezone_abbrevs” View?**

Run the “SELECT *” query along with the “pg_timezone_abbrevs” view to get the list of Postgres-supported timezones:
    
    
    SELECT * FROM pg_timezone_abbrevs;

The output demonstrates that the “pg_timezone_abbrevs” view retrieves the abbreviated time zones along with the utc_offset.

 **How to Get Postgres-Supported Timezones Using the “pg_timezone_abbrevs()” Function?**

The pg_timezone_abbrevs() function can also be used as an alternative to the pg_timezone_abbrevs view to get the PostgreSQL-supported timezones:
    
    
    SELECT * 
    FROM pg_timezone_abbrevs();

The output shows that the stated function retrieves the same output as the pg_timezone_abbrevs view.

 **Conclusion**

In Postgres, the pg_timezone_abbrevs() function, the “pg_timezone_names” view, and the pg_timezone_abbrevs view are used to get the list of PostgreSQL-supported timezones. All these approaches are utilized with the help of the SELECT statement. This blog has illustrated various methods to get the list of PostgreSQL-supported timezones.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-a-list-of-postgresql-supported-timezones/)

---

# How to Multiply Two Table Columns in PostgreSQL

> To perform multiplication on two columns of a particular table, the “*” operator is used in PostgreSQL. For this purpose, all you need to do is, specify the “*…

PostgreSQL users often need to perform mathematical operations on mathematical data, such as addition, subtraction, multiplication, and so on. To deal with such cases, Postgres provide various inbuilt operators and functions. For instance, to perform multiplication on two columns of a particular table, the “*” operator is used in PostgreSQL.

This post will explain how to multiply two columns of a particular table in Postgres using the “*” operator.

 **How to Multiply Two Table Columns in Postgres?**

To perform multiplication on tables columns, all you need to do is, specify the “*” operator between the column names, as shown in the following syntax:
    
    
    SELECT
    col_1 * col_2
    FROM tab_name;

Here, col_1 and col_2 are the columns to be multiplied while tab_name represents the targeted table.

 **Example: Multiplying Two Columns**

We have a sample table named “product_details” that contains the following records:
    
    
    SELECT * FROM product_details
    ORDER BY pro_id;

Suppose we want to get the total price of each product. To do so, we need to multiply the “pro_price” column with the “pro_quantity” column:
    
    
    SELECT *,
    pro_price * pro_quantity AS subtotal 
    FROM product_details
    ORDER BY pro_id;

In the above query:

\- The SELECT * query is used to fetch all columns of the “product_details” table.  
\- The “*” operator is used between the “pro_price” and “pro_quantity” columns of the selected table to get the total price.  
\- The column alias “AS” is used to assign a temporary name to the resultant column.  
\- The table’s records will be sorted according to the “pro_id” column.

The output snippet shows that the multiplication has been successfully performed on the selected columns.

That was all about multiplying two columns in PostgreSQL.

 **Conclusion**

To perform multiplication on two columns of a particular table, the “*” operator is used in PostgreSQL. For this purpose, all you need to do is, specify the “*” operator between the selected columns. Consequently, the stated operator will perform the multiplication on the selected columns and retrieve the result in a new column. This blog post has demonstrated the use of the “*” operator in PostgreSQL using appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-multiply-two-table-columns-in-postgresql/)

---

# How to Group Data by Year in PostgreSQL

> In PostgreSQL, various inbuilt functions like DATE_PART(), EXTRACT(), and DATE_TRUNC() are used with the GROUP BY clause to group the table’s data by a specifi…

Grouping the table’s data help’s us count and analyze the identical data and remove the redundancy. In PostgreSQL, users may encounter a situation where they need to group the table’s data based on a specific date field such as a month, year, etc. For this purpose, various built-in date functions can be utilized with the Postgres’ GROUP BY clause.

This blog will illustrate how to group the table’s data based on a year.

 **How to Group Data by Year in Postgres?**

To group data by year, use the DATE_PART() function with the GROUP BY clause and pass “year” as an argument to the stated function. Consider the following syntax for a profound understanding:
    
    
    SELECT DATE_PART('Year', date_val),
    COUNT(col_name)
    FROM tab_name
    GROUP BY DATE_PART('Year', date_val);

In the above syntax, the DATE_PART() function will fetch the year from the given date, and the GROUP BY clause will group the data based on the extracted year.

 **Example: How to Group Table’s Data by Years in PostgreSQL?**

We have created an “emp_info” table with the following data:
    
    
    SELECT * FROM emp_info
    ORDER BY emp_id;

Suppose we want to group the employees with respect to their joining year. For this purpose, we will utilize the DATE_PART() function along with the GROUP BY clause as follows:
    
    
    SELECT
    DATE_PART('Year', joining_date) AS joining_year,
    COUNT(emp_id) AS total_employees
    FROM emp_info
    GROUP BY DATE_PART('Year', joining_date);

In the above query:

\- The DATE_PART() function pulls the year from the “joining_date” column.  
\- The COUNT() function will calculate the number of employees in each group.  
\- Finally, the GROUP BY clause will group the employees according to the extracted year.

The output shows that three employees joined the company in “2023”, two in “2018”, and one in “2019” and “2021”.

 **Note:** In PostgreSQL, the **EXTRACT()** and **DATE_TRUNC()** functions can also be used to group the table’s data based on a specific year.

 **Conclusion**

In PostgreSQL, various inbuilt functions like DATE_PART(), EXTRACT(), and DATE_TRUNC() are used with the GROUP BY clause to group the table’s data by a specific date field. “Year” must be passed as an argument to the stated functions to group the table’s data based on a year. This post has explained how to group the table’s data by year in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-group-data-by-year-in-postgresql/)

---

# What Does DELETE RETURNING Clause Do in PostgreSQL

> In PostgreSQL, the DELETE RETURNING clause not only deletes the selected rows but also retrieves the deleted rows.

PostgreSQL provides a wide range of commands, clauses, built-in functions, etc. to facilitate its users. Users can store, retrieve, and manipulate the data effectively using these commands, functions, and queries. A frequently performed database operation is deleting a specific record or a set of records that can be done using the **DELETE** command. The DELETE command retrieves the number of deleted records on successful execution. In Postgres, the **DELETE RETURNING** clause can be used to extend the functionalities of the standard DELETE command.

This write-up will discuss what is DELETE RETURNING and how to use it in PostgreSQL.

 **What Does the DELETE RETURNING Clause Do in PostgreSQL?**

In PostgreSQL, the DELETE RETURNING clause not only deletes the selected rows but also retrieves the deleted rows. The example of using the DELETE RETURNING clause is depicted in the following snippet:
    
    
    DELETE tab_name
    RETURNING *;

Here in the above syntax, the “*” indicates that all the deleted rows will be retrieved on successful execution of the “DELETE RETURNING” clause.

 **Example 1: How to Use DELETE RETURNING Clause in Postgres?**

Suppose we have a table named “emp_dat” that contains the following records:
    
    
    SELECT * FROM emp_dat;

Now the need of the moment is to delete all those employees whose id is greater than or equal to five. Also, the users want to retrieve the deleted records so that they can confirm the deleted records. Both these operations can be done in one go using the “DELETE RETURNING” clause as follows:
    
    
    DELETE FROM emp_dat
    WHERE id >= 5
    RETURNING *;

The output shows that the DELETE RETURNING clause not only deleted the selected records but also retrieved them as output.

 **Example 2: How to Use DELETE RETURNING Clause on Specific Columns in Postgres?**

The DELETE RETURNING clause can be used to delete the selected records and retrieve only specific columns:
    
    
    DELETE FROM emp_dat
    WHERE id >= 3
    RETURNING name;

The above query will delete all those employees that meet the described criteria. However, instead of returning all columns, the RETURNING clause will retrieve only the employee names from the “name” column:

That was all about the use of the DELETE RETURNING clause in Postgres.

 **Conclusion**

In PostgreSQL, the **DELETE RETURNING** clause not only deletes the selected rows but also retrieves the deleted rows. The DELETE RETURNING clause saves a lot of time for the user as it deletes and retrieves the selected rows in one go. The DELETE RETURNING clause can also be used to delete the selected records and retrieve only specific columns. This post has explained the usage of the DELETE RETURNING clause in Postgres using various examples.

---
[View this page online](https://www.commandprompt.com/education/what-does-delete-returning-clause-do-in-postgresql/)

---

# How to Create a Sequence in PostgreSQL?

> To create a sequence in Postgres, execute the CREATE SEQUENCE command followed by the name of the sequence to be created.

A Postgres sequence is an object of a database that generates a unique series of integers. In Postgres, sequences can be created using a “ **CREATE SEQUENCE** ” command. Sequences maintain a particular order, such as ascending or descending. The sequence’s order (ascending or descending) is determined at the time of sequence creation which plays a very crucial role. For instance, {2, 4, 6, 8, 10} and {10, 8, 6, 4, 2} are totally different sequences.

This write-up will present a comprehensive guide on sequence creation in Postgres using suitable examples.

 **How to Create a Sequence in Postgres?**

In PostgreSQL, the **CREATE SEQUENCE** statement helps us create a new sequence. An additional clause **IF NOT EXISTS** can be utilized with the stated command to create a sequence only if it doesn’t exist already. The following syntax will let you understand how to create a sequence in Postgres:
    
    
    CREATE SEQUENCE [ IF NOT EXISTS ] seq_name
    [ AS integer_data_type ]
    [ INCREMENT [ BY ] increment_value ]
    [ MINVALUE min_value | NO MINVALUE ] 
    [ MAXVALUE max_value | NO MAXVALUE ]
    [ START [ WITH ] start_value ] 
    [ CACHE cache ] 
    [ [ NO ] CYCLE ]
    [ OWNED BY { tab_name.col_name | NONE } ]

Let’s understand this syntax line-by-line:

\- “seq_name” represents a new sequence to be created.  
\- Replace the “integer_data_type” option with one of the following data types: INTEGER, SMALLINT, or BIGINT.  
\- If you omit the data type while sequence creation, then Postgres will create the sequence with the default data type, i.e., BIGINT.  
\- The increment_value defines the sequence’s increment criteria.  
\- Specify any positive or negative value in place of “increment_value”. Where positive “increment_value” increments the sequence in ascending order, while negative “increment_value” will create a descending sequence.  
\- By default, the minimum value for an ascending sequence is 1, however, you can specify the minimum/lowest value of the sequence using the MINVALUE. Use the NO MINVALUE clause to specify the default minimum value of a sequence.  
\- Use the MAXVALUE to specify the maximum value of the sequence. A Postgres ascending sequence has a maximum/highest value equal to the maximum value of the specified data type. Use the NO MAXVALUE clause to specify the default maximum value of a sequence.  
\- The default minimum value for descending sequences is the lowest/minimum value of the given data type, while the default maximum value is “-1”.  
\- Use the START clause to define the initial value of a sequence, by default, it is equal to MINVALUE for ascending sequences and MAXVALUE for descending sequences.  
\- Using the CACHE, you can preallocate and store sequence numbers in memory for faster access.  
\- Enabling the CYCLE will restart the value of the sequence when it reaches the limit.  
\- The OWNED BY clause helps us in connecting the table’s column with the sequence. Therefore, dropping a table or column will also delete its associated sequence.

 **Example 1: How Does CREATE SEQUENCE Work in Postgres?**

Let’s learn how to create a sequence in Postgres using the following code example:
    
    
    CREATE SEQUENCE example_sequence
    AS SMALLINT
    INCREMENT 2
    MAXVALUE 20
    START 10;

In this example:

\- A new sequence named “ **example_sequence** ” is created using the CREATE SEQUENCE command.  
\- The **SMALLINT** represents the type of sequence.  
\- The **INCREMENT 2** represents that the sequence value will be incremented with 2.  
\- A positive increment value results in an ascending sequence.  
\- The sequence is started with a value 10.

The sequence has been successfully created. Let’s utilize the nextval() function to fetch the next value from the given sequence:
    
    
    SELECT nextval('example_sequence');

Nextval() was executed three times, and this is what we got:

The output shows that the sequence value was incremented by 2 on each execution. Since we specified “20” as the maximum value. So, Postgres will throw an error if the nextval() function is used on a sequence that has reached its maximum limit:

The output shows an error stating that the “example_sequence” has reached its maximum limit. To rectify the stated error, you must use the “ **CYCLE** ” clause at the time of sequence creation.

 **Example 2: How to Create a Sequence in Descending Order?**

In the following example, a negative INCREMENT value will be used to create a sequence in descending order:
    
    
    CREATE SEQUENCE example_sequence_1
    AS SMALLINT
    INCREMENT -2
    MINVALUE 1 
    MAXVALUE 20
    START 10
    CYCLE;

Let’s run the nextval() function to fetch the next value from the given sequence:
    
    
    SELECT nextval('example_sequence_1');

Following are the results of executing nextval() function three times:

The output shows that the sequence value decreases by 2 after each execution.

 **Example 3: How to Create a Sequence Associated/Linked With a Postgres Table?**

A sequence can be created and used with an integer column of a table. In the following snippet, a new table named “student_tab” is created with three columns: “id”, “std_name”, and “std_age”.
    
    
    CREATE TABLE student_tab(
    id INTEGER, 
    std_name TEXT,
    std_age INTEGER
    );

Now we will create a sequence named “ **std_seq** ” and associate it with the “ **student_tab** ” table:
    
    
    CREATE SEQUENCE std_seq
    START 1
    INCREMENT 3
    MAXVALUE 50
    OWNED BY student_tab.id;

In the above query, START, INCREMENT, and MAXVALUE are used to specify the starting value as 1, increment value as 3, and sequence’s maximum value as 50. Finally, the OWNED BY clause is used to associate the “std_seq” sequence with the “id” column of the “student_tab” table:

The sequence has been successfully created and associated with the “student_tab” table. Now, we will execute the following piece of code to insert the data into the “student_tab” table:
    
    
    INSERT INTO student_tab(id, std_name, std_age)
    VALUES (nextval('std_seq'), 'Dean Jones', 35),
    (nextval('std_seq'), 'Tim Joseph', 25);

In the above command, the “nextval()” function is used within the INSERT statement to get the value from the “std_seq” sequence and insert it into the “student_tab” table:

The output verifies that the selected records have been added to the “student_tab” table. Now, we will utilize the SELECT query to populate all the data of the “student_tab” table:
    
    
    SELECT * FROM student_tab;

From the output, you can observe that the id column is populated based on the “std_seq” sequence.

 **Conclusion**

To create a sequence in Postgres, execute the **CREATE SEQUENCE** command followed by the name of the sequence to be created. An additional clause **IF NOT EXISTS** can be utilized with the stated command to create a sequence only if it doesn’t exist already. Various options like START, INCREMENT, MAXVALUE, etc. can be used with the CREATE SEQUENCE command to specify sequence starting value, increment value, maximum value, and so on. This blog post demonstrated different use cases of the CREATE SEQUENCE command in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-sequence-in-postgresql/)

---

# PostgreSQL Conditional Select With Examples

> To make the conditional selection in PostgreSQL, the CASE expression must be used within the SELECT statement.

The term “ **conditional select** ” refers to data selection based on some particular conditions. In PostgreSQL, conditional statements, such as the IF ELSE and CASE, are used to define the selection criteria. However, the Postgres IF ELSE statement can’t be utilized within the SELECT query. Therefore, to make a conditional selection the **SELECT** statement must be executed with the **CASE** statement.

This write-up will guide you on how to perform the conditional selection in Postgres.

 **PostgreSQL Conditional Select With Examples**

In PostgreSQL, the **CASE** statement lets us check multiple conditions and retrieves the results based on the specified conditions. While the SELECT statement allows us to fetch the table’s data. Use the following syntax to use the CASE expression within the SELECT statement:
    
    
    SELECT col_list, 
    CASE
    WHEN cond_1 THEN result_1
    WHEN cond_2 THEN result_2
    …
    WHEN cond_n THEN result_n
    ELSE else_result
    END
    FROM tab_name;

In the above-given syntax:  
\- cond_1, cond_2, …, cond_n represents the conditions based on which the reult_1, result_2, …, or result_n will be selected.  
\- For instance, when the cond_1 is true, the result_1 will be retrieved.  
\- If no condition is true, the result specified within the ELSE statement will be retrieved.  
\- tab_name represents the table from which the data will be selected.

In simple terms, the above syntax will let you select the table’s data based on some specific conditions.

 **Example: Understanding Conditional Select**

A table named “bikes_info” has already been created with the following data:
    
    
    SELECT * FROM bikes_info;

In the following snippet, the CASE statement is used within the SELECT statement to display the results based on the conditional select:
    
    
    SELECT bike_model, bike_price, launch_date,
    CASE
    WHEN launch_date BETWEEN '2020-01-01' AND CURRENT_DATE
    THEN 'Already Launched'
    WHEN launch_date BETWEEN CURRENT_DATE AND '2024-01-01'
    THEN 'Launching Soon'
    WHEN launch_date > '2024-01-01'
    THEN 'Will be launched in Future'
    ELSE 'Already Launched'
    END CASE
    FROM bikes_info;

In this example program:

\- Columns to be selected are specified in the SELECT statement.  
\- The CASE statement is also used in the SELECT statement to make the conditional selection.  
\- The selection criteria are defined using the WHEN clause. While the corresponding results are specified using the THEN clause.  
\- The selection condition is defined using the “launch_date” column of the “bikes_info” table.

The above snippet demonstrates how to do conditional selection in PostgreSQL.

 **Conclusion**

To make the conditional selection in PostgreSQL, the CASE expression must be used within the SELECT statement. In PostgreSQL, the SELECT statement allows us to fetch the table’s data. While the **CASE** statement lets us check multiple conditions and retrieves the results based on the specified conditions. The conditions can be defined using the WHEN clause and the corresponding results can be specified using the THEN clause. This post presented a detailed guide on conditional selection in PostgreSQL using examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-conditional-select-with-examples/)

---

# What is Postgres (summary)

> PostgreSQL, often referred to simply as &quot;Postgres,&quot; is a popular open-source relational database management system (RDBMS). It is known for its stability, robu…

PostgreSQL, often referred to simply as "Postgres," is a popular open-source relational database management system (RDBMS). It is known for its stability, robustness, and support for a wide range of advanced features, making it a popular choice for large-scale, high-performance applications.  


PostgreSQL was first released in 1996 as an Open Source project by the PostgreSQL Global Development Group. It is a fork of work done on Ingres and later Postgres which were research projects at the University of California, Berkeley. Since then, it has evolved into a mature, enterprise-grade database system that is widely used in both commercial and open-source software applications.

Read more here.

---
[View this page online](https://www.commandprompt.com/education/what-is-postgres/)

---

# PostgreSQL DATEDIFF - DateTime Difference in Years, Months, etc

> The “-” operator, DATE_PART(), EXTRACT(), and AGE() functions can be used in PostgreSQL to calculate the difference between various DateTime values.

Database management systems, such as SQL Server, Oracle, etc., utilize the DATEDIFF function to find the difference between given Dates. However, Postgres doesn’t support the DATEDIFF function. So, how to find the DateTime difference in Postgres?

Well! In PostgreSQL, the “-” operator, **DATE_PART()** , **EXTRACT()** , and **AGE()** functions are used to calculate the difference between various DateTime values.

This post presents a comprehensive guide on calculating the difference between different dates, times, timestamps, and intervals using examples.

 **How to Find DateTime Difference in Postgres Via the DATE_PART() Function?**

The DATE_PART() function is used in Postgres to get a specific field from a date. So, it can be used with the “-” operator to find the difference between the given DateTime values.

This section demonstrates how to use the DATE_PART() function to find date differences in:

\- Year  
\- Month  
\- Week  
\- Day  
\- Hour  
\- Minute  
\- Second

 **Date Difference in Years**

To find the DateTime difference in “Years” using **DATE_PART()** function, use the below syntax:
    
    
    DATE_PART('YEAR', end_date) - DATE_PART('YEAR', start_date);

Where the “start_date” and “end_date” can be “Timestamps”, “Dates”, “Intervals”, etc.

 **Example: Calculating the Date Difference in Years**

The DATE_PART() is utilized in the following code snippet to calculate the difference between the given dates in “years”:
    
    
    SELECT
    DATE_PART('YEAR', '2023-01-01' :: DATE) - 
    DATE_PART('YEAR', '2019-06-01' :: DATE) AS year_diff;

The output successfully retrieves the date difference in years.

 **Date Difference in Months**

With DATE_PART() function, you can calculate the DateTime difference in "Month" as follows:
    
    
    (datediff_in_years) *12 + (DATE_PART('Month', end_date) - DATE_PART('Month', start_date));

From the above syntax, you can notice that to find the date difference in months, first, you need to find the date difference in years. Multiply the “date difference in years” with “12” and add it to the “date difference in months” to find the precise date difference in months.

 **Example: Calculating the Date Difference in Months**

The below snippet demonstrates how to find the date difference in “Month” using the DATE_PART() function:
    
    
    SELECT 
    (DATE_PART('YEAR', '2023-01-01' :: DATE) - 
    DATE_PART('YEAR', '2020-04-01' :: DATE)) * 12
    + (DATE_PART('Month', '2023-01-01' :: DATE) - 
    DATE_PART('Month', '2020-04-01' :: DATE)) AS month_diff;

The output successfully retrieves the date difference in months.

 **Date Difference in Days**

To get the date difference in days, use the following syntax:
    
    
    DATE_PART('Day', end_date - start_date);

Here is an example code:

 **Example: Calculating Date Difference in Days**

In the following snippet, the DATE_PART() function is used to find the date difference in “Days”:
    
    
    SELECT
    DATE_PART('Day', '2023-02-01'::TIMESTAMP - '2023-01-10'::TIMESTAMP) AS day_diff;

The output snippet demonstrates that the date difference is “22” days.

 **Date Difference in Weeks**

Divide the “date difference in days by 7” and wrap it within TRUNC() function to find the date difference in weeks, as shown below:
    
    
    TRUNC(DATE_PART('Day', end_date - start_date)/7);

Here, the TRUNC() function is used to trim the floating points from the weeks' difference.

 **Example: Calculating Date Difference in Weeks**

In the below code snippet, the DATE_PART() function is used along with the TRUNC() function to get the date difference in weeks:
    
    
    SELECT
    TRUNC(DATE_PART('Day', '2023-02-01'::TIMESTAMP - '2023-01-10'::TIMESTAMP)/7) AS week_diff;

The output demonstrates that the difference between the input dates is “3” weeks.

 **Date Difference in Hours**

To find the date difference in hours from the given DateTime values, you must follow the below-provided steps:

\- First, find the “date_diff” in days and multiply it with “24”.  
\- Calculate the “date_diff” in hours and add it with the “date_diff in days”.

The below syntax will help you understand this concept better:
    
    
    (DATE_PART('Day', end_date - start_date)) * 24 + 
    (DATE_PART('Hour', end_date) - DATE_PART('Hour', start_date));

 **Example: Calculating Date Difference in Hours**

Let’s learn how to find the date difference in hours using the “DATE_PART()” function:
    
    
    SELECT
    DATE_PART('Day', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP) * 24
    + (DATE_PART('Hour', '2023-01-03 04:10:00'::TIMESTAMP) - 
    DATE_PART('Hour', '2023-01-02 03:15:00'::TIMESTAMP)) AS hour_diff;

The output shows that the difference between the given TIMESTAMPS is “25” hours.

 **Date Difference in Minutes**

To find the date difference in minutes from the given DateTime values, use the following steps:

\- First, find the “date_diff” in days and multiply it with “24”.  
\- Find the “date_diff” in hours and multiply it by “60”.  
\- Find the “date_diff” in minutes and add it with the “date_diff” in hours and the “date_ diff” in days.

Here is the basic syntax:
    
    
    (DATE_PART('Day', end_date - start_date)) * 24 + 
    (DATE_PART('Hour', end_date start_date)) * 60 +
    (DATE_PART('Minute', end_date - start_date));

Let’s put this concept into practice.

 **Example: Calculating Date Difference in Minutes**

In this example, the DATE_PART() function is applied on two different TIMESTAMPS to find the data difference in minutes:
    
    
    SELECT 
    ((DATE_PART('Day', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP) * 24 +
    DATE_PART('Hour', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP)) * 60 +
    DATE_PART('Minute', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP));

The difference between the given TIMESTAMPS is “1495” minutes.

 **Date Difference in Seconds**

To find the date difference in seconds from the specific DateTime values, you must follow the following instructions:

\- First, find the “date_diff” in days and multiply it with “24”.  
\- Calculate the “date diff” in hours and minutes and multiply them by “60”.  
\- Find the “date_diff” in seconds and add it with the “date_diff” in hours, days, and minutes.

Here is the syntax:
    
    
    (DATE_PART('Day', end_date - start_date)) * 24 + 
    (DATE_PART('Hour', end_date) - DATE_PART('Hour', start_date)) * 60 +
    (DATE_PART('Minute', end_date - start_date)) *60 +
    DATE_PART('Second', end_date - start_date);

 **Example: Calculating Date Difference in Seconds**

Using DATE_PART(), the below example calculates the date difference in seconds:
    
    
    SELECT 
    ((DATE_PART('Day', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP) * 24 +
    DATE_PART('Hour', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP)) * 60 +
    DATE_PART('Minute', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP)) * 60
    + DATE_PART('Second', '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP)
    AS sec_diff;

The above snippet demonstrates that the difference between the provided TIMESTAMPS is “89700” seconds.

 **How to Find DateTime Difference in Postgres Via the EXTRACT() Function?**

The EXTRACT() function can be used instead of the DATE_PART() function to get the date difference in years, months, seconds, etc. In that case, the “,” will be replaced with the “FROM” clause.

For instance, the below snippet depicts how to find the date difference in seconds using the EXTRACT() function:
    
    
    SELECT ((EXTRACT('Day' FROM '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP) * 24 + 
    EXTRACT('Hour' FROM '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP)) * 60
    + EXTRACT('Minute' FROM '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP))*
    60 + EXTRACT('Second' FROM '2023-01-03 04:10:00'::TIMESTAMP - '2023-01-02 03:15:00'::TIMESTAMP)
    sec_diff;

The EXTRACT() function retrieves the date difference in seconds.

 **How to Find DateTime Difference in Postgres Via the AGE() Function?**

In PostgreSQL, the built-in AGE() function can also be used to calculate the date difference. The AGE() function returns the DateTime difference as an interval. Here is the syntax that exhibits the basic usage of the AGE() function:
    
    
    AGE(end_date, start_date);

The AGE() function will subtract the start date from the end date and retrieve the resultant DateTime as an interval.

 **Example: Calculating DateTime Difference**

Let’s learn how to get date difference as an INTERVAL in Postgres:
    
    
    SELECT AGE('2023-01-03 04:10:00' - '2023-01-02 03:15:00') date_diff;

The above snippet illustrates that the difference between the provided dates is “1 year 10 months and 3 days”.

 **Conclusion**

In databases, such as SQL Server, Oracle, etc., the DATEDIFF function is used to find the difference between provided Dates or TIMESTAMPS. However, Postgres doesn’t support the DATEDIFF function. Alternatively, the “-” operator, **DATE_PART()** , **EXTRACT()** , and **AGE()** functions can be used in PostgreSQL to calculate the difference between various DateTime values. This post explained different alternatives of the DATEDIFF function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-datediff-datetime-difference-in-years-months-etc/)

---

# How to Start or Stop PostgreSQL Server on Ubuntu

> In Ubuntu, “/etc/init.d/postgresql” and the “systemctl” commands are used with the “start” or “stop” option to activate or deactivate the Postgres server, resp…

PostgreSQL is a widely used relational database because of its basic to advanced features. One of the notable features of Postgres is that it is compatible with various operating systems, such as Windows, Linux, and MacOS. It assists users in storing, managing, and retrieving large amounts of data efficiently. To get the maximum of Postgres features, it is necessary to learn how to start or stop the Postgres server on ubuntu.

This post is going to present a step-by-step guide on how to start or stop the PostgreSQL server on the Ubuntu operating system.

 **How to Start or Stop PostgreSQL Server on Ubuntu?**

In Ubuntu, the Postgres server can be started or stopped using various methods. In this article a couple of well-known methods will be discussed to start or restart the Postgres server on Linux (Ubuntu):

  * Method 1: Using the “systemctl” Command
  * Method 2: Using the “/etc/init.d/postgresql” which is the script that systemctl calls.



 **Method 1: Start and Stop Postgres Server Using the “systemctl” Command**

Here are the steps to start or stop the Postgres server on ubuntu using the “systemctl” command:

 **Step 1: Review the Postgres Status**

Open the terminal and execute the following “sudo” command to review the current status of the Postgres server:
    
    
    sudo systemctl status postgresql

The above snippet shows that the Postgres server is currently deactivated.

 **Step 2: Start the Postgres Server**

Use the below-given “sudo” command with the “start” option to begin the Postgres server:
    
    
    sudo systemctl start postgresql

The output illustrates that the Postgres server has been initiated successfully.

 **Step 3: Verify the Postgres Status**

Use the below-given “sudo” command along with the “status” option to verify the Postgres status:
    
    
    sudo systemctl status postgresql

The output confirms that the Postgres Server has been activated successfully.

 **Step 4: Stop the Postgres Server**

Type the “systemctl” command followed by the “stop” option to halt the Postgres server:
    
    
    sudo systemctl stop postgresql

The output shows that the Postgres server has been stopped successfully.

 **Step 5: Confirm Postgres Status**

Type the “systemctl” command followed by the “status” option to confirm the Postgres status:
    
    
    sudo systemctl status postgresql

The output proves that the Postgres server has been deactivated successfully.

 **Method 2: Start and Stop Postgres Server Using “/etc/init.d/postgresql”**

To start or stop a Postgres server on Ubuntu, follow the below-given instructions:  


  
 **Step 1: Review the Postgres Status**

Open the terminal and execute the following command to review the current status of the Postgres server:
    
    
    /etc/init.d/postgresql status

The above snippet states that the Postgres server is not active yet.

 **Step 2: Start the Postgres Server**

Use the “/etc/init.d/postgresql” command with the start option to initiate the Postgres server:
    
    
    /etc/init.d/postgresql start

The output shows that the Postgres server has been started successfully.

 **Step 3: Verify the Postgres Status**

Use the “/etc/init.d/postgresql” command with the “status” option to verify the Postgres status:
    
    
    /etc/init.d/postgresql status

The output demonstrates that the Postgres Server has been activated/started successfully.

 **Step 4: Stop the Postgres Server**

Type the “/etc/init.d/postgresql” command followed by the “stop” option to halt the Postgres server:
    
    
    /etc/init.d/postgresql stop

The output shows that the Postgres server has been stopped successfully.

 **Step 5: Confirm Postgres Status**

Type the “/etc/init.d/postgresql” command followed by the “status” option to confirm the Postgres status:
    
    
    /etc/init.d/postgresql status

The output proves that the Postgres server has been stopped successfully.

 **Conclusion**

In Ubuntu, “/etc/init.d/postgresql” and the “systemctl” commands are used with the “start” or “stop” option to activate or deactivate the Postgres server, respectively. The status of the Postgres server can be confirmed by executing these commands with the “status” option. This article has presented a step-by-step guide on how to start or stop the PostgreSQL server on the Ubuntu operating system.

---
[View this page online](https://www.commandprompt.com/education/how-to-start-or-stop-postgresql-server-on-ubuntu/)

---

# Composite Primary Keys in PostgreSQL

> In PostgreSQL, a composite primary key can be defined as a combination of two or more columns that guarantees the uniqueness of a record.

In RDBMS like PostgreSQL, the **composite primary keys** are used to uniquely identify a record. It is created by merging multiple column values that ensure uniqueness. More specifically, a composite primary key can be defined as the combination of multiple columns that ensures the uniqueness of a record. Selecting an individual column of a composite primary key doesn’t guarantee uniqueness.

This write-up explains the following aspects of the composite primary keys in PostgreSQL:

\- What is the Need for Composite Primary Key in Postgres?  
\- How to Add or Define Composite Primary Keys in Already Existing Tables?  
\- How to Create/Define Composite Primary Keys While Creating a New Postgres Table?

 **What is the Need for Composite Primary Key in Postgres?**

The need for a composite primary key arises when we have to identify the table’s records with two or more attributes uniquely. For instance, a composite primary key can be needed while maintaining the “product-order” details. Consider the following snippet for a profound understanding:

From the table, it can be observed that the uniqueness can’t be figured out based on a single column. Therefore, for better search purposes, the customer's details can be uniquely identified based on the “product_id” and “order_id” columns.

 **How to Add or Define Composite Primary Keys in Already Existing Tables?**

Postgres allows us to add a composite primary key to an already existing table by utilizing the **ALTER TABLE** statement. To do that, the below-provided syntax is used in Postgres:
    
    
    ALTER TABLE table_name
    ADD PRIMARY KEY (col_list);

In this syntax:

\- The “ALTER TABLE” statement is used to modify an already existing table.  
\- The “table_name” represents a table to be altered.  
\- The “PRIMARY KEY” constraint is used to define/create composite primary keys.  
\- The “col_list” represents the columns to be defined as the composite primary keys.

 **Example: Adding a Composite Primary Key**

In this example, a composite primary key will be added to the “product_order” table by combining the “order_id” and “product_id” columns:
    
    
    ALTER TABLE product_order 
    ADD PRIMARY KEY (product_id, order_id);

In the above query, the “ALTER TABLE” command is executed with the “ADD PRIMARY KEY” clause to add a composite primary key in the “product_order” table:

The “ALTER TABLE” message in the output ensures that the given table has been modified. The table alteration can be confirmed using the following query:
    
    
    SELECT * FROM product_order;

The output snippet proves that the composite primary key has been successfully added to an already existing table.

 **How to Create/Define Composite Primary Keys While Creating a New Postgres Table?**

A composite primary key can be created/defined in Postgres while table creation. For this purpose, the below-provided syntax is used in Postgres:
    
    
    CREATE TABLE table_name(
    col_1 data_type, 
    col_2 data_type, 
    col_3 data_type,
    …
    col_n data_type,
    PRIMARY KEY(col_list)
    );

In this syntax:

\- The “CREATE TABLE” statement is used to define a new Postgres table.  
\- The “table_name” represents a table to be created.  
\- col_1, col_2, …, col_n represent the column names.  
\- The “PRIMARY KEY” constraint is used to add/define the composite primary keys.  
\- The “col_list” represents the columns to be defined as the composite primary keys.

 **Example: Creating a Composite Primary Key**

In the following example, a composite primary key will be created on the “product_id” and “order_id” columns:
    
    
    CREATE TABLE customer_details(
    product_id INTEGER,
    order_id INTEGER,
    price NUMERIC,
    PRIMARY KEY (product_id, order_id)
    );

The “CREATE TABLE” message in the output signifies that the desired table has been created. To verify the creation of the composite primary key, execute the “SELECT *” command:
    
    
    SELECT * FROM customer_details;

The output shows that a composite primary key has been successfully created on two columns.

 **Conclusion**

In PostgreSQL, the composite primary keys are used to uniquely identify a record. A composite primary key can be defined as a combination of two or more columns that guarantees the uniqueness of a record. The need for a composite primary key arises when we have to identify the table’s records with two or more attributes uniquely. This article presented a detailed guide on how to create a composite primary key while table creation or add a composite primary key by altering an already existing table.

---
[View this page online](https://www.commandprompt.com/education/composite-primary-keys-in-postgresql/)

---

# How to Fix psql Command Not Found Error in PostgreSQL?

> In PostgreSQL, the “psql command not found” error arises if Postgres is not installed or the path for Postgres tools is not set on your system.

PostgreSQL is a widely used relational database that supports various CLI and GUI tools. These tools assist us in managing and manipulating databases efficiently. The traditional way of working with Postgres is using a CLI tool.

SQL Shell aka “psql” is an interactive command line tool that helps us access PostgreSQL via the terminal. However, while accessing Postgres via psql, you may encounter the “psql command not found error”. The stated error arises because of various reasons.

This blog post will present a detailed guide on how to resolve the psql command not found error using one of the following fixes:

\- Install Postgres  
\- Set Environment Variable

 **How to Fix psql Command Not Found Error in Postgres?**

In PostgreSQL, the “psql command not found” error or the “psql” is not recognized as an internal or external command arises because of the following reasons:

\- Postgres is not installed on the Machine.  
\- The Path for Postgres tools is not set on our system.

The stated error can be fixed either by installing PostgreSQL or by setting the environment variable for the Postgres tools.

 **Solution 1: Download and Install Postgres**

The very first reason that causes this error is Postgres is not installed on the system. In that case, [installing Postgres](<https://commandprompt.com/education/how-to-download-and-install-postgresql/>) will rectify the stated problem.

 **Solution 2: Set Environment Variable**

The primary reason which leads to the command not found error is that the path for the Postgres tools is not set on the system. In such a case, you can enforce one of the following solutions:

\- Set Path Using Command Prompt  
\- Set Path Using Edit System Environment Variables

 **Setting Path Using Command Prompt**

Open the windows search menu by pressing the “🪟 + S” button. Search CMD, and launch it as an administrator. Once the CMD terminal is open, execute the “setx” command to set the path for the Postgres tools using CMD:
    
    
    setx /M path "%PATH%;C:\Program Files\PostgreSQL\15\bin"

In this command:

\- “/M” is used to set the variable at the SYSTEM level/scope.  
\- “15” represents the Postgres version installed on our system. You must replace the with the Postgres version installed on your OS:

The Postgres bin directory’s path has been set successfully. For confirmation, you can re-launch the CMD and type any psql command:

The Postgres version confirms that the stated error has been rectified.

 **Setting Path Using Edit System Environment Variables**

Open the “Edit the System Environment Variables” settings from the Windows search menu:

Click on the “Environment variables…” button to launch the system properties:

Select the path variable available under the system variables and hit the “Edit” button:

Now, copy the “bin directory’s path”, click on the “New” button, and paste the copied path here:

Click on the “OK” button to add the path to the “Edit Environment Variables” window. Next, hit the “OK” button to close the “Environment Variables” Window:

Next, close the “System Properties” Window by clicking on the “OK” button:

Setting the path for the Postgres tools will fix the "psql command not found" error.

 **Conclusion**

In PostgreSQL, the “psql command not found” or “psql is not recognized as an internal or external command” error arises if Postgres is not installed or the path for Postgres tools is not set on your system. Installing Postgres or setting up the environment for Postgres will fix this error. This post explained a couple of solutions to fix the “psql command not found error” in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-psql-command-not-found-error-in-postgresql/)

---

# How to Use the pg_sleep() Function in PostgreSQL

> In PostgreSQL, the pg_sleep() function accepts the fractional seconds as arguments and delays the execution until the specified seconds pass

PostgreSQL is a relational database that facilitates its users with different built-in functions and operators. One such built-in function is “pg_sleep()” which is used to delay a query for a specified time period. It suspends the execution of the current process for a specific number of seconds. Once the specified seconds have passed, the process execution resumes automatically.

This article demonstrates how to use the pg_sleep() function in PostgreSQL using appropriate examples.

 **How to Use the pg_sleep() Function in Postgres?**

pg_sleep() function accepts the fractional seconds as arguments and delays the execution until the specified seconds pass. Here is the basic syntax of the stated function:
    
    
    pg_sleep(time);

Where the “time” represents the seconds that determine how long a process will sleep.

 **Example 1: How Does pg_sleep() Work in Postgres?**

In the following example, the pg_sleep() function is used between two CLOCK_TIMESTAMP() functions:
    
    
    SELECT CLOCK_TIMESTAMP(),
    pg_sleep(10),
    CLOCK_TIMESTAMP();

Ten seconds are specified in the pg_sleep() function to halt the execution for ten seconds:

The output clearly shows that there is a ten seconds delay between the execution of two CLOCK_TIMESTAMP() functions.

 **Example 2: Passing Negative Seconds to pg_sleep()**

Let’s learn how the pg_sleep() function deals with the negative seconds:
    
    
    SELECT CLOCK_TIMESTAMP(),
    pg_sleep(-10),
    CLOCK_TIMESTAMP();

The output shows that passing the negative seconds to the pg_sleep() function doesn’t make any difference.

 **Example 3: Passing Fractional Seconds to pg_sleep()**

The fractional seconds can also be passed to the pg_sleep() function to pause the execution for a specific time:
    
    
    SELECT CLOCK_TIMESTAMP(),
    pg_sleep(1.5),
    CLOCK_TIMESTAMP(),
    pg_sleep(1.5),
    CLOCK_TIMESTAMP();

This is how the pg_sleep() function works in PostgreSQL.

 **Conclusion**

In PostgreSQL, the pg_sleep() function accepts the fractional seconds as arguments and delays the execution until the specified seconds pass. The pg_sleep() function suspends the execution of the current process for the specified number of seconds. Once the specified seconds have passed, the process execution resumes automatically. This article has explained different use cases of the Postgres pg_sleep() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-pg_sleep-function-in-postgresql/)

---

# How to Use TRIM_ARRAY() Function in PostgreSQL

> In PostgreSQL, the TRIM_ARRAY() function trimmed the specified number of elements from the end of the given array and return a newly updated array.

PostgreSQL offers numerous array functions that are used to perform different operations on the arrays. For instance, the ARRAY_REMOVE() deletes the array’s elements, the ARRAY_APPEND() adds a new element at the end of an array, and so on. The TRIM_ARRAY() is one such array function that is used to remove or trim the specific number of array elements.

This article will explain the usage of the Postgres TRIM_ARRAY() function using appropriate examples.

 **How to Use TRIM_ARRAY() Function in PostgreSQL?**

The TRIM_ARRAY() function accepts an array and the number of elements to be trimmed as arguments. As a result, it trimmed the specified number of elements from the end of the given array and return a newly updated array. Here is the basic syntax of the TRIM_ARRAY() function:
    
    
    TRIM_ARRAY(arr, num);

The stated function returns a modified array, however, if the input array is NULL then NULL will be retrieved.

 **Example 1: How to Use the TRIM_ARRAY() in Postgres?**

In the following example, the **TRIM_ARRAY()** function is used on a 1-D array:
    
    
    SELECT TRIM_ARRAY(
    ARRAY['Joseph', 'John', 'Joe', 'Seth', 'Stephen'], 2
    );

The output clarifies that the two elements from the right side of the array have been trimmed.

 **Example 2: How to Use the TRIM_ARRAY() on Multi-dimensional Arrays?**

Let’s learn how to use the TRIM_ARRAY() function on a multi-dimensional array:
    
    
    SELECT TRIM_ARRAY(
    ARRAY[['Seth', 'Joseph'],
    ['John', 'Joe'], 
    ['Mike', 'Ambrose'],
    ['Seth', 'Stephen']], 2
    );

Here is what we will get on successful execution:

The output proved that the specified number of elements have been removed from the array.

 **Example 3: Using the TRIM_ARRAY() Function With a Negative Value**

In this example, we will show you how the TRIM_ARRAY() function deal with a negative value:
    
    
    SELECT TRIM_ARRAY(
    ARRAY[['Seth', 'Joseph'],
    ['John', 'Joe'], 
    ['Mike', 'Ambrose'],
    ['Seth', 'Stephen']], -2
    );

The output snippet shows that an error occurs when we tried to pass a negative value.

 **Example 4: Using the TRIM_ARRAY() Function on Table’s Data**

In this example, we will use an already created table named “std_info”:
    
    
    SELECT * FROM std_info;

Let’s use the TRIM_ARRAY() function on the “std_num” column to trim 3 values from each array:
    
    
    SELECT std_name, std_num, TRIM_ARRAY(std_num, 3)
    FROM std_info;

The output shows that 3 elements have been trimmed from the “std_num” array.

 **Conclusion**

In PostgreSQL, the TRIM_ARRAY() function accepts an array and the number of elements to be trimmed as arguments. As a result, it trimmed the specified number of elements from the end of the given array and return a newly updated array. It accepts a positive integer as the second argument, passing a negative integer will result in an error. This write-up has explained the usage of the Postgres TRIM_ARRAY() function with appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-trim_array-function-in-postgresql/)

---

# How to Join Three Tables in PostgreSQL

> PostgreSQL uses the INNER JOIN to get matching results from two or more tables based on the defined join conditions.

PostgreSQL is a famous relational database that is freely available for all operating systems like Windows, Linux, and MacOS. In relational databases, different tables are linked with each other using various constraints. To get the related information from different tables, you might need to merge various tables. To do that, the Joins can be used in databases. PostgreSQL supports various types of JOINS, such as “INNER JOIN”, “OUTER JOIN”, “NATURAL JOIN”, “SELF JOIN”, etc.

This post will explain how to use the Postgres **INNER JOIN** to merge three different tables.

 **How to Join Three Tables in PostgreSQL?**

Postgres uses the INNER JOIN to get matching results from two or more tables based on the defined join conditions.

Use the below syntax to combine multiple tables using “INNER JOIN”:
    
    
    SELECT <tab_1.col_names >, <tab_2.col_names>, <tab_3.col_names>
    FROM <tab_1>
    INNER JOIN <tab_2>
    ON <table_1.col_name> = <tab_2.col_name>;
    INNER JOIN <tab_3>
    ON <tab_3.col_name> = <tab_2.col_name>;

Here, in the above syntax:

\- “tab_1”, “tab_2”, and “tab3” represents the tables to be joined.  
\- To avoid ambiguity, the tables’ columns must be specified with the table name, such as “tab_1.col_name”, “tab_2.col_name”, and tab_3.col_name.  
\- The “INNER JOIN” joins the given tables on the basis of the defined JOIN condition.  
\- The “ON” clause specifies the joining condition.

 **Example: Joining Three Tables in Postgres**

Suppose we have already created three sample tables named “emp_bio”, “dpt_info”, and “emp_details''. All three tables are connected via the foreign key constraint.

 **Step 1: Get Tables’ Data**

Let’s type the “SELECT *” command to fetch all the tables:
    
    
    SELECT * FROM emp_bio;

The “e_id” column is defined as a primary key in the “emp_bio” table.

Now, run the “SELECT” command to fetch the results from the “dpt_info” table:
    
    
    SELECT * FROM dpt_info;

The “dpt_id” column is defined as a primary key in the “dpt_info” table.

The final table is “emp_details” which contains the following records:
    
    
    SELECT * FROM emp_details;

In the “emp_details” table, the “e_id” and “dpt_id” are foreign keys.

 **Step 2: Join Three Tables’ Data**

Now use the INNER JOIN to combine the three given tables:
    
    
    SELECT emp_bio.e_name, emp_bio.emp_name, 
    dpt_info.dpt_name, emp_salary
    FROM emp_bio
    INNER JOIN emp_details
    ON emp_bio.e_id = emp_details.e_id
    INNER JOIN dpt_info
    ON dpt_info.dpt_id = emp_details.dpt_id;

In this example:

\- The SELECT statement specifies the columns to be fetched from all three tables.  
\- The first INNER JOIN is utilized to merge the “emp_bio” and “emp_details” tables based on the “e_id” column.  
\- The second INNER JOIN is utilized to combine the emp_info table with the other two tables based on the “dpt_id” column:

The output demonstrates that the given three tables have been joined successfully.

 **Conclusion**

Postgres uses the INNER JOIN to get matching results from two or more tables based on the defined join conditions. The “ON” clause is utilized with the INNER JOIN to define a joining condition. To avoid ambiguity, the tables’ columns must be specified with the table name. This article has explained how to use the INNER JOIN to combine three different tables in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-join-three-tables-in-postgresql/)

---

# How to Get/Check Yesterday’s Date in PostgreSQL

> In Postgres, there is no such function that directly retrieves yesterday’s date. However, any Postgres function that returns today’s date can be used with the …

PostgreSQL facilitates us with numerous Date and Time functions, such as NOW(), CURRENT_TIME, CURRENT_TIMESTAMP, etc. These functions assist us in storing or retrieving the date and time values smoothly. Postgres offers various functions that retrieve today’s date time. However, there is no such function that directly retrieves yesterday’s date.

This article will illustrate a complete guide on getting yesterday’s date.

 **How to Get/Check Yesterday’s Date in Postgres?**

Any Postgres function that retrieves today’s date can be used with the “-” operator to get yesterday’s date. Here are some frequently used functions that retrieve today’s date:

  * CURRENT_DATE
  * NOW()
  * CURRENT_TIMESTAMP



Let’s consider the below examples to learn how to use any of the above-provided functions to fetch yesterday’s date.

 **Example 1: Getting Yesterday’s Date Using CURRENT_DATE Function**

In the following example, the CURRENT_DATE function will be utilized to get the day before today’s date:
    
    
    SELECT CURRENT_DATE AS today,
    CURRENT_DATE - INTEGER '1' AS yesterday;

In the above snippet, we utilized the “CURENT_DATE” function to get today’s and yesterday’s dates side-by-side:

The output shows that the CURRENT_DATE function successfully retrieves yesterday's date.

 **Example 2: Getting Yesterday’s Date Using NOW() Function**

Alternatively, the NOW() function can be used with the “-” operator to achieve the same functionality. However, the NOW() function retrieves a timestamp value, therefore, it must be cased to the DATE data type:
    
    
    SELECT NOW() AS today,
    NOW():: DATE - INTEGER '1' AS yesterday;

Similarly, the CURRENT_TIMESTAMP function can also be used to get yesterday’s date:
    
    
    SELECT CURRENT_TIMESTAMP AS today,
    CURRENT_TIMESTAMP:: DATE - INTEGER '1' AS yesterday;

The output demonstrates that the CURRENT_TIMESTAMP() function successfully retrieves yesterday's date.

 **Example 3: Getting Yesterday’s Date Using INTERVAL**

Yesterday’s data can also be fetched by using the CURRENT_DATE function with an INTERVAL. Here is an example code:
    
    
    SELECT CURRENT_DATE AS today,
    (CURRENT_DATE - INTERVAL'1 day') :: DATE AS yesterday;

The output proves that yesterday’s date has been successfully retrieved.

 **Conclusion**

Postgres offers various functions that retrieve today’s date time. However, there is no such function that directly retrieves yesterday’s date. Any Postgres function that retrieves today’s date can be used with the “-” operator to get yesterday’s date. For instance, the “SELECT CURRENT_DATE - INTEGER '1' AS yesterday;” retrieves yesterday’s date in Postgres. This article has explained various methods to get yesterday’s date in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-getcheck-yesterdays-date-in-postgresql/)

---

# How to Uninstall PostgreSQL on CentOS?

> To uninstall PostgreSQL from CentOS, execute the “yum remove postgresql-server postgresql-contrib” command.

The purpose of uninstalling PostgreSQL on CentOS is to remove the PostgreSQL software and all associated components from the system. There could be several reasons to uninstall PostgreSQL, such as upgrading or downgrading with different versions, reinstalling, releasing disk space, and many more.

This article will teach the step-by-step procedure to uninstall PostgreSQL from CentOS.

\- How to Uninstall PostgreSQL on CentOS?  
\- Stop the PostgreSQL Service  
\- Remove the PostgreSQL Package  
\- Remove the PostgreSQL Data Directory  
\- Remove the PostgreSQL User

 **How to Uninstall PostgreSQL on CentOS?**

Uninstalling PostgreSQL on CentOS refers to the process of removing PostgreSQL software and all associated components, such as the data directory, configuration files, and user accounts, from a CentOS system.

To uninstall PostgreSQL on CentOS, follow the below steps:

 **Step 1: Stop the PostgreSQL Service**

Before users uninstall PostgreSQL, users need to stop the PostgreSQL service. For this, run the following command:
    
    
    $ systemctl stop postgresql

 **Step 2: Remove the PostgreSQL Package**

Once the service has stopped, remove the PostgreSQL package using the “ **yum** ” package manager. To do this, run the following command:
    
    
    $ sudo yum remove postgresql-server postgresql-contrib

This command removes the PostgreSQL server and the contrib package.

 **Step 3: Remove the PostgreSQL Data Directory**

After removing the package, users need to remove the PostgreSQL data directory. By default, the data directory is located at “/ **var/lib/pgsql/data** ”. To remove this directory and its contents execute the following command:
    
    
    $ sudo rm -rf /var/lib/pgsql/data

 **Step 4: Remove the PostgreSQL User**

Finally, users need to remove the PostgreSQL user. For this, run the below command as the root user:
    
    
    # userdel postgres

This command removes the PostgreSQL user from the system.

 **Conclusion**

To uninstall PostgreSQL from CentOS, execute the “ **yum remove postgresql-server postgresql-contrib** ” command. It removes all the associated packages with the dependencies. Users can also remove the PostgreSQL data directory by running the “sudo rm -rf /var/lib/pgsql/data” command in the terminal. This article has presented step-by-step guidelines to uninstall PostgreSQL from CentOS.

---
[View this page online](https://www.commandprompt.com/education/how-to-uninstall-postgresql-on-centos/)

---

# PostgreSQL SELECT INTO Statement With Examples

> In PostgreSQL, the SELECT INTO statement creates a new table, copies data from the original table, and pastes it into the newly created table.

In PostgreSQL, the **SELECT INTO** statement performs various functionalities in one go. The stated command creates a new table, copies data from the original table, and pastes it into the newly created table. The newly created table will have the same structure as the original/selected table. Using the SELECT INTO command a partial, or a complete table can be copied or duplicated.

This post explains how to use the Postgres SELECT INTO command to copy data from the selected table into a new temporary or regular table.

 **PostgreSQL SELECT INTO Statement**

The “ **SELECT INTO** ” statement can be used as an alternative to the CREATE TABLE AS statement. Since both commands let us create a new table based on some other table.

Here is the syntax of the SELECT INTO statement:
    
    
    SELECT col_list
    INTO [ TEMPORARY | TEMP | UNLOGGED ] [ TABLE ] new_tab_name
    FROM tab_name
    WHERE condition;

In this syntax:

\- The “col_list” represents the columns to be selected from the original table.  
\- “TEMPORARY”, “TEMP”, “UNLOGGED”, and “TABLE” keywords are used to define a new temporary, unlogged, or regular table.  
\- The “WHERE” clause lets us specify particular criteria for copying the data from the actual table to the newly created table.

Different clauses can be used with the “ **SELECT INTO** ” statement to perform different operations on the tables, such as the WHERE, INNER JOIN, GROUP BY, etc.

 **How Does the SELECT INTO Statement Work in Postgres?**

The working of the SELECT INTO statement is illustrated below:

\- First, it selects or fetches the data from the original table.  
\- Next, it creates a new table or temporary table.  
\- Finally, it inserts the selected data from the original table and puts it into the newly created table.

Let’s understand the SELECT INTO statement via the following examples.

 **Example 1: Copying Data to Regular Postgres Table**

We have already created a table with the following records:
    
    
    SELECT * FROM emp_details;

Now, utilize the SELECT INTO command to copy the “emp_id” and “emp_name” columns of the “emp_info” table into a new table named “emp_info_copy”:
    
    
    SELECT emp_id, emp_name
    INTO TABLE emp_info_copy
    FROM emp_info;

To verify the working of the SELECT INTO command, use the following command:
    
    
    SELECT * FROM emp_info_copy;

The output proves that the selected records have been copied into the “emp_info_copy” table.

 **Example 2: Copying Data to a Temporary Table**

In the following code, we will utilize a TEMP keyword with the SELECT INTO command to copy the data from the “emp_info” table into a newly created temporary table:
    
    
    SELECT *
    INTO TEMP TABLE emp_temp_table
    FROM emp_info;

Execute the below command to confirm the table’s duplication:
    
    
    SELECT * FROM emp_temp_table;

The output states that ten records have been selected from the “emp_info” table and inserted into the “emp_temp_table”.

 **Conclusion**

In PostgreSQL, the **SELECT INTO** statement creates a new table, copies data from the original table, and pastes it into the newly created table. The newly created table will have a similar structure to the actual table. Using the SELECT INTO command a partial, or a complete table can be copied. Different clauses can be used with the “SELECT INTO” statement to perform different operations on the tables, such as the WHERE, INNER JOIN, GROUP BY, etc. This post explained different use cases of the SELECT INTO statement in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-select-into-statement-with-examples/)

---

# PostgreSQL RANK() Function With Examples

> Postgres has a built-in Window function called RANK() that assigns a rank to every single row within a partition.

Postgres has a built-in Window function called **RANK()** that assigns a rank to every single row within a partition. For instance, in Postgres, the same rank is awarded to all rows that tie for a rank. However, the RANK() function allows us to rank the rows based on the provided columns instead of retrieving the consecutive integers. A frequent use case of the RANK() function is creating reports for the top N or bottom N records.

This post explains the usage of the RANK() function using practical examples.

 **How to Use the RANK() Function in PostgreSQL?**

In PostgreSQL, the “RANK()” function is used with the “OVER” clause, as illustrated in the following syntax:
    
    
    RANK() OVER (
    [PARTITION BY partition_exp, ... ] 
    ORDER BY sorting_exp [ASC | DESC], ...
    )

Here in this syntax:

\- The “PARTITION BY” clause splits the records of the result set into partitions or groups and the RANK() function is applied to each partition.  
\- The “ORDER BY” clause sorts the rows of each partition(in ascending or descending order) to which the RANK() function is applied.

Let’s put this concept into practice for a deep understanding.

 **Example 1: How Does the RANK() Function Work in Postgres?**

In this example, we will utilize a “programming_languages” table that we have already created in our database:
    
    
    SELECT * FROM programming_languages;

In the following example, the RANK() function is used on the “programming_languages” to assign a rank to each row based on the “language” column:
    
    
    SELECT language,
    RANK () OVER ( 
    ORDER BY language 
    ) 
    FROM
    programming_languages;

The output shows that instead of assigning a consecutive integer, a rank has been assigned to each row based on the “language” column.

 **Example 2: How Does the RANK() Function Work With the Postgres PARTITION BY Clause?**

This example explains the usage of the RANK() function with the PARTITION BY clause:
    
    
    SELECT *,
    RANK () OVER ( 
    PARTITION BY language
    ORDER BY id
    ) 
    FROM
    programming_languages;

The output demonstrates that partitions have been created based on the “language” and a particular rank is assigned to each row of a partition.

 **Conclusion**

Postgres has a built-in Window function called **RANK()** that assigns a rank to every single row within a partition. For instance, in Postgres, the same rank is awarded to all rows that tie for a rank. However, the RANK() function allows us to rank the rows based on the provided columns instead of retrieving the consecutive integers. This post explained the usage of the RANK() using appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-rank-function-with-examples/)

---

# PostgreSQL Subquery Explained With Examples

> A subquery in PostgreSQL is nothing more than a query within another query. It is also called a nested query, inner query, or inner select.

In relational databases like PostgreSQL, various tables are linked with each other to manage a large amount of data efficiently. While working with relational databases you may encounter a situation where you have to select numerous records from different tables and then filter them based on specific criteria. This process may require writing a large amount of unnecessary and redundant code. In such scenarios, the “Subqueries” can be proved very useful.

This write-up will explain the usage of the Postgres “Subqueries” using suitable examples.

 **What is a Subquery in Postgres?**

A subquery in Postgres is a query within another query. It can also be named as an inner select, nested query, or inner query. While the query that contains a subquery is referred to as an outer query, main query, or outer select.

The following guidelines must be considered before using a subquery:

\- A subquery must be wrapped/enclosed inside the parenthesis.  
\- Subqueries can be utilized with the FROM, SELECT, DELETE, UPDATE, INSERT, or WHERE clauses.  
\- In the WHERE clause, conditional operators like =, >, <, >=, <=, IN, or EXISTS can be used.  
\- The ORDER BY can be utilized with the main/outer query, however, it can’t be utilized with the inner/subquery.  
\- A subquery that retrieves multiple records can only be utilized with multi-value operators, such as IN, ANY/SOME, EXISTS, ALL, etc.  
\- The BETWEEN operator can’t be used with the subquery; however, it can be used inside the subquery.

 **How to Write or Define a Subquery in Postgres?**

In Postgres, a subquery is mostly used with the WHERE clause. So, you must follow the below-provided syntax to write a subquery:
    
    
    SELECT column_name [, col_name ]
    FROM table
    WHERE expression OPERATOR
    (SELECT col_name [, col_name ]
    FROM table
    [WHERE]
    )

In the above syntax:

\- The query specified within the parenthesis represents the inner query.  
\- The inner/subquery will execute before the outer/main query.  
\- The result of the inner query will be used as a condition in the WHERE clause of the outer query.

 **How to Use a Subquery in Postgres?**

This section describes the usage of the Postgres subquery with:

\- WHERE Clause  
\- IN Operator  
\- EXIST Operator

 **Example 1: What is the Need for the Subqueries in Postgres?**

Assume we have to fetch the details of employees having salaries above the average salary. For this, first, we must find the average salary. After that, we can utilize the average salary to filter the employees having salaries greater than the average salary.

The following snippet depicts the data of the sample table:

To find the average employee salary, utilize the AVG() function as follows:
    
    
    SELECT AVG(emp_sal)
    FROM emp_bio;

The output depicts that the average employee salary is “44000”. Utilize the following command to get the employees with an average salary greater than or equal to “44000”:
    
    
    SELECT e_id, emp_name, emp_sal
    FROM emp_bio
    WHERE emp_sal >= 44000;

Executing the above query will filter the employees' data based on the average salary:

The result signifies that the employees' data has been successfully filtered. However, the code is not optimized/efficient, as it involves two steps. To wrap both steps into one, use the subquery.

 **Example 2: Using Subquery With a Postgres WHERE Clause**

The following code explains the usage of the Postgres subquery with the WHERE clause:
    
    
    SELECT e_id, emp_name, emp_sal
    FROM emp_bio
    WHERE emp_sal >= (
    SELECT AVG (emp_sal)
    FROM emp_bio );

The above query will be executed in the following sequence:

\- First, the INNER SELECT (subquery) will be executed.  
\- Next, the results retrieved by the INNER SELECT will be passed to the OUTER SELECT.  
\- Finally, the OUTER SELECT will be executed based on the results of the INNER SELECT.

The output shows that the subquery successfully retrieves the filtered data.

 **Example 3: Using Subquery With a Postgres IN Operator/Clause**

Use the subquery with the IN operator to retrieve zero or more rows from the INNER SELECT. Consider the following query for a profound understanding:
    
    
    SELECT e_id, emp_salary
    FROM emp_details
    WHERE dpt_id IN 
    (SELECT dpt_id
    FROM dpt_info
    WHERE dpt_name = 'Writing Department');

In the above query:

\- The “emp_details” and “dpt_info” tables are used that are linked with each other via a foreign key.  
\- The inner query will filter the records based on the “Writing Department”.  
\- The IN operator will check the list of values returned by the nested SELECT.  
\- Finally, the query retrieves the employee’s id and salary whose department is “Writing Department”:

The output demonstrates that the subquery retrieves the filtered records.

 **Example 4: Using Subquery With the EXIST Operator**

The subquery can be used with the EXIST operator to evaluate if it retrieves any rows.
    
    
    SELECT e_id, emp_salary
    FROM emp_details 
    WHERE EXISTS 
    (SELECT 1
    FROM dpt_info
    WHERE dpt_info.dpt_id = emp_details.dpt_id
    );

\- The above query will work as an INNER JOIN on the dpt_id column.  
\- The INNER SELECT will check if a department has at least one employee using the “dpt_info.dpt_id = emp_details.dpt_id” condition.  
\- The INNER SELECT will retrieve true if the specified condition is valid.  
\- Finally, the ids and salaries of those employees will be retrieved who met the specified criteria.

This is how a subquery works with the EXISTS operator.

 **Conclusion**

A subquery in PostgreSQL is nothing more than a query within another query. It is also called a nested query, inner query, or inner select. While the query that contains a subquery is referred to as an outer query, main query, or outer select. In Postgres, the inner SELECT or the subquery executes before the main or outer query. The results retrieved by the inner/nested query are used as a condition in the WHERE clause of the outer/main query. This article explained different use cases of the Postgres subqueries using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-subquery-explained-with-examples/)

---

# PL/pgSQL Record Types Explained With Examples

> In PL/pgSQL, the record types are used to create the variables that can store a complete row/record of a result set.

In PL/pgSQL aka Procedural Language/Postgres, the **record** types are used to create the variables that can store a complete row/record of a result set. The record is not a proper data type, instead, it’s just a variable/placeholder. These variables are the same as the row-type variables; the only difference is that the record variables don’t have a predefined structure while the row-type variable does.

This post explains how to declare, assign and access a record variable in Postgres.

 **PL/pgSQL Record Types**

A record variable can hold a single row returned by a Postgres table or a view. A record-type variable's structure is defined when FOR and SELECT statements assign an actual record/row to such variables. Use the following syntax to declare the record variables:
    
    
    var_name RECORD;

To access a specific field of a record variable, use the following dot syntax:
    
    
    var_name.field_name;

Accessing a record-type field prior to its declaration causes an error. A record variable can be re-assigned and its structure changes when you re-assign it.

Let’s learn the row-type variables practically.

 **Example 1: How to Assign a Complete Row to a Record Type Using SELECT INTO Statement?**

In this example, we will utilize a sample table named “emp_bio” whose details are shown in the below snippet:
    
    
    SELECT * FROM emp_bio;

Let's declare a record-type variable and assigned it a single row:
    
    
    DO $$
    DECLARE emp_info emp_bio%ROWTYPE;
    BEGIN
    SELECT *
    INTO emp_info
    FROM emp_bio
    WHERE e_id = 3;
    RAISE NOTICE 'Employee INFO: %', emp_info;
    END;
    $$

In the above code:

\- A record-type variable named “emp_info” is declared.  
\- The INTO keyword is used to specify the selected row into the “emp_info” variable.  
\- The FROM clause keeps the name of the targeted table, i.e., “emp_bio”.  
\- The WHERE clause defines the selection criteria.  
\- The “RAISE NOTICE” is used to display the variable’s value.

The output shows the complete row that is stored in the “emp_info” variable.

 **Example 2: How to Access a Specific Field of a Record-Type Variable in Postgres?**

In the following code snippet, we will utilize the dot syntax to access an individual field of the record-type variable:
    
    
    DO $$
    DECLARE emp_info RECORD;
    BEGIN
    SELECT *
    INTO emp_info
    FROM emp_bio
    WHERE e_id = 3;
    RAISE NOTICE 'Employee Salary: %', emp_info.emp_sal;
    END;
    $$

The output confirmed that an individual field of the record-type variable has been accessed successfully.

 **Example 3: How to Assign a Complete Row to a Record Type Using For Loop?**

In the below code snippet, we will explain the working of the record variables in the for loop:
    
    
    DO $$
    DECLARE emp_info RECORD;
    BEGIN
    For emp_info IN SELECT emp_name, emp_sal
    FROM emp_bio
    WHERE e_id >= 3
    LOOP
    RAISE NOTICE 'Name: %, Salary: %', emp_info.emp_name, 
    emp_info.emp_sal;
    END LOOP;
    END;
    $$

In this example:

\- A record-type variable named “emp_info” is declared.  
\- The for loop is used to get the employee's name and salary whose id is greater than or equal to 3.  
\- The dot syntax is utilized to access the individual fields of the record-type variable.

This is how you can use the RECORD variable in the for-loop.

 **Conclusion**

In PL/pgSQL, the **record** types are used to create the variables that can store a complete row/record of a result set. The record is not a proper data type, instead, it’s just a variable or a placeholder that holds a single row returned by a Postgres table. These variables are the same as the row-type variables; the only difference is that the record variables don’t have a predefined structure while the row-type variable does. This post presented a detailed guide on record types using practical examples.

---
[View this page online](https://www.commandprompt.com/education/plpgsql-record-types-explained-with-examples/)

---

# PostgreSQL ROW_NUMBER() Function With Examples

> In Postgres, the “ROW_NUMBER()” function is used with the OVER clause to operate on a set of rows and assigns a unique integer to each row.

PostgreSQL provides a built-in Window function named “ **ROW_NUMBER()** ” that operates on a set of rows and assigns a unique integer to each row. The set/collection of records is referred to as a “Window”. The ROW_NUMBER() function assigns the consecutive numbering/ranking to the rows which ultimately assists us in data analysis and manipulation.

This write-up presents a comprehensive guide on the usage of the ROW_NUMBER() function using suitable examples.

 **How to Use the ROW_NUMBER() Function in Postgres?**

In Postgres, “ROW_NUMBER()” is used with the “OVER” clause to get the row number, as depicted in the following syntax:
    
    
    ROW_NUMBER() OVER (
    [PARTITION BY col_list ] 
    [ORDER BY col_list]
    );

\- In Postgres, a “Window” is referred to as the set of rows on which ROW_NUMBER() is applied.  
\- The “PARTITION BY” clause is optional and can be used to split the “window” into partitions or groups.  
\- If the “PARTITION BY” clause is omitted, then the ROW_NUMBER() considers the whole window as one partition.  
\- "ORDER BY" specifies the order in which the numbers will be assigned.

 **Example 1: How Does ROW_NUMBER() Work in Postgres?**

In this example, we will utilize a “programming_languages” table that we have already created in our database:
    
    
    SELECT *,
    ROW_NUMBER() OVER (
    PARTITION BY language
    ORDER BY id DESC
    )
    FROM programming_languages;

In this code:

\- The “ROW_NUMBER()” function is used with the “OVER” clause to get the row number within the associated partition.  
\- The “PARTITION BY” clause is used to split the table by language.  
\- The "ORDER BY" clause organizes the partitions descendingly.

From the output, it is clear that the consecutive ranking has been assigned to the given table.

 **Example 2: ROW_NUMBER() With Subquery**

This example explains how to use the ROW_NUMBER() function with the subquery to get the list of unique records:
    
    
    SELECT DISTINCT *,
    ROW_NUMBER() OVER (
    ORDER BY language
    )
    FROM (
    SELECT DISTINCT language
    FROM programming_languages
    ) 
    programming_languages;

In the above-stated code block:

\- A subquery can be used with the DISTINCT operator to get the unique records.  
\- After that, the ROW_NUMBER() can be utilized in the outer query to assign the numbering to the unique records:

The output shows that the numbering has been assigned to the unique “languages”.

 **Note:** The ROW_NUMBER() works on the result set prior to the DISTINCT clause. Therefore, using a DISTINCT operator with the ROW_NUMBER() wouldn’t exclude the duplicates.

 **Example 3: ROW_NUMBER() for Pagination**

In Postgres, a technique named pagination is used to retrieve chunks of records instead of showing all records of a result set. Usually, the LIMIT clause is used to get the limited data, however, the ROW_NUMBER() can also be used as its alternate. Here is an example:
    
    
    SELECT * FROM
    (SELECT *,
    ROW_NUMBER() OVER (
    ORDER BY language)
    FROM programming_languages
    )
    programming_languages
    WHERE id BETWEEN 4 AND 7;

This query retrieves the records between id 4 and 7 and assigns them consecutive row numbers:

That's all from this Postgres guide on ROW_NUMBER() function.

 **Conclusion**

In PostgreSQL, a built-in Window function named “ **ROW_NUMBER()** ” is used with the OVER clause to operate on a set of rows and assigns a unique integer to each row. The “PARTITION BY” clause is optional and can be used with the ROW_NUMBER() to split the “window” into partitions or groups. If the "PARTITION BY" clause is skipped, the whole window will be treated as a single partition. This post provided a thorough guide on how to use the ROW_NUMBER() function in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-row_number-function-with-examples/)

---

# Constants in PostgreSQL Explained With Examples

> In Postgres, constants are nothing but immutable or unchangeable variables. Once a constant is initialized with a value, it stays the same throughout the progr…

In PostgreSQL, variables are used to store the mutable(changeable) data whereas the **constants** store the immutable(unchangeable) data. Once a constant is initialized with a value, it stays the same in the entire program. Trying to modify the constant’s value will result in an error. Constants offer various features, such as easy code readability, reusability, maintainability, etc.

This post presents a comprehensive guide on Postgres constant along with suitable examples.

 **What are Constants in PostgreSQL?**

In Postgres, constants are nothing but immutable or unchangeable variables. In PostgreSQL, there are three types of implicit constants: String Constants, Integer Constants, and Floating Point Constants. However, for more accuracy and efficiency, Postgres allows us to specify the Constants with explicit, user-defined types.

 **How to Declare a Constant in Postgres?**

The declaration of a constant is the same as the variable’s declaration except for the “ **CONSTANT** ” keyword. The following syntax is used to declare a constant in Postgres:
    
    
    DECLARE const_name CONSTANT data_type := value/expression;

In this syntax:

\- DECLARE is a keyword that is used to declare a constant.  
\- The “const_name” represents any meaningful name of a constant.  
\- CONSTANT is a keyword that ensures its initial value doesn’t change throughout the program.  
\- Data_type can be any valid type, such as INT, TEXT, VARCHAR, etc.  
\- “ **:=** ” or “ **=** ” operators are used to initialize the constant.  
\- Replace the “value/expression” with a valid value or expression based on the specified data type.

Let’s consider the following examples to learn the usage of Postgres CONSTANTS practically.

 **Example 1: Declaring and Printing a Constant**

The below snippet illustrates how to create and print a constant in Postgres:
    
    
    DO $$ 
    DECLARE
    product_price CONSTANT INTEGER := 150;
    BEGIN 
    RAISE NOTICE 'The price of the selected product is %', product_price;
    END $$;

\- First, the “ **DO** ” keyword is used to execute the code block.  
\- Next, an integer constant is declared and initialized within the “ **DECLARE** ” block.  
\- The declared constant is printed in the “ **BEGIN** ” block using the “RAISE NOTICE” statement.

The output shows that the constant has been declared, initialized, and printed successfully.

 **Example 2: Variable is Declared Constant Error**

In the following example, we tried to modify the initial value of the given constant:

DO $$  
DECLARE  
product_price CONSTANT INTEGER := 150;  
BEGIN  
product_price := 140;  
RAISE NOTICE 'The price of the selected product is %', product_price;  
END $$;

The output clearly states that a constant can’t be modified.

 **Example 3: Solving Constant Expression**

In the following example, a variable and a constant are declared in the declaration section:
    
    
    DO $$ 
    DECLARE
    original_price NUMERIC := 120.50;
    discount CONSTANT NUMERIC := 10.0;
    net_cost NUMERIC = original_price - discount;
    BEGIN 
    RAISE NOTICE 'The discounted price of the selected product is %', net_cost;
    END $$;

The constant’s value is subtracted from the variable’s value and the resultant value is printed using the RAISE statement.

 **Example 4: Run Time Evaluation**

PostgreSQL evaluates the constants at run-time, not at compile-time, just like it evaluates the default value of a variable:
    
    
    DO $$ 
    DECLARE
    query_begin_at CONSTANT TIMESTAMP = CURRENT_TIMESTAMP;
    BEGIN 
    RAISE NOTICE 'Query begins at %', query_begin_at;
    perform pg_sleep(10);
    RAISE NOTICE 'Query begins at %', query_begin_at;
    END $$;

In the above code:

\- A constant named “query_begin_at” is declared with the TIMESTAMP data type.  
\- The “query_begin_at” is initialized with the CURRENT_TIMESTAMP.  
\- The value of the given constant is printed using the RAISE statement.  
\- The “pg_sleep()” function is used to put the “10” seconds delay between the execution of the first and the second raise statements.

The output shows that the pg_sleep() function doesn’t make any impact on the current timestamp. To see its impact, let’s invoke the block one more time:

The output proves that Postgres evaluates the CURRENT_TIMESTAMP function each time the block is invoked.

 **Conclusion**

In Postgres, constants are nothing but immutable or unchangeable variables. Once a constant is initialized with a value, it stays the same throughout the program. Assigning a new value to a CONSTANT will result in an error stating "variable is declared constant". This post explained what a constant is, and how to declare and use it in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/constants-in-postgresql-explained-with-examples/)

---

# PL/pgSQL SELECT INTO Statement - Assign Data to a Variable

> PostgreSQL supports a “PL/pgSQL SELECT INTO” statement that assists us in storing the table&#x27;s data into a specific variable.

In PostgreSQL, the PL/pgSQL **SELECT INTO** statement helps us store the table's data into a specific variable. The PL/pgSQL SELECT INTO statement fetches the data from a particular table and assigns it to the given variable. Different clauses can be used with the PL/pgSQL SELECT INTO statement for different purposes, such as the WHERE clause, GROUP BY clause, JOIN, etc.

This article explains how to use the PL/pgSQL SELECT INTO command to copy data from the selected table into a specific variable.

 **PL/pgSQL SELECT INTO Statement - Assign Data to a Variable**

Follow the below instructions to assign data from a table to a variable:

\- Specify the SELECT statement followed by the select expression.  
\- After that, utilize the INTO keyword followed by the variable name.  
\- Finally, specify the table’s name in the FROM clause.

Here, is the basic syntax for the PL/pgSQL SELECT INTO statement:
    
    
    SELECT select_expression
    INTO var_name
    FROM tab_name;

 **Example 1: How to Use PL/pgSQL SELECT INTO Statement?**

A sample table with the following records has been already created in the database:
    
    
    SELECT *
    FROM emp_bio;

Suppose we want to assign the total number of employees to a specific variable. For this, we will utilize the SELECT INTO statement, as follows:
    
    
    DO $$
    DECLARE emp_counter INTEGER;
    BEGIN
    SELECT COUNT(*)
    INTO emp_counter 
    FROM emp_bio;
    RAISE NOTICE 'Total Employees: %', emp_counter;
    END;
    $$

In the above code:

\- An integer variable named “emp_counter” is declared.  
\- The COUNT(*) is used to count the rows that match the specified criteria.  
\- The INTO keyword is used to specify the rows count into the “emp_counter” variable.  
\- The FROM clause keeps the name of the targeted table, i.e., “emp_bio”.  
\- The “RAISE NOTICE” is used to display the variable’s value.

The output shows that the total number of employees has been assigned to the emp_counter variable.

 **Example 2: How to Use PL/pgSQL SELECT INTO Statement With WHERE Clause?**

In the following example, the WHERE clause is used with the SELECT INTO statement to copy the table’s data on specific criteria:
    
    
    DO $$
    DECLARE emp_count INTEGER;
    BEGIN
    SELECT COUNT(*)
    INTO emp_count
    FROM emp_bio
    WHERE emp_sal > 40000;
    RAISE NOTICE 'Total Employees Having Salary More than 40k: %', emp_count;
    END;
    $$

The clause will filter the employees based on their salary. Only those employees will be counted and assigned to the “emp_count” variable whose salary is more than 40,000”:

The output verified that only filtered data is assigned to the given variable.

 **Conclusion**

PostgreSQL supports a “ **PL/pgSQL SELECT INTO”** statement that assists us in storing the table's data into a specific variable. The stated command fetches the data from a particular table and assigns it to a specific variable. Different clauses can be used with the PL/pgSQL SELECT INTO statement for different purposes, such as the WHERE clause, GROUP BY clause, JOIN, etc. This post presented a detailed guide on how to assign a table's data to a variable using the SELECT INTO command in Postgres.

---
[View this page online](https://www.commandprompt.com/education/plpgsql-select-into-statement-assign-data-to-a-variable/)

---

# PostgreSQL Schema Search Path

> In PostgreSQL, the SET SEARCH_PATH command is used to set the schema search path. The “SHOW” command is used to demonstrate the current schema search path.

In RDBMS like Postgres, the schemas are used to define a way of organizing the data. It is a collection of logical structures such as tables, views, data types, constraints, functions, etc. In PostgreSQL, the schema **SEARCH_PATH** represents an environment variable. By default, the objects are created in the public schema, however, setting the **SEARCH_PATH** allows us to store the tables, views, functions, etc. in a particular schema.

This post presents a detailed guide on the Postgres search path.

 **PostgreSQL Schema Search Path**

The following topics will be covered regarding the PostgreSQL schema search path using practical demonstration:

\- How to Show the Current Search Path in Postgres?  
\- How to Set the Search Path for the Current Session?  
\- How to Set a Permanent Search Path for a Database?  
\- How to Reset SEARCH_PATH for a Specific Database?  
\- How to Set a Permanent Search Path for a User/Role?  
\- How to Reset SEARCH_PATH for a Specific Role/User?

 **How to Show the Current Search Path in Postgres?**

In Postgres, the “SHOW” command is used to demonstrate the current schema search path:
    
    
    SHOW SEARCH_PATH;

The output displays that the current search path is public.

 **How to Set Search Path for Current Session?**

Execute the “\dn” command to fetch the available schemas:
    
    
    \dn;

Suppose we want to set the search path from “public” to “postgres_schema” for the current session. For this purpose, we will use the “SET” command as follows:
    
    
    SET SEARCH_PATH = postgres_schema;

The search path has been set for the current session. Execute the “SHOW” command for the confirmation:
    
    
    SHOW SEARCH_PATH;

The output snippet demonstrates that the “postgres_schema” has been set as the default search path for the current session. The search path will be reset to the "public" schema once the current session expires.

 **How to Set a Permanent Search Path for a Database?**

To set a permanent search path for a database, use the “ALTER DATABASE” command followed by the “SET SEARCH_PATH” command:
    
    
    ALTER DATABASE postgres SET SEARCH_PATH TO postgres_schema;

\- Here, “postgres” is the name of the current database.  
\- The “postgres_schema” represents the schema to be set as the search path.  
\- The above command will change the schema search path at the database level, permanently.

For confirmation, execute the “SHOW SEARCH_PATH” command:
    
    
    SHOW SEARCH_PATH;

The output shows that the schema search path has been set successfully.

 **How to Reset SEARCH_PATH for a Specific Database?**

Execute the ALTER DATABASE command along with the RESET command to unset the current SEARCH_PATH to the default SEARCH_PATH:
    
    
    ALTER DATABASE postgres RESET SEARCH_PATH;

Let’s confirm the search path for the “postgres” database using the following command:
    
    
    SHOW SEARCH_PATH;

The search path has been unset to the default schema/search path.

 **How to Set a Permanent Search Path for a User/Role?**

Use the “ALTER USER” command with the “SET” command to set the search path at the user level:
    
    
    ALTER USER postgres SET SEARCH_PATH TO example_user;

To confirm the search path for the “postgres” user, execute the “SHOW” command as follows:
    
    
    SHOW SEARCH_PATH;

The search path for the “postgres” user has been successfully changed to the “example_user”.

 **How to Reset SEARCH_PATH for a Specific Role/User?**

Use the ALTER USER or ALTER ROLE command with the RESET command to rest the search path for a specific role:
    
    
    ALTER USER postgres RESET SEARCH_PATH;

To confirm the search path for the “postgres” user use the “SHOW” command, as follows:
    
    
    SHOW SEARCH_PATH;

The search path for the “postgres” user has been reset to the default search path.

 **Conclusion**

In PostgreSQL, the SET SEARCH_PATH command is used to set the schema search path. The SET SEARCH_PATH sets the search path for the current session only, however, it can be set permanently at the user or database level. For this purpose, use the SET SEARCH_PATH command along with the ALTER DATABASE or ALTER ROLE command. This post presented a detailed guide on how to set or reset the default schema search path in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-schema-search-path/)

---

# How to Insert a Timestamp into a PostgreSQL Table

> The inbuilt date functions like NOW(), CURRENT_TIMESTAMP, and LOCALTIMESTAMP, are used with the INSERT statement to add the current timestamp into a Postgres t…

Postgres supports various temporal data types, such as DATE, TIMESTAMP, TIME, etc. Among them, the **TIMESTAMP** and **TIMESTAMPTZ** are used to store the date and time values with or without time zone information. A table’s column created with TIMESTAMP or TIMESTAMPTZ data type has the ability to store the current timestamp or any specific timestamp.

This Postgres blog presents a detailed guide on how to insert the current or any specific timestamp in Postgres.

 **How to Insert a Timestamp into a Postgres Table?**

The need for the **TIMESTAMP** data type arises when we have to keep/save the date and time values in a particular database. For instance, the TIMESTAMP data type can be handy in scenarios where we have to maintain the staff’s check-in and check-out record, the customer’s order placement DateTime, the flight’s arrival and departure record, etc.

 **Syntax**

Utilize the following syntax to create/define a table’s column with TIMESTAMP data type:
    
    
    CREATE TABLE tab_name(
    col_name TIMESTAMP | TIMESTAMPTZ constraint
    );

\- col_name represents a column to be defined with the TIMESTAMP data type.  
\- Use either TIMESTAMP or TIMESTMAPTZ data type.  
\- Specify the constraint of your choice such as PRIMARY KEY, CHECK, UNIQUE, etc. in place of constraint.

 **Example 1: Creating a Table Column With Timestamp**

Let’s create a sample table named staff_info with the following columns: e_id, e_name, and e_joining_date:
    
    
    CREATE TABLE staff_info(
    e_id INT PRIMARY KEY,
    e_name TEXT,
    e_joining_date TIMESTAMP
    );

The “staff_info” table with the specified columns has been successfully created.

 **Note:** Use the TIMESTAMPTZ data type instead of the TIMESTAMP to store the DateTime values along with the time zone.

 **Example 2: Inserting a Specific Timestamp Into a Postgres Table**

Use the INSERT query to insert a particular timestamp into the “staff_info” table:
    
    
    INSERT INTO staff_info(e_id, e_name, e_joining_date)
    VALUES (1, 'Joe', '2022-10-10 11:30:30');

Let’s fetch the newly inserted record via the “SELECT” command:
    
    
    SELECT * FROM staff_info;

A particular timestamp has been inserted into the staff_info table.

 **Example 3: Inserting the Current Timestamp Into a Postgres Table**

The inbuilt date functions like NOW(), CURRENT_TIMESTAMP and LOCALTIMESTAMP can be used with the INSERT statement to insert the current timestamp into a Postgres table:
    
    
    INSERT INTO staff_info(e_id, e_name, e_joining_date)
    VALUES (2, 'Natie', CURRENT_TIMESTAMP),
    (3, 'Seth', LOCALTIMESTAMP),
    (4, 'Joseph', NOW());

In the above query, three different DateTime functions are used to insert the current timestamp in the “staff_info” table:

To confirm the newly inserted records, utilize the “SELECT *” command:
    
    
    SELECT * FROM staff_info;

This way, you can insert the current timestamp into any specific Postgres table.

 **Conclusion**

In PostgreSQL, the **TIMESTAMP** and **TIMESTAMPTZ** are used to store the date and time values with or without time zone information. The inbuilt date functions like NOW(), CURRENT_TIMESTAMP, and LOCALTIMESTAMP, are used with the INSERT statement to add the current timestamp into a Postgres table. This post considered different examples to explain how we can insert a specific or current timestamp into a Postgres table.

---
[View this page online](https://www.commandprompt.com/education/how-to-insert-a-timestamp-into-a-postgresql-table/)

---

# PL/pgSQL Row Types - Assign Complete Row to a Variable in PostgreSQL

> In PL/pgSQL, the row-type variables aka row variables are used to store a complete record of a result set into a specific variable.

The term PL/pgSQL refers to the Procedural Language/Postgres. In PL/pgSQL, the row-type variables aka row variables are used to store a complete record of a result set into a specific variable. Although, the row variables keep the whole row, however, an individual field of a specific row-type variable can be accessed using the dot syntax.

This post explains how to assign a complete row to a variable in Postgres using the row-type variables.

 **PL/pgSQL Row Types - Assign Complete Row to a Variable in Postgres**

To work with row variables, first, you must learn how to declare them. A row variable can hold a row returned by a Postgres table or a view. Here, is the basic syntax that allows you to declare the row variables:
    
    
    row_var_name tab_name%ROWTYPE;
    
    
    row_var_name view_name%ROWTYPE;

In this syntax:

\- “row_var_name” represents the variable’s name.  
\- “tab_name” and “view_name” represent the targeted table or view.  
\- The “tab_name” and “view_name” must be followed by the “%ROWTYPE” to declare a row variable.

Use the following dot syntax to access a specific field of a row-type variable.
    
    
    row_var_name.field_name;

Let’s learn the row-type variables practically.

 **Example 1: How to Assign a Complete Row to a Variable in Postgres?**

In the following example, we will utilize a sample table named “emp_bio” whose details are depicted in the following snippet:
    
    
    SELECT * FROM emp_bio;

Let's declare a row-type variable and assigned it a complete row:
    
    
    DO $$
    DECLARE emp_info emp_bio%ROWTYPE;
    BEGIN
    SELECT *
    INTO emp_info
    FROM emp_bio
    WHERE e_id = 3;
    RAISE NOTICE 'Employee INFO: %', emp_info;
    END;
    $$

In the above code:

\- A row-type variable named “emp_info” is declared.  
\- The INTO keyword is used to specify the selected row into the “emp_info” variable.  
\- The FROM clause keeps the name of the targeted table, i.e., “emp_bio”.  
\- The WHERE clause defines the selection criteria.  
\- The “RAISE NOTICE” is used to display the variable’s value.

The output shows the complete row that is stored in the “emp_info” variable.

 **Example 2: How to Access a Specific Field of a Row-Type Variable in Postgres?**

In the following code snippet, we will utilize the dot syntax to access an individual field of the row-type variable:
    
    
    DO $$
    DECLARE emp_info emp_bio%ROWTYPE;
    BEGIN
    SELECT *
    INTO emp_info
    FROM emp_bio
    WHERE e_id = 3;
    RAISE NOTICE 'Employee Salary: %', emp_info.emp_sal;
    END;
    $$

The output verifies that an individual field of the row-type variable has been successfully accessed.

 **Conclusion**

In PL/pgSQL, the row-type variables aka row variables are used to store a complete record of a result set into a specific variable. A row-type variable can be declared with the same data type as the table’s selected row by using the “row_var_name tab_name%ROWTYPE” syntax. The dot syntax is used to access an individual field of a row-type variable. This post explained how to declare, assign, and access a row-type variable in Postgres using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/plpgsql-row-types-assign-complete-row-to-a-variable-in-postgresql/)

---

# How to Restart PostgreSQL Server on Linux

> The Postgres server can be restarted using the “/etc/init.d/postgresql restart” or “sudo systemctl restart postgresql” commands.

PostgreSQL is a widely used relational database that is compatible with various operating systems, such as Windows, Linux, and MacOS. Installing PostgreSQL on Linux allows users to perform various database functions efficiently, such as storing, managing, and retrieving large amounts of data. However, sometimes you may need to restart the Postgres server because of various reasons, such as when the server is inactive/dead, to enforce updates, when a system crashes, a lag occurs, etc.

This post is going to present a step-by-step guide on restarting the PostgreSQL server on the Linux operating system.

 **How to Restart Postgres Server on Linux(Ubuntu)?**

The Postgres Server can be restarted using various methods. In this write-up the below-given methods will be demonstrated to restart the Postgres server on Linux:

\- Method 1: Using the “/etc/init.d/postgresql” Directory  
\- Method 2: Using the “systemctl” Command

 **How to Restart Postgres on Linux Using the “/etc/init.d/postgresql” Directory?**

Follow the given instructions to restart a Postgres server on Linux without any obstacles:

 **Step 1: Check the Postgres Status**

Open the terminal and run the following “sudo” command to see the current status of the Postgres server:
    
    
    /etc/init.d/postgresql status

The output shows that the Postgres server is currently inactive.

 **Step 2: Restart the Postgres Server**

Use the below command to restart the Postgres server via the “/etc/init.d/postgresql” directory:
    
    
    /etc/init.d/postgresql restart

The output shows that the stated command was executed successfully.

 **Step 3: Verify the Postgres Status**

Use the “/etc/init.d/postgresql” directory with the “status” option to verify the Postgres status:
    
    
    /etc/init.d/postgresql status

The output shows that the Postgres Server has been activated/restarted successfully.

 **How to Restart Postgres Server on Linux Using the “systemctl” Command?**

Let’s head towards the below-listed steps to learn how to restart Postgres Server on Linux:

 **Step 1: Check the Status**

Type the following “systemctl” command to see the current status of the Postgres server:
    
    
    sudo systemctl status postgresql

The output shows that the Postgres server is currently not functioning.

 **Step 2: Restart the Postgres Server**

Type the following sudo command to restart the Postgres server:
    
    
    sudo systemctl restart postgresql

The output shows that the input command was executed successfully.

 **Step 3: Confirm the Status**

To confirm that if Postgres is restarted or not, use the "systemctl" command with the "status" option:
    
    
    sudo systemctl status postgresql

The output proves that the Postgres server has been restarted successfully.

 **Conclusion**

The Postgres server can be restarted using the “/etc/init.d/postgresql restart” or “sudo systemctl restart postgresql” commands. The status of the Postgres server can be confirmed by executing these commands with the “status” option. In Postgres, the need to restart the Postgres server arises because of various reasons, such as to activate the dead server, enforce updates, tackle system crashes, overcome lags, etc. This article has explained the step-by-step guide on restarting the PostgreSQL server on Linux.

---
[View this page online](https://www.commandprompt.com/education/how-to-restart-postgresql-server-on-linux/)

---

# How Does the CEILING() Function Work in PostgreSQL?

> In Postgres, CEILING() is a built-in math function that accepts a numeric or double precision value and converts it into the nearest integer toward the positiv…

PostgreSQL supports various mathematical functions that help us round a numeric value up to the specified decimal places. CEILING() is one such function that rounds the given decimal number up to the nearest integer. It is the equivalent of the CEIL() function, as both these functions round up the given to the nearest integer. It is equally effective for rounding negative numbers.

This post explains the various use cases of the CEILING() function along with suitable examples.

 **How Does the CEILING() Function Work in Postgres?**

In Postgres, CEILING() is a built-in math function that accepts a numeric or double precision value and converts it into the nearest integer toward the positive infinity. Here is the basic syntax:
    
    
    CEILING(num);

Where num represents any positive or negative numeric or double precision number. The return type of the CEILING() function depends on the data type of the input value.

 **Example 1: Using CEILING() Function With Positive Value**

In the following example, the CEILING function is utilized on a positive value to get a rounded value:
    
    
    SELECT CEILING(250.77);

The output signifies that the input numeric value has been rounded up to the nearest integer.

 **Example 2: Using CEILING() Function With Negative Value**

In the following example, the CEILING function is utilized on a negative to get a rounded integer:
    
    
    SELECT CEILING(-250.77);

The output verifies that the given numeric value has been rounded up to the nearest integer.

 **Example 3: CEILING() VS CEIL() VS FLOOR() VS ROUND() VS TRUNC()**

In the following example, we will utilize the CEILING(), CEIL(), FLOOR(), ROUND(), and TRUNC() functions side by side:
    
    
    SELECT CEILING(272.77),
    CEIL(272.77),
    FLOOR(272.77),
    ROUND(272.77),
    TRUNC(272.77);

Here in the above snippet:

\- The CEILING() and CEIL() functions are used to round up the given numeric value to the nearest integer.  
\- The FLOOR() function is utilized to round down the input numeric value to the closest integer.  
\- The ROUND() function will round the given numeric value upward or downward based on the specified fractional part.  
\- The TRUNC() function will trim the fractional points and retrieve the integer value.

The output demonstrates the difference between the CEILING(), CEIL(), FLOOR(), ROUND(), and TRUNC() functions.

 **Example 4: Using CEILING() Function on Table’s Data**

In this example, we will utilize the “product_details” table that we have already created in our database:
    
    
    SELECT * FROM product_details;

Let’s utilize the CEILING() function to round the “pro_price” column up to the nearest integer:
    
    
    SELECT pro_name, pro_price, CEILING(pro_price)
    FROM product_details;

The output shows that the CEILING() function successfully rounded the given values up to the nearest integers.

 **Conclusion**

In Postgres, CEILING() is a built-in math function that accepts a numeric or double precision value and converts it into the nearest integer toward the positive infinity. It is equally effective for rounding negative numbers. It is the equivalent of the CEIL() function, as both these functions round up the given to the nearest integer. This post explained how the CEILING() function works in Postgres using appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/how-does-the-ceiling-function-work-in-postgresql/)

---

# How to Install PostgreSQL on CentOS?

> To install PostgreSQL on CentOS, execute the “sudo yum install postgresql-server postgresql-contrib” script.

CentOS is a famous distribution of the Linux operating system for its stability and long-term support. By installing PostgreSQL on CentOS, users can have access to a powerful database management system that provides advanced features. It includes storing, managing, and retrieving large amounts of data, performing complex data analytics, and building web applications, among other things.

This post will teach the step-by-step procedure to install PostgreSQL on CentOS.

\- How to Install PostgreSQL on CentOS?  
\- Update System  
\- Install PostgreSQL  
\- Initialize PostgreSQL  
\- Start PostgreSQL Service  
\- Set PostgreSQL to Start at Boot Time  
\- Configure PostgreSQL

 **How to Install PostgreSQL on CentOS?**

Here are the steps to install PostgreSQL on CentOS:

 **Step 1: Update the System**

Before installing any new package, it is important to update your system to the latest available version. Users can do this by running the following command in the terminal:
    
    
    $ sudo yum update

The output shows that the system repository has been updated.

 **Step 2: Install PostgreSQL**

To install PostgreSQL on CentOS, execute the “yum” command by specifying the required packages:
    
    
    $ sudo yum install postgresql-server postgresql-contrib

This command installs both the PostgreSQL server and additional contributed modules.

 **Step 3: Initialize PostgreSQL**

After installing the PostgreSQL server, users need to initialize it. For this, execute the following command:
    
    
    $ sudo postgresql-setup initdb

This command creates the initial database cluster.

 **Step 4: Start PostgreSQL Service**

Now start the PostgreSQL service by running the “systemctl” command with the “start” utility:
    
    
    $ sudo systemctl start postgresql

In this way, the services of PostgreSQL have been started.

 **Step 5: Set PostgreSQL to Start at Boot Time**

To ensure that the PostgreSQL service starts automatically at system boot, run the following command:
    
    
    $ sudo systemctl enable postgresql

It ensures that PostgreSQL has been set to start at boot time.

 **Step 6: Configure PostgreSQL**

By default, PostgreSQL listens on the localhost. If users want to allow remote connections, modify the configuration file. For this, open the file “/ **var/lib/pgsql/data/pg_hba.conf** ” in a text editor, and add the following line at the end of the file:
    
    
    $ host all all 0.0.0.0/0 md5

It gives permission to make connections to any IP address. Users can restrict this by replacing 0.0.0.0/0 with a specific IP address or subnet.

 **Step 7: Restart PostgreSQL**

After modifying the configuration file, restart the PostgreSQL service by running the following command:
    
    
    $ sudo systemctl restart postgresql

It restarts the PostgreSQL service in the CentOS.

 **Conclusion**

To install PostgreSQL on CentOS, execute the “sudo yum install postgresql-server postgresql-contrib” script. After the installation, users can configure the PostgreSQL by modifying the “/ **var/lib/pgsql/data/pg_hba.conf** ” configuration file. This article has explained the step-by-step guide to installing PostgreSQL on CentOS.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-postgresql-on-centos/)

---

# How to Use CARDINALITY() Function in PostgreSQL?

> In PostgreSQL, CARDINALITY() is an array function that counts the total number of array elements. The return type of the stated function is INT.

In PostgreSQL, a variety of array functions are available that assist us in working with the array data productively. Some frequently used array functions include the ARRAY_APPEND(), ARRAY_REMOVE(), ARRAY_REPLACE(), etc. In Postgres, **CARDINALITY()** is also a notable array function that counts the total number of array elements.

This article will demonstrate different use cases of the CARDINALITY() function using appropriate examples.

 **How to Use CARDINALITY() Function in PostgreSQL?**

The CARDINALITY() function accepts a single or multi-dimensional array and retrieves the total number of elements present in that array. Here is the syntax for the CARDINALITY() function:
    
    
    CARDINALITY(arr);

It retrieves an integer that represents the number of the array elements.

Let’s learn it practically.

 **Example 1: CARDINALITY() Function With 1-D Array**

In the following example, a single dimensional array is passed to the “CARDINALITY()” function:
    
    
    SELECT CARDINALITY(ARRAY['Joe', 'John', 'Mike', 'Seth']);

The output demonstrates that the input array has four elements.

 **Example 2: CARDINALITY() Function With Multi-Dimensional Array**

Let’s learn how to find the array elements of the multi-dimensional array using the CARDINALITY() function:
    
    
    SELECT CARDINALITY('[2:4][2:3]={{10,20},{70,90},{100,120}}'::INTEGER[]);

The output shows that the given multi-dimensional array has six elements.

 **Example 3: CARDINALITY() Function on Table’s Data**

In this example, we will use an already created table named “std_info”:
    
    
    SELECT * FROM std_info;

Let’s utilize the CARDINALITY() function on the “std_num” column of the “std_info” table:
    
    
    SELECT std_name, std_num, CARDINALITY(std_num) 
    FROM std_info;

The CARDINALITY() function retrieves the total elements of the std_num array.

That’s all from this Postgres guide.

 **Conclusion**

In PostgreSQL, **CARDINALITY()** is an array function that counts the total number of array elements. It accepts a single or multi-dimensional array and retrieves the total number of elements present in that array. The return type of the stated function is INT. This post explained a complete guide on how to use the CARDINALITY() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-cardinality-function-in-postgresql/)

---

# How to Restart PostgreSQL Server on Windows

> In PostgreSQL, the “pg_ctl” command and “services manager” can be used to restart the Postgres server on the Windows operating system.

PostgreSQL is one of the most used RDBMS that is compatible with all the major operating systems, like Windows, Linux, and MacOS. Installing PostgreSQL on Windows allows us to store, manipulate, and retrieve enormous data efficiently. While working with Postgres, you may come across a situation where you need to restart the Postgres server. The possible reasons might be an inactive/dead server, system crashes, lags, etc. In such situations restarting the Postgres server can be proved very fortunate.

This post will present a step-by-step guide on restarting the PostgreSQL server on the Windows operating system.

 **How to Restart PostgreSQL Server on Windows**

There are various methods to restart a Postgres Server on Windows. In this write-up, the following methods will be discussed to restart the Postgres server:

\- Method 1: Using GUI (Services Manager).  
\- Method 2: Using CLI (Command Prompt).

 **Method 1: Restart Postgres Server Using GUI**

Press the “Win + S” button to open the windows search bar, type “services”, and hit the “Open” button to launch the services Window:

Once the “Services Manager” is opened, discover the “Postgresql-x64-15”, select the stated service, and press the “restart” button to restart the Postgres server:

Once you click on the “Restart” button the Postgres Server will be re-initiated.

 **Method 2: Restart Postgres Server Using CMD**

Type “CMD” in the windows search bar, and click on the “Open” button to launch the Windows command prompt:

Once the CMD is opened, type the following “pg_ctl” command to re-initiate the Postgres Server:
    
    
    pg_ctl -D "C:\Program Files\PostgreSQL\15\data" restart

The output snippet clearly states that the server has been restarted successfully.

 **Conclusion**

In PostgreSQL, the “pg_ctl” command and “services manager” can be used to restart the Postgres server on the Windows operating system. The Postgres users may come across a situation where they need to restart the Postgres server, such as having an inactive/dead server, system crashes, lags, etc. In such situations restarting the Postgres server can be proved very fortunate. This article has presented a step-by-step guide on how to restart the Postgres server on the Windows operating system.

---
[View this page online](https://www.commandprompt.com/education/how-to-restart-postgresql-server-on-windows/)

---

# How to Lock or Unlock a PostgreSQL User

> To lock a Postgres user, the “ALTER USER” statement can be used with the “NOLOGIN” clause. While a user can be unlocked by using the “ALTER USER” command with …

While working with PostgreSQL, sometimes the database administrators or superusers need to lock a user for a specific time period. For this purpose, the Postgres “ **ALTER USER** ” statement can be used with the “ **NOLOGIN** ” clause. Locking the users allows us to prevent the databases without removing the roles or databases. However, a user can be unlocked when needed by executing the “ **ALTER USER** ” command with the “ **LOGIN** ” attribute.

This post will present a stepwise guide on how to lock or unlock the PostgreSQL user.

 **How to Lock or Unlock a PostgreSQL User?**

This post will let you understand how to:

\- Create a New User.  
\- Lock a Particular User.  
\- Confirm the User Attributes.  
\- Unlock a Particular User.

 **Step 1: Create a New User**

Type the CREATE ROLE or USER command to define a new user:
    
    
    CREATE USER Joseph LOGIN PASSWORD 'xyz';

A new user named “joseph” has been created successfully.

 **Step 2:** **Lock the User**

Type the following ALTER command to lock the user:
    
    
    ALTER USER joseph NOLOGIN;

The specified role has been locked. Use the following “psql” command to confirm the user attributes:
    
    
    \du;

The above snippet shows that the user named “joseph” can’t log in.

 **Step 3: Login With the Locked User**

Let’s re-launch the terminal and try to log in as the locked user, i.e., “Joseph”:

The above snippet shows that we can not log in as a user “joseph”.

 **Step 4:** **Unlock the User**

Now, type the following ALTER command to unlock the selected user:
    
    
    ALTER USER joseph LOGIN;

The output snippet proves that the “ALTER USER” command was executed successfully. For confirmation, type the following command:
    
    
    \du;

The output shows that the “Can’t log in” attribute of the user “joseph” has been removed.

 **Step 5: Login With the Unlocked User**

Now re-open the terminal window, and logged in as the user “joseph”:

The above snippet proves that we have successfully logged in as the user “joseph”.

That was all regarding the locking or unlocking the Postgres users.

 **Conclusion**

In PostgreSQL, the database administrators or superusers can lock or unlock a user for a specific time period. To lock a Postgres user, the “ **ALTER USER** ” statement can be used with the “ **NOLOGIN** ” clause. While a user can be unlocked when needed by executing the “ **ALTER USER** ” command with the “ **LOGIN** ” attribute. This article has presented a practical guide on how to lock or unlock a user in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-lock-or-unlock-a-postgresql-user/)

---

# How to Check if a User is Connected to the PostgreSQL Server or Not

> In Postgres, to check the active users via the “pg_stat_activity”, use the “SELECT usename, datname, state FROM pg_stat_activity WHERE usename=&#x27;user_name&#x27;;” co…

Roles or users play a very crucial part in databases as they help us manage the database objects. In PostgreSQL, the concept of roles or users is used to manage the database access privileges. While working with Postgres, checking the connected users is a routine task for the database administrators. To do this, a system view named “ **pg_stat_activity** ” is used in PostgreSQL.

This article explains how to check if a particular user is connected with the Postgres server or not using practical demonstration.

 **How to Check if a User is Connected to the Postgres Server or Not?**

In Postgres, the “pg_stat_activity” is a system view that helps us determine the active queries. To check the active users via the “pg_stat_activity”, use the following syntax:
    
    
    SELECT usename, datname, state
    FROM pg_stat_activity 
    WHERE usename='user_name';

Specify the user name of your choice in place of the 'user_name' option. If the stated query retrieves any result, this means the specified user is connected to the server.

 **Example: Checking User Status**

This example will utilize the “pg_stat_activity” view to check if the “postgres” user is connected to the PostgreSQL server or not:
    
    
    SELECT usename, datname, state
    FROM pg_stat_activity 
    WHERE usename='postgres';

The output shows that the “postgres” user is connected and currently in an active state. Let’s execute the same query one more time for the “sample_user”:
    
    
    SELECT usename, datname, state
    FROM pg_stat_activity 
    WHERE usename='sample_user';

The output didn’t retrieve anything, which means the “sample_user” is not connected to the Postgres server.

That was all about checking if the user is connected with the Postgres server or not.

 **Conclusion**

In Postgres, the “pg_stat_activity” is a system view that helps us determine the active queries. To check the active users via the “pg_stat_activity”, use the “SELECT usename, datname, state FROM pg_stat_activity WHERE usename='user_name';” command. If the stated query retrieves any result, this means the specified user is connected to the server. However, if it didn’t retrieve anything, this means the selected user is not connected to the Postgres server. This article has presented a comprehensive guide on how to check if a user is connected to the Postgres server or not.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-if-a-user-is-connected-to-the-postgresql-server-or-not/)

---

# How to Grant Permissions on all Tables to a PostgreSQL User

> In PostgreSQL, the GRANT statement is utilized along with the “ON ALL TABLES” clause to assign permissions on all tables to single or multiple users.

In PostgreSQL, access privileges for database objects are managed by users or roles. Managing the privileges means granting or revoking the permissions. When it comes to allocating/granting privileges, the GRANT statement can be used. Using the GRANT statement, specific, multiple, or all permissions can be granted to a Postgres User.

This article will explain how to grant access to all tables to a specific Postgres user using the GRANT keyword.

 **How to Grant Permissions on all Tables to a Postgres User?**

Using the GRANT statement, access to all tables can be allotted to a certain Postgres user. Here is the basic syntax that is to fulfill this task:
    
    
    GRANT permissions_list
    ON ALL TABLES IN SCHEMA public 
    TO user;

\- Replace the “permissions_list” with the permissions to be granted, such as INSERT, SELECT, etc.  
\- The GRANT statement is utilized along with the “ON ALL TABLES” clause to assign permissions on all tables to a user.  
\- Specify the name of the selected user in place of “user”.

 **Example: Granting DML Permissions on All Tables to a Postgres User?**

Let’s consider the following steps to grant the permissions of CRUD operations on all tables to a particular user.

 **Step 1: Review Available Users**

Type the “\du” command to see the available users:
    
    
    \du;

 **Step 2: Assign Permissions on All Tables/Relations to a Specific User**

Suppose we want to grant “INSERT”, “UPDATE”, “DELETE”, and “SELECT” privileges on all tables to a user named “joseph”. For this, type the following command:
    
    
    GRANT INSERT, UPDATE, SELECT, DELETE
    ON ALL TABLES IN SCHEMA public 
    TO joseph;

The output proves that the stated permissions on all the tables have been granted to the “joseph”.

 **Step 3: Grant Permissions on All Tables to Multiple Users**

Specify the multiple users’ names using the comma-separated syntax to grant all table privileges to multiple users:
    
    
    GRANT INSERT, UPDATE, SELECT, DELETE
    ON ALL TABLES IN SCHEMA public 
    TO sample_user, example_user;

The specified permissions on all tables have been successfully granted to multiple users.

 **Conclusion**

In PostgreSQL, the GRANT statement is utilized along with the “ON ALL TABLES” clause to assign permissions on all tables to single or multiple users. Specify the multiple users’ names using the comma-separated syntax to grant all table privileges to multiple users. Using the GRANT statement, only specific, multiple, or all permissions can be granted to a Postgres User. This article has explained a practical guide on granting permission on all tables to single or multiple users.

---
[View this page online](https://www.commandprompt.com/education/how-to-grant-permissions-on-all-tables-to-a-postgresql-user/)

---

# How to Change the Table Owner in PostgreSQL

> To change or modify the table’s owner in PostgreSQL, use the “ALTER TABLE tab_name OWNER TO new_owner_name;” command.

Tables are the most frequently used database objects in any database, including PostgreSQL. Every table must have an **owner**. In Postgres, a user who creates a database object like tables, views, etc. is referred to as the owner of that particular object. However, the owner of any particular object can be changed when needed. For this purpose, the “ **ALTER TABLE** ” must be executed with the “ **OWNER TO** ” clause.

This article will present a step-by-step guide on how to change the owner of a specific Postgres table using the ALTER TABLE command.

 **How to Change or ALTER the Table Owner in Postgres?**

To change or modify the table’s owner, use the “ **ALTER TABLE** ” command followed by the selected “table’s name”. After that, use the “ **OWNER TO** ” clause followed by the new owner’s name. The following syntax will help you clarify this concern:
    
    
    ALTER TABLE tab_name
    OWNER TO new_owner_name;

The table’s owner, a superuser, or a user with the “ALTER TABLE” permissions can change the owner of a specific table.

The below-listed steps will help you alter the table’s owner efficiently:

 **Step 1: Review the Table’s Existing Owner**

Type the “\dt” command to see the current/original owner of the “employee_information” table:
    
    
    \dt employee_information;

The output depicts that the “employee_information” table is owned by the “postgres” user.

 **Step 2: Review Available Users**

Type the “\du” command and hit the “ENTER” button to see the available users:
    
    
    \du;

The output shows the available users along with their attributes.

 **Step 3: Change the Table’s Owner**

Suppose we have to change the table’s owner from “postgres” to “sample_user”. For this, type the following “ALTER TABLE” command and press the “ENTER” button:
    
    
    ALTER TABLE employee_information
    OWNER TO sample_user;

The above snippet depicts that the “ALTER TABLE” command was executed successfully.

 **Step 4: Verify the Table’s New Owner**

Now type the “\dt” command followed by “employee_information” to see the owner of the table:
    
    
    \dt employee_information;

The output shows that the owner of the specified table has been changed to “sample_user”.

 **Conclusion**

To change or modify the table’s owner in PostgreSQL, use the “ **ALTER TABLE tab_name OWNER TO new_owner_name;** ” command. To alter the table’s owner, the user must be a superuser, or he must have the “ALTER TABLE” permissions. In PostgreSQL, the “\dt” command can be used to verify the owner of a particular table. This article has presented a step-by-step guide on how to alter the table’s owner in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-change-the-table-owner-in-postgresql/)

---

# How to Grant All Privileges on Schema to User in PostgreSQL

> In PostgreSQL, the “GRANT ALL” statement is utilized along with the “ON ALL TABLES IN SCHEMA” clause to assign permissions on the schema to single or multiple …

In PostgreSQL, the database administrators or superusers are capable of assigning privileges for database objects to users or roles. For instance, the **GRANT** statement assists us in assigning/granting privileges to a particular user. Using the **GRANT ALL** statement, all permissions on a schema can be granted to a Postgres User.

This article will explain how to grant all privileges on the schema to a specific Postgres user.

 **How to Grant All Privileges on Schema to User in PostgreSQL?**

In PostgreSQL, the GRANT ALL statement is used to allocate all privileges on the schema to certain Postgres users. Here is the basic syntax:
    
    
    GRANT ALL ON tab_name TO user;

The above syntax is used to grant all privileges on a specific table to a certain user. However, if you want to grant all privileges on all tables of a schema, then the following syntax can be used:
    
    
    GRANT ALL ON ALL TABLES 
    IN SCHEMA schema TO user;

Specify the schema name and user name of your choice in place of the “schema” and “user” options.

 **Example: Granting All Privileges on Schema to User in Postgres**

Let’s consider the following steps to grant all permissions on the schema to a particular user.

 **Step 1: Review Available Users**

Type the “\du” command to see the available users:
    
    
    \du;

 **Step 2: Review Available Schemas**

Utilize the “\dn” command to see the available schemas:
    
    
    \dn;

 **Step 3: Granting All Permissions on Schema to a Single User**

Suppose we want to grant all privileges on the “public” schema to a user named “joseph”. For this, we will use the following command:
    
    
    GRANT ALL 
    ON ALL TABLES 
    IN SCHEMA public TO joseph;

The output proves that all permissions on all the tables of the “public” schema have been granted to the user “joseph”.

 **Step 4: Granting All Permissions on Schema to Multiple Users**

Specify the multiple users’ names using the comma-separated syntax to grant all privileges on the schema to multiple users:
    
    
    GRANT ALL
    ON ALL TABLES 
    IN SCHEMA public 
    TO sample_user, example_user;

All permissions on the “public” schema have been successfully granted to multiple users.

 **Conclusion**

In PostgreSQL, the “GRANT ALL” statement is utilized along with the “ON ALL TABLES IN SCHEMA” clause to assign permissions on the schema to single or multiple users. Specify the multiple users’ names using the comma-separated syntax to grant all schema privileges to multiple users. This article has explained a practical guide on granting permission on the schema to single or multiple users.

---
[View this page online](https://www.commandprompt.com/education/how-to-grant-all-privileges-on-schema-to-user-in-postgresql/)

---

# How to Get the List of Privileges Assigned to a Table in PostgreSQL

> In PostgreSQL, the “\z” command and “information_schema” can be used to check the list of assigned privileges to a certain Postgres table.

In PostgreSQL, privileges decide what operations a database object can perform. The privileges can be granted or revoked to a database object using the **GRANT** or **REVOKE** commands. To perform a specific database operation, Postgres users may need to check the privileges assigned to a specific database object. To do that, different commands or meta-commands can be used in Postgres.

This article will explain how to get the list of assigned privileges to a specific Postgres table.

 **How to Get/Check the List of Privileges Granted to a Postgres Table?**

In PostgreSQL, the “\z” command and “information_schema” can be used to check the list of assigned privileges to a certain Postgres table.

 **Example 1: Check Table Privileges Using “\z” Command**

Type the “\z” command followed by the table’s name to check the privileges assigned to a particular table:
    
    
    \z emp_info;

Here “emp_info” represents the table name:

The above snippet shows that the “postgres”, “sample_user”, and “example_user” users have access to the “emp_info” table. The stated users are granted various privileges, such as append, read, write, delete, truncate, REFERENCES, and TRIGGER.

 **Note:** in the above snippet, the “arwdDxt” is the abbreviation for different privileges that are explained in the [official Postgres documentation](<https://www.postgresql.org/docs/current/ddl-priv.html#PRIVILEGE-ABBREVS-TABLE>).

 **Example 2: Check Table Privileges Using “information_schema”**

In PostgreSQL, the “information_schema.role_table_grants” is used to get the list of all privileges assigned to a particular table. Here is the example code that demonstrates the working of the information schema and the “role_table_grants” view:
    
    
    SELECT grantee, privilege_type 
    FROM information_schema.role_table_grants 
    WHERE table_name='emp_bio';

In the above code:

\- The “grantee” and “privilege_type” are the columns to be fetched.  
\- The “information schema” is used to get all the information regarding the database objects, in our case, the object represents a table.  
\- The “role_table_grants” view is used to determine the assigned privileges on the selected tables or views.

The output snippet shows that the stated command retrieves detailed information regarding the privileges assigned to the “emp_info” table.

That’s it! All the necessary aspects of getting the list of assigned privileges to a Postgres table have been explained.

 **Conclusion**

In PostgreSQL, the “\z” command and “information_schema” can be used to check the list of assigned privileges to a certain Postgres table. Users can utilize the “\z” command followed by the table’s name to check the privileges assigned to a particular table. Alternatively, the “information_schema” can be executed along with the “role_table_grants” view to determine the assigned privileges on the selected tables or views. This article has covered a couple of methods to fetch the list of privileges allocated to a Postgres table.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-list-of-privileges-assigned-to-a-table-in-postgresql/)

---

# How to Get or Check Table Structure in PostgreSQL

> In PostgreSQL, the “\d”, the “\d+”, “information_schema”, and the “SELECT *” statement with the “FALSE” option are used to check the table’s structure.

Tables are the most often used database objects that help us store data in a well-organized (i.e., rows and columns) manner. PostgreSQL allows us to perform various operations on the tables, such as insertion, deletion, updation, and searching. While performing any of these tasks the Postgres users must determine the table’s structure. The table structure provides detailed information regarding table columns, constraints(if any), column types, etc.

This article explained how to get/check the table structure in PostgreSQL.

 **How to Get/Check Table Structure in Postgres?**

In PostgreSQL, various methods are used to check the table’s structure. The following methods will be discussed to determine the table’s structure in Postgres:

\- Method 1: Using “\d” Command  
\- Method 2: Using “\d+” Command  
\- Method 3: Using “information_schema”  
\- Method 4: Using the “SELECT *” Command

 **Method 1: Using “\d” Command**

The “\d” is one of the most commonly used commands that retrieves the table’s structure:
    
    
    \d emp_bio;

Here, “emp_bio” represents the targeted table:

The output shows the complete table structure, including column name, type, constraints, default value, etc.

 **Method 2: Using “\d+” Command**

The “\d+” is an extended form of the “\d” command that retrieves some additional information:
    
    
    \d+ emp_bio;

The stated command retrieves some extra information like “storage”, “description”, “access method”, etc.

 **Method 3: Using “information_schema”**

Postgres supports another handy command that can be executed from any interface like psql or pgAdmin. Use the SELECT command with the “information_schema” to get the table’s structure:
    
    
    SELECT *
    FROM information_schema.columns
    WHERE table_schema = 'public'
    AND table_name = 'emp_bio';

In this example, the “public” illustrates the schema name while “emp_bio” represents the table name:

The output depicts that the information schema returns detailed information regarding the table’s structure, such as the “table_catalog”, “table_schema”, “data_type”, etc.

 **Method 4: Using the “SELECT *” Command**

Type the SELECT * command is used with the “FALSE” option to get the table’s structure:
    
    
    SELECT * FROM emp_bio
    WHERE FALSE;

The primary use case of the stated command is fetching the table’s data. However, specifying the “FALSE” option in the WHERE clause will retrieve the table’s structure:

The stated command shows the column names, data types, and constraints of the selected table.

 **Conclusion**

In PostgreSQL, the “ **\d** ” command, the “ **\d+** ” command, “ **information_schema** ”, and the “ **SELECT *** ” statements with the “ **FALSE** ” option are used to check the table’s structure. The “\d” and “\d+” are meta-commands and must be executed from the “SQL Shell” aka psql. While the “information_schema” and “SELECT *” commands can be executed from any Postgres tool, including psql and pgAdmin. This write-up has explained four different methods to get or check the table’s structure in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-or-check-table-structure-in-postgresql/)

---

# How to Use REVERSE() Function in PostgreSQL

> The REVERSE() function accepts exactly one argument and that must be a string. As a result, it retrieves the given string in reverse order.

A wide range of built-in string functions is available in PostgreSQL that allows us to manipulate the text data. The “ **REVERSE()** ” is one of the string functions that is used to reverse the sequence of the string characters. The REVERSE() function accepts one of the string data types like TEXT, VARCHAR, etc., and its return type is text. A common use case of the REVERSE() function is to check if a specific string is a palindrome or not.

This article presents a detailed guide on how to reverse a string in Postgres using the REVERSE() function.

 **How to Use the REVERSE() Function in Postgres?**

The REVERSE() function accepts exactly one argument and that must be a string. As a result, it retrieves the given string in reverse order. Here is the basic syntax:
    
    
    REVERSE(str);

The “str” can be of TEXT, CHAR, or VARCHAR data type.

 **Example 1: Reversing a String Using REVERSE() Function**

In the following example, a string is passed to the REVERSE() function:
    
    
    SELECT REVERSE('Hello Welcome to USA');

The given string has been reversed successfully.

 **Example 2: Using REVERSE() Function With Table’s Data**

We will use the “employee_information” table that has been already created in the database:
    
    
    SELECT * FROM employee_information;

Let’s utilize the REVERSE() function to reverse the data of “e_email” column:
    
    
    SELECT *,
    REVERSE(e_email) 
    FROM employee_information;

The result shows that the “REVERSE()” function successfully changes the order of the given string data.

 **Example 3: Using REVERSE() Function in PL/pgSQL**

The following example illustrates how to check if a string is a palindrome or not:
    
    
    DO $$ 
    DECLARE
    name TEXT := 'bob';
    reverse_name TEXT := REVERSE(name);
    BEGIN 
    IF name = reverse_name THEN
    RAISE NOTICE 'Palindrome';
    ELSE
    RAISE NOTICE 'Not Palindrome';
    END IF;
    END $$;

In the above example,

\- Two string variables are declared.  
\- The first variable is assigned a string value, while the second variable is initialized with the reverse of the first variable.  
\- The if-else statement is used to check if the given string is a palindrome or not.

The output shows that the given string is a palindrome.

 **Conclusion**

The “ **REVERSE()** ” is one of the string functions that is used to reverse the sequence of a string. The REVERSE() function accepts exactly one argument and that must be a string. As a result, it retrieves the given string in reverse order. The accepted argument can be of TEXT, CHAR, or VARCHAR data type. This post has explained various use cases of the Postgres REVERSE() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-reverse-function-in-postgresql/)

---

# PostgreSQL STRING_TO_TABLE() Function With Examples

> The STRING_TO_TABLE() function accepts a string and a delimiter as arguments and splits the given string based on the specified delimiter.

PostgreSQL provides a built-in string function named **STRING_TO_TABLE()** that is used to convert or split the given string into a set based on the specified delimiter/splitter. For instance, using the **STRING_TO_TABLE()** function, a sentence can be divided into words. It can be used as an alternative to the REGEXP_SPLIT_TO_TABLE().

This write-up explains how to use the **STRING_TO_TABLE()** function in PostgreSQL using practical examples.

 **How to Use the STRING_TO_TABLE() Function in Postgres?**

The STRING_TO_TABLE() function accepts a string and a delimiter as arguments and splits the given string based on the specified delimiter. Here is the syntax:
    
    
    STRING_TO_TABLE(str, delimiter);

The delimiter can be any character, a white space, a comma, etc.

 **Example 1: How Does the STRING_TO_TABLE() Function Work in Postgres?**

The example below accepts a string as an argument and splits it into substrings based on the specified delimiter:
    
    
    SELECT STRING_TO_TABLE('Hello Welcome to USA', ' ');

In the above query, white space is used as a delimiter:

The given string is divided into words using the space as a delimiter.

 **Example 2: How to Use the STRING_TO_TABLE() Function Using the Null?**

In the following example, NULL will be used as the delimiter, which will split the given string and specify each character on a new line:
    
    
    SELECT STRING_TO_TABLE('Hello Welcome to USA', NULL);

The output shows that the stated function accepts a string and retrieves the set of characters.

 **Example 3: How Does the STRING_TO_TABLE() Function Work on the Table’s Data?**

We will use the “employee_information” table that has already been created in the database:
    
    
    SELECT * FROM employee_information;

Let’s utilize the STRING_TO_TABLE() function to split the employees email ids from the “@” symbol:
    
    
    SELECT STRING_TO_TABLE(e_email, '@') 
    FROM employee_information;

The output shows that the employees’ emails have been divided based on the specified delimiter, i.e., “@”.

 **Conclusion**

The STRING_TO_TABLE() function accepts a string and a delimiter as arguments and splits the given string based on the specified delimiter. The delimiter can be any character, a white space, a comma, NULL, etc. The NULL value can be used as the delimiter to split the given string into individual characters. This write-up explained the usage of the STRING_TO_TABLE() function with suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-string_to_table-function-with-examples/)

---

# How to Order by Count in PostgreSQL?

> In PostgreSQL, the ORDER BY clause is used along with the COUNT() function to retrieve the table’s records by count/quantity.

In database management systems, organizing the tables’ data is a crucial task. In databases like PostgreSQL, MySQL, ORACLE, etc., the ORDER BY clause is used to specify the table’s data in a particular order. In Postgres, the need of sorting the table’s data by count arises while working with the aggregated data. In such cases, the users must be aware of which column should be used when sorting the table's data.

This write-up will present a detailed guide on how to order the table’s data by count in Postgres.

 **How to Order Table’s Records by Count in PostgreSQL?**

In Postgres, the COUNT() function calculates the total number of records in a table while the ORDER BY clause sorts the data in a certain order. Utilizing the ORDER BY clause with the COUNT() function will retrieve the table’s records by count/quantity. Here is the simple yet very effective syntax:
    
    
    SELECT col_list, COUNT(col_name)
    FROM tab_name
    GROUP BY col_name
    ORDER BY COUNT(col_name) ASC | DESC;

\- The COUNT() is an aggregate function, so it must be utilized with the GROUP BY clause.  
\- The “ORDER BY COUNT()” will sort the table's data based on the count.

 **Example 1: How to Sort By Count in Postgres?**

In the following example code, we will utilize an already created sample table named “bike_info”:
    
    
    SELECT * FROM bikes_info;

Let’s execute the following statement to sort the table’s data by count:
    
    
    SELECT bike_price, COUNT(bike_model)
    FROM bikes_info
    GROUP BY bike_price
    ORDER BY COUNT(bike_model);

\- The above-stated command will group the bikes by their price.  
\- It will count the number of bikes for each price group.  
\- We didn’t specify the “ASCE” or “DSCE” option in the “ORDER BY COUNT()” command, so the result set will be sorted in ascending order, by default.  
\- Consequently, the bikes that have the least count will occur at the top.

The result set shows that the bikes’ data is sorted by count (in ascending order).

 **Example 2: Sort By Count in Descending Order**

Use the “DESC” option with the “ORDER BY COUNT()” to sort the table’s records in descending order:
    
    
    SELECT bike_price, COUNT(bike_model)
    FROM bikes_info
    GROUP BY bike_price
    ORDER BY COUNT(bike_model) DESC;

The result set shows that the bikes’ data is sorted by count (in descending order).

 **Conclusion**

In Postgres, the COUNT() function calculates the total number of records in a table while the ORDER BY clause sorts the data in a certain order. Utilizing the ORDER BY clause with the COUNT() function will retrieve the table’s records by count/quantity. The “ASCE” and “DSCE” options determine the sorting order of the result set. Omitting the “ASCE” or “DSCE” option will by default sort the table’s data in ascending order. This article has demonstrated a practical guide on how to order by count in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-order-by-count-in-postgresql/)

---

# How to Declare a Variable in PostgreSQL

> In Postgres, a variable is declared with a particular data type, such as INTEGER, TEXT, DATE, etc. To declare a variable, use the “DECLARE var_name data_type:=…

In PostgreSQL, a **variable** assigns a specific name to a memory location. Data can be temporarily stored in variables during code execution. In Postgres, variables need to be declared with a specific data type in the declaration block. Variables keep the mutable data that can be modified using a function or code block.

> Try the new PgManage (Open Source) and get rid of PgAdmin!

This write-up presents a practical guide on declaring the variables in Postgres.

 **How to Declare a Variable in Postgres?**

A variable in Postgres is always declared with a particular data type, such as INTEGER, TEXT, DATE, TIME, etc. Here is the syntax to declare a variable in Postgres:
    
    
    DECLARE var_name < CONSTANT > data_type < NOT NULL > < { DEFAULT | := } expression >;

In this syntax:

\- The “ **var_name** ” represents a meaningful name that will be assigned to a variable.  
\- “ **CONSTANT** ” is an optional parameter, used to assign a non-changeable value to the given variable.  
\- Replace the “ **data_type** ” with a valid data type, such as INT, DATE, TEXT, etc.  
\- The “ **NOT NULL** ” is an optional parameter that makes sure that the variable must contain a non-null value.  
\- The “ **DEFAULT** ” keyword initializes the given variable with a default or initial value.  
\- The “ **:=** ” or “ **=** ” operator is used to initialize a variable.

Let’s learn how to declare a variable in Postgres using the following examples.

 **Example 1: How to Declare and Initialize the Variables in Postgres?**

The below code explains how to declare and initialize different variables in Postgres:
    
    
    DO $$ 
    DECLARE 
    roll_number INT;
    std_name TEXT; 
    BEGIN
    roll_number := 5;
    std_name := 'Joseph';
    RAISE NOTICE 'Student Roll No: %, Student Name is %', 
    roll_number, 
    std_name;
    END $$;

In the above snippet:

\- Initially, the “ **DO** ” keyword is used to execute the code block.  
\- Two variables “roll_number” and “std_name” are declared within the “ **DECLARE** ” block.  
\- The “ **BEGIN** ” keyword starts the transaction block.  
\- The declared variables are initialized with some values in the “ **BEGIN** ” block.  
\- The “ **RAISE NOTICE** ” statement is used to print the variables.  
\- The variables to be printed are specified within the “ **RAISE NOTICE** ” and “ **END** ” statements.  
\- The “ **%** ” placeholders are used to print the values of the given variables.  
\- The “ **END** ” statement halts the transaction block.

The output demonstrates that the variables have been successfully declared, initialized, and printed.

 **Example 2: How to Declare the Variables With Default Values in Postgres?**

In the following coding example, various variables are declared and initialized with default string values:
    
    
    DO $$ 
    DECLARE 
    std_name TEXT := 'Alex';
    std_department VARCHAR(30) := 'Computer Science';
    BEGIN
    RAISE NOTICE '% is enrolled in % department', 
    std_name, 
    std_department;
    END $$;

In this example:

\- In the “ **DECLARE** ” block, two variables are declared and initialized with the default values.  
\- The “ **TEXT** ” and “ **VARCHAR** ” data types are used to declare two different variables.  
\- The “ **RAISE** ” command is used to display the errors or notices.

The output proves the variables’ declaration and initialization.

 **Example 3: How to Change the Variables Default Values in Postgres?**

In Postgres, the variables' default or initial values can be changed in the program at any time:
    
    
    DO $$ 
    DECLARE 
    std_name TEXT := 'Alex';
    std_department VARCHAR(30) := 'Computer Science';
    BEGIN
    std_name **=** 'John';
    RAISE NOTICE '% is enrolled in % department', 
    std_name, 
    std_department;
    END $$;

In the above code, the initial value of the “std_name” variable is re-initialized in the “BEGIN” block:

The output shows that the value of “std_name” has been successfully changed from “Alex” to “John”.

 **Example 4: How to Declare Constant Variables in Postgres?**

The following code snippet illustrates the usage of the CONSTANT keyword:
    
    
    DO $$ 
    DECLARE 
    std_name CONSTANT TEXT := 'Alex';
    std_department VARCHAR(30) := 'Computer Science';
    BEGIN
    std_name **=** 'John';
    RAISE NOTICE '% is enrolled in % department', 
    std_name, 
    std_department;
    END $$;

The CONSTANT is used to declare a non-changeable variable:

The output shows that an error occurs when we try to change the value of the constant variable.

 **Conclusion**

In PostgreSQL, a variable is always declared with a particular data type, such as INTEGER, TEXT, DATE, TIME, etc. To declare a variable, use the “DECLARE var_name data_type:= expression;” syntax. Variables keep the mutable data that can be modified using a function or block code. However, the constant variables can be declared using the CONSTANT keyword. This write-up illustrated a thorough guide on how to declare a variable in Postgres using appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-declare-a-variable-in-postgresql/)

---

# How to Get a Date Greater Than Today in PostgreSQL?

> In PostgreSQL, comparison operators like greater than “&gt;” and greater than or equal to “&gt;=” can be used with the “CURRENT_DATE” function to get a date greater …

PostgreSQL supports numerous built-in functions that assist us in manipulating the date and time values efficiently. In Postgres, the built-in functions like **NOW()** , **CURRENT_DATE** , **CURRENT_TIMESTAMP** , and **LOCALTIMESTAMP** are used with the **SELECT** statement to get today’s date. These functions can be used with comparison operators to filter the data based on today’s date.

This article explains how to get dates greater than today from a Postgres table.

 **How to Get a Date Greater Than Today in Postgre?**

The comparison operators like greater than “ **>** ” and greater than or equal to “ **> =**” can be used with the “ **CURRENT_DATE** ” function to get a date greater than today. Use the following syntax to get the table’s data greater than or equal to the current date (today):
    
    
    SELECT col_list
    FROM tab_name
    WHERE col_name > CURRENT_DATE;

In the above syntax:

\- The “SELECT” statement will retrieve the specified columns of the selected table.  
\- The tab_name is the name of the given table.  
\- The “WHERE” clause will filter the table’s record based on the current date.

All in all, the above query will return the records greater than today from the given table.

 **Sample Table**

A sample table named bikes_info has already been created in the database whose data is enlisted in the following snippet:
    
    
    SELECT * FROM bikes_info;

The result set demonstrates that the “ **launching_date** ” column contains some dates greater than today.

 **Example 1: Getting Dates Greater Than Today**

Suppose we want to get the data of all those bikes that are not launched yet. To fulfill this task, we will use the CURRENT_DATE function with the greater than operator, as follows:
    
    
    SELECT * 
    FROM bikes_info
    WHERE launching_date > CURRENT_DATE;

The above query will retrieve the details of only those bikes whose launching date is greater than today:

The bikes that have not yet been launched are displayed along with their model, price, and launch date.

 **Example 2: Getting Dates Greater Than or Equal to Today**

In the above example, replacing the ">" sign with ">=" retrieves the dates greater than or equal to today:
    
    
    SELECT * 
    FROM bikes_info
    WHERE launching_date >= CURRENT_DATE;

This time the result set displays the bikes whose launch date is today or greater than today.

 **Example 3: Getting Dates Greater Than Today Using NOW() Function**

In Postgres, built-in functions like **NOW()** , **CURRENT_TIMESTAMP** , and **LOCALTIMESTAMP** can also be used with the “>” or “>=” operator to get a date greater than today:
    
    
    SELECT * 
    FROM bikes_info
    WHERE launching_date >= NOW();

The output shows the launching dates greater than or equal to today in PostgreSQL.

 **Note:** The comparison operators like “ **<** ”, and “ **< =**” can be used with the CURRENT_TIMESTAMP, NOW(), CURRENT_DATE, and LOCALTIMESTAMP, functions to get the date less than or equal to today.

 **Conclusion**

In PostgreSQL, comparison operators like greater than “ **>** ” and greater than or equal to “ **> =**” can be used with the “ **CURRENT_DATE** ” function to get a date greater than or equal to today. Some other built-in date functions like **NOW()** , **CURRENT_TIMESTAMP** , and **LOCALTIMESTAMP** can also be used with the “>” or “>=” operator to get a date greater than today. This write-up presented a detailed guide on how to get a date greater than or equal to today in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-a-date-greater-than-today-in-postgresql/)

---

# Postgres Conference, PostgresConf and PgConf

> In the past Postgres Conference has gone by many names including, Postgres Conference, PostgresConf, PgConf.US and PgConf.Org. These are all the same organizat…

## Postgres Conference, PostgresConf and PgConf

  
When you are looking for a positive and productive experience to develop your professional skills and networking around Postgres, the place to be is the [Postgres Conference](<https://postgresconf.org/>)Ⓡ. Postgres Conference is organized by a passionate, professional and knowledgeable staff of volunteers. The conference is operated by the 501c3, PgCentral, Inc.. The 501c3 also organizes the [PostgresWorld](<https://www.meetup.com/pro/postgresworld/>) series of meetups for the professional Postgres community.  
  


In the past Postgres Conference has been known by many names including, Postgres Conference, PostgresConf, PgConf.US and PgConf.Org. These are all the same organization and community. They now, all refer back to [https://postgresconf.org](<https://postgresconf.org/>). Postgres Conference: The canonical and best source for growing your Postgres expertise and professional network.  


We invite everyone who wishes to enjoy a truly positive and inclusive experience around Postgres to join us at a [Postgres Conference](<https://postgresconf.org/>) event. If you wish to reach the organizers of PostgresConf, please email organizers@postgresconf.org.

  
If an event with local community is more your style, we invite your to participate with [PostgresWorld](<https://www.meetup.com/pro/postgresworld/>), the largest network of professional Postgres related meetups in North America.

---
[View this page online](https://www.commandprompt.com/education/postgres-conference-postgresconf-and-pgconf/)

---

# How to Copy a Table From One Database to Another in PostgreSQL

> To copy a table from one database to another, open CMD as an administrator, and run the &quot;pg_dump -U user –t table source_db | psql -U user target_db&quot; command.

In database management systems, copying a table provides numerous features, such as time-saving, error-free data manipulation, etc. Postgres lets us copy/duplicate a table [within the same](<https://www.commandprompt.com/education/different-methods-to-copy-or-clone-a-table-in-postgresql/>) or different database. To copy a table within the same database, various commands are used, such as the “CREATE TABLE AS”, “CREATE TABLE LIKE”, etc. However, to copy a table to a different database the “pg_dump” utility is used in Postgres.

This write-up explains how to copy a Postgres table from one database to another using practical examples.

 **How to Copy/Duplicate a Postgres Table From One Database to Another?**

Use the following “pg_dump” command to duplicate a table from one database to another:
    
    
    pg_dump –U user_name –t table_name source_db | psql –U user_name targeted_db

Here in the above snippet:

\- “pg_dump” is a utility that is used to back up a database.  
\- “-U” is a parameter specifying the user name.  
\- “table_name” represents a table to be duplicated.  
\- “source_db” represents the source database(where the selected table is placed).  
\- “targeted_ db” represents the targeted database(where the selected table will be copied).

To learn how to copy a table from one database to another, follow the steps below:

 **Step 1: Populating the Sample Databases**

Let’s execute the “\l” command to see the available databases:
    
    
    \l

Use the “\dt” command to populate the tables available in “postgres” database:
    
    
    \dt

To see all the tables of the “example_db” database, first, we need to access that particular database. For this, execute the “\c” command along with the database name:
    
    
    \c example_db;

Once you are connected to the “example_db” database, then you can populate all of its tables using the “\dt” command:
    
    
    \dt

The output snippet shows that the “example_db” database didn’t have any table.

 **Step 2: Sample Table**

The “postgres” database has a table named “author_info”, whose content is displayed in the following snippet:
    
    
    SELECT * FROM author_info;

In the following step, we will copy the “author_info” table from the “postgres” database to the “example_db” database.

 **Step 3: Access the Postgres Bin Directory**

Type “CMD” in the Windows search bar, and open it as an administrator:

Once the “CMD” is opened, use the “cd” command to navigate to the Postgres’ bin directory:
    
    
    cd C:\program files\postgresql\15\bin

Replace "15" with the Postgres version installed on your system:

The output shows that the Postgres bin directory has been accessed successfully.

 **Step 4: Copying Table From One Database to Another**

Execute the following “pg_dump” command to copy the “author_info” table from “postgres” to “example_db”:
    
    
    pg_dump –U postgres –t author_info postgres | psql –U postgres example_db

The output shows that the selected table has been successfully copied to the “example_db”.

 **Step 5: Confirm the Table Duplication**

Now navigate back to the “example_db” and execute the following command to populate the copied table:
    
    
    \dt

The “author_info” table of the “postgres” database has been successfully duplicated to the “example_db” database. Utilize the below-provided query to fetch the content of copied table:
    
    
    SELECT * FROM author_info;

This is how a specific table can be copied from one database to another.

 **Conclusion**

To duplicate a table from one database to another, PostgreSQL uses the "pg_dump" command with the name of the targeted table, source database, and destination database. For more clarity, specify the user name in the “pg_dump” command using the -U parameter. This post presented a practical guide on how to copy a specific table from one(source) database to another(destination).

---
[View this page online](https://www.commandprompt.com/education/how-to-copy-a-table-from-one-database-to-another-in-postgresql/)

---

# How to Install pgAdmin on Ubuntu

> To install pgAdmin on Ubuntu, add the public key using Curl, add the pgAdmin repository using sudo, and execute the “sudo apt install pgAdmin4” command.

**pgAdmin** is a freely available administration and management tool for the Postgres Database. It provides numerous features, such as a user-friendly graphical interface, local and remote session management, compatibility with all Postgres versions, etc.

When you install Postgres on the Windows operating system, " **pgAdmin** " is installed by default. However, in Ubuntu, you have to install it manually.

This post presents a practical demonstration of how to install pgAdmin on Ubuntu.

 **How to Install pgAdmin on Ubuntu?**

You must follow the below-given step-by-step instructions to install pgAdmin on the ubuntu operating system:

 **Prerequisite**

“curl” is a command line utility that helps us transfer data from one server to another. The “curl” utility must be pre-installed on Ubuntu in order to install pgAdmin. Execute the following command if curl isn't yet installed on your system:
    
    
    sudo apt install curl

Once the “curl” is successfully installed on your Ubuntu machine, you can install pgAdmin without any obstacles.

 **Step 1: Add Public Key Using Curl**

pgAdmin cannot be installed without the public key, because it isn't available/listed in the Ubuntu repositories. Therefore, first, we need to add the public key for the repository using the following command:
    
    
    sudo curl https://www.pgadmin.org/static/packages_pgadmin_org.pub | sudo apt-key add

 **Step 2: Add pgAdmin Repository and Update Server’s Packages**

Executing the below-provided command will add the pgAdmin repository and update the server’s packages:
    
    
    sudo sh -c 'echo "deb https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main" > /etc/apt/sources.list.d/pgadmin4.list && apt update'

 **Step 3: Install pgAdmin**

Now execute the following “sudo” command to install pgAdmin on your system:
    
    
    sudo apt install pgadmin4

Type “y” and press the “ENTER” button to proceed the further installation:

Finally, the pgAdmin4 has been successfully installed on Ubuntu 22.04.

 **Step 4: Launch pgAdmin**

Now click on the “Show Applications” button, type “pgAdmin” in the search bar, and left-click on the “pgAdmin4” application to launch it:

Clicking on the “pgAmin4” will lead you to the following window:

Specify the master password and hit the “OK” button.

 **Step 5: Add New Server**

To add a new server, you must click on the “Add New Server” button, as shown in the following snippet:

Specify the server’s name and navigate to the “Connection” tab:

Specify the details like hostname, password, etc. under the “Connection” tab and hit the “Save” button:

Clicking on the save button will show you the following window:

The above snippet depicts that the new server has been successfully added.

 **Step 6: Check Postgres Version**

Expand the “Databases” tab, select a database, right-click on it, and select the “Query Tool”:

Use the “VERSION()” function to check the currently installed Postgres version on Ubuntu:

The output shows that the “PostgreSQL 14.7” is running on our Ubuntu machine.

 **Conclusion**

To install pgAdmin on Ubuntu, add the public key using Curl, add the pgAdmin repository using sudo, and execute the “sudo apt install pgAdmin4” command. “curl” is a command line utility and it is a prerequisite for the pgAdmin installation. So, it must be pre-installed on Ubuntu in order to install pgAdmin. This write-up presented step-by-step instructions to install pgAdmin4 on Ubuntu.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-pgadmin-on-ubuntu/)

---

# How to Check PostgreSQL Service Status in Linux(Ubuntu)

> Execute the “sudo systemctl status postgresql” command to check the PostgreSQL service status on your Linux (Ubuntu) operating system.

PostgreSQL is one of the frequently used relational databases that assist us in storing data securely and efficiently. It offers numerous features, such as security, faster query execution, open-source development, etc. However, you need to install Postgres on your machine to earn these features. The Postgres Service status needs to be checked after installation in order to use the PostgreSQL database smoothly.

This write-up will explain how to check the status of the Postgres service using practical demonstration. The outcomes of this post are enlisted below:

\- How to Check if Postgres is Installed or Not?  
\- How to Check the Status of Postgres Service?  
\- How to Check if the Postgres Service is Active?  
\- How to Check if the Postgres Service is Enabled?  
\- How to Check if PostgreSQL is Ready to Accept/Recieve User Connections?

 **How to Check if Postgres is Installed or Not?**

Firstly, launch the terminal and connect to the “postgres” user via the below-given “sudo” command:
    
    
    sudo -i -u postgres

Now run the “psql” command from the terminal to access the “postgres”:
    
    
    psql

The output proves that the Postgres database is installed on your Ubuntu system. If Postgres is not installed on your system then first, you must [install](<https://www.commandprompt.com/education/how-to-install-postgresql-database-on-ubuntu/>) it on your system.

 **How to Check the Status of Postgres Service?**

Open the terminal and utilize the below-provided command to check the status of the Postgres service:
    
    
    sudo systemctl status postgresql

From the output snippet, you can observe that the “Postgres service” is currently enabled and active.

Alternatively, you can use the “systemctl” command with different options, like “is-active” or “is-enabled” to check the status of the Postgres service with respect to a specific parameter.

 **How to Check if the Postgres Service is Active?**

Use the “systemctl” command with the “is-active” option to check if Postgres is operating or not:
    
    
    sudo systemctl is-active postgresql

The output shows that “Postgres” is active.

 **How to Check if the Postgres Service is Enabled?**

Use the “sudo systmctl” command with the “is-enabled” option to check if the Postgres service is enabled or not:
    
    
    sudo systemctl is-enabled postgresql

The output proved that Postgres is currently enabled.

 **How to Check if PostgreSQL is Ready to Accept/Recieve User Connections?**

Use the "sudo pg_isready" command to check whether Postgres is ready for client connections or not:
    
    
    sudo pg_isready

The output clarifies that Postgres is accepting the users’ connections at the default port, i.e., 5432.

That’s all from this guide.

 **Conclusion**

Use the “sudo systemctl status postgresql” command to check the PostgreSQL service status in Linux. Users can also use the “sudo systemctl is-active postgresql” and “sudo systemctl is-enabled postgresql” commands to check if the Postgres service is active and enabled. Moreover, users can execute the "sudo pg_isready" command to check whether Postgres is ready for client connections or not.

This post presented a comprehensive guide on how to check the status of Postgres service on the Linux (Ubuntu) operating system.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-postgresql-service-status-in-linuxubuntu/)

---

# How to Check Query History in PostgreSQL?

> Run the “\s” command from psql to get query history. To check the query history using pgAdmin, open the “query tool” and navigate to the “Query History” tab.

In database management systems like Postgres, different commands and queries are used to perform various tasks. The data kept in the queries’ history is very beneficial for any database administrator. For instance, in different scenarios, there is a need to track back the Postgres server’s query history, such as while investigating a specific task, recovering a certain query if the server crashes, etc. In all these cases, query history serves as the user assistant.

This write-up demonstrates a practical guide on how to check the query history in PostgreSQL.

 **How to Check Query History in Postgres?**

The need for the query history arises when a server crashes, when a failure occurs, for routine task analysis, etc. Postgres allows us to check the backup history:

\- **Method 1:** Using SQL Shell  
\- **Method 2:** Using pgAdmin

 **Method 1: How to Check Query History in Postgres Using SQL Shell?**

In SQL Shell, the “\s” retrieves the command's history. The stated command can also be used to save the command's history to a specific file.

 **Example 1: Getting Query History Using “\s”**

Open the terminal, log into “psql”, and execute the following command to see the query history:
    
    
    \s

The output shows that the “\s” command successfully retrieves the query history.

 **Example 2: Getting the Last Executed Query**

If you want to check only the last executed command, then you must use the “pg_stat_activity” view. For this purpose, firstly, you need to get the “PID” for a specific session:
    
    
    SELECT pg_backend_pid();

Now use the “pg_stat_activity” view to get the last executed query:
    
    
    SELECT pid, query, backend_start
    FROM pg_stat_activity
    WHERE pid = '13999';

The output demonstrates that the “pg_stat_activity” view retrieves the last executed command along with the query’s start time.

 **Method 2: How to Check Query History in Postgres Using pgAdmin?**

Users can check the query history using pgAdmin. It shows the commands’ history with date and time.

 **Example: Check Query’s History Using pgAdmin**

Log into “pgAdmin”, and open the “Query tool”:

Clicking on the “Query Tool” will lead you to the following window:

Select the “Query History” tab to see the commands history:

The output depicts that the pgAmin’s “Query History” tab kept the query history with date and time.

That was all regarding the Postgres query history.

 **Conclusion**

In PostgreSQL, the query history can be checked using SQL Shell or pgAdmin. Execute the “ **\s** ” command from SQL Shell (psql) to get query history. To check the query history using pgAdmin, open the “query tool” and navigate to the “ **Query History** ” tab. Use the “ **pg_stat_activity** ” view to see only the last executed command. This post explained how to see the query history in PostgreSQL using the SQL Shell and pgAdmin.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-query-history-in-postgresql/)

---

# How to Modify an Array Using Built-in Functions in PostgreSQL

> Postgres offers different built-in array functions that are used with the UPDATE command to modify an array, such as ARRAY_PREPEND(), ARRAY_REMOVE(), ARRAY_CAT…

In PostgreSQL, the **UPDATE** statement is used to modify the whole array or only specific indexes of an array. However, Postgres provides numerous built-in functions that can be used with the UPDATE statement to modify the arrays more efficiently, such as **ARRAY_PREPEND()** , **ARRAY_REMOVE()** , **ARRAY_CAT()** , etc. Using these methods, users can add new elements to arrays, delete or replace unnecessary elements from arrays, concatenate multiple arrays, etc.

This post will discuss how to modify the Postgres arrays using various built-in array functions.

 **How to Update Arrays Using Built-in Array Functions in Postgres?**

In this section we will learn how to update an array using the following array functions:

\- ARRAY_PREPEND()  
\- ARRAY_APPEND()  
\- ARRAY_CAT()  
\- ARRAY_REMOVE()  
\- ARRAY_REPLACE()

 **Sample Table**

A sample table named “std_info” has already been created with the following records:
    
    
    SELECT * FROM std_info;

The above-provided array functions will be used in the following examples to update the “std_num” array.

 **Example 1: Updating an Array Using ARRAY_PREPEND() Function**

Use the ARRAY_PREPEND() function to add a new element at the start of a given array:
    
    
    UPDATE std_info
    SET std_num = ARRAY_PREPEND(50, std_num);

Execute the “SELECT *” command to validate the modified array:
    
    
    SELECT * FROM std_info;

The output clarifies that a new element has been successfully inserted at the start of the given array.

 **Example 2: Updating an Array Using ARRAY_APPEND() Function**

The ARRAY_APPEND() function allows us to add a new element at the end of the given array:
    
    
    UPDATE std_info
    SET std_num = ARRAY_APPEND(std_num, 55);

Let’s verify the updated array using the following command:
    
    
    SELECT * FROM std_info;

The output snippet validates that the selected array has been modified.

 **Example 3: Updating an Array Using ARRAY_CAT() Function**

Use the ARRAY_CAT() function to combine/concatenate an array with any other array:
    
    
    UPDATE std_info
    SET std_num = ARRAY_CAT(std_num, ARRAY[65, 40, 72]);

Run the SELECT query to check the modified array:
    
    
    SELECT * FROM std_info;

The output shows that a new array has been successfully concatenated with the “std_num” array.

 **Example 4: Updating an Array Using ARRAY_REMOVE() Function**

In Postgres, the ARRAY_REMOVE() function helps us remove the unnecessary array elements from a particular array:
    
    
    UPDATE std_info
    SET std_num = ARRAY_REMOVE(std_num, 72);

To validate the modified array, run the SELECT query as follows:
    
    
    SELECT * FROM std_info;

From the output snippet, you can observe that all the occurrences of “72” have been removed from the given array.

 **Example 5: Updating an Array Using ARRAY_REPLACE() Function**

Use the ARRAY_REPLACE() function to replace an array element with some particular value:
    
    
    UPDATE std_info
    SET std_num = ARRAY_REPLACE(std_num, 50, 61);

To demonstrate the modified array elements, use the SELECT query as follows:
    
    
    SELECT * FROM std_info;

The output depicts that all occurrences of “50” have been replaced with “61”.

 **Conclusion**

Postgres offers different built-in array functions that are used with the UPDATE command to modify an array. For instance, the **ARRAY_PREPEND()** function to insert an element at the start of an array, **ARRAY_REMOVE()** to remove any particular element from an array, **ARRAY_CAT()** to concatenate multiple arrays, etc. This Postgres guide provided numerous examples of how to modify an array using appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-modify-an-array-using-built-in-functions-in-postgresql/)

---

# PostgreSQL INNER JOIN Explained With Examples

> In PostgreSQL, the INNER JOIN is used to get the matching results from two or more tables based on a specific join condition.

PostgreSQL is a renowned freely available relational database. In relational databases, data is distributed into various tables. To get detailed information, you might need to combine/merge the data of various tables. For this purpose, the Joins are used in databases. PostgreSQL supports various types of JOINS, such as “ **INNER JOIN** ”, “ **OUTER JOIN** ”, “ **NATURAL JOIN** ”, “ **SELF JOIN** ”, etc.

This post will specifically discuss the usage of the Postgres **INNER JOIN** using suitable examples.

 **How to Use INNER JOIN in Postgres?**

In Postgres, the INNER JOIN is used to get the matching results from two or more tables based on a specific join condition.

Use the below syntax to combine multiple tables using “INNER JOIN”:
    
    
    SELECT <tab_1.col_names>, <tab_2.col_names>
    FROM <tab_1>
    INNER JOIN <tab_2>
    ON <table_1.col_name> = <tab_2.col_name>;

Here, in the above syntax:

\- “tab_1” and “tab_2” are the tables to be joined.  
\- The tables’ columns will be specified as “table_name.col_name”, i.e., “tab_1.col_name”, and “tab_2.col_name”.  
\- The “INNER JOIN” joins the given tables according to the specified JOIN condition.  
\- The “ON” clause defines the joining condition.

If the tables to be joined have the same column names, then the “USING” clause can be used instead of the “ON” clause to define a join condition:
    
    
    SELECT col_list
    FROM tab_1
    INNER JOIN tab_2
    USING (col_names);

Here, the “INNER JOIN” will join the selected tables based on the condition defined via the “USING” clause.

 **Example 1: INNER JOIN With ON Clause**

We have already created a couple of sample tables, whose details are depicted in the following snippets:
    
    
    SELECT * FROM employee_information;

Use the “SELECT *” command to get the detailed information regarding the “department_information” table:
    
    
    SELECT * FROM department_information;

The “e_id” is a primary key in the “employee_information” table and the foreign key in the “department_information” table.

Let’s use the INNER JOIN to join the “employee_information” and “department_information” tables based on the “e_id”:
    
    
    SELECT employee_information.e_id, 
    e_name, e_email, dpt_name, dpt_id
    FROM employee_information 
    INNER JOIN department_information
    ON employee_information.e_id = department_information.e_id;

The output snippet validates that the given tables have been successfully joined using the “INNER JOIN”.

 **Example 2: INNER JOIN With USING Clause**

The “USING” clause can also be used along with the “INNER JOIN” to join/combine multiple tables. However, in such a case the column names should be the same in both tables:
    
    
    SELECT employee_information.e_id, 
    e_name, e_email, dpt_name, dpt_id
    FROM employee_information 
    INNER JOIN department_information
    USING(e_id);

Here, the column name “e_id” is the same in both tables, so the given tables can be joined using the INNER JOIN and the USING clause:

The “employee_information” and “department_information” tables have been joined successfully using the “INNER JOIN”.

 **Example 3: Joining Three Tables Using the INNER JOIN**

Suppose we have three tables: “emp_bio”, “dpt_info”, and “emp_details''. All these tables are linked with each other via the foreign key constraint. Let’s utilize the SELECT query to fetch the details of each table:
    
    
    SELECT * FROM emp_bio;

In the “emp_bio” table, “e_id” is a primary key. Let’s execute the “SELECT” command one more time to fetch the results from the “dpt_info” table:
    
    
    SELECT * FROM dpt_info;

In the “dpt_info” table, “dpt_id” is a primary key. The third sample table is “emp_details”, whose details are enlisted in the following snippet:
    
    
    SELECT * FROM emp_details;

In the “emp_details” table, the “e_id” and “dpt_id” are foreign keys.

Let’s learn how to join three tables using the INNER JOIN:
    
    
    SELECT emp_bio.e_name, emp_bio.emp_name, 
    dpt_info.dpt_name, emp_salary
    FROM emp_bio
    INNER JOIN emp_details
    ON emp_bio.e_id = emp_details.e_id
    INNER JOIN dpt_info
    ON dpt_info.dpt_id = emp_details.dpt_id;

In the above code, the first INNER JOIN is used to join the “emp_bio” and “emp_details” tables on the basis of “e_id”. While the second INNER JOIN is used to join the emp_info table with the other two tables based on the “dpt_id”:

The output authenticates that the “emp_bio”, “dpt_info”, and “emp_details'' tables have been successfully joined.

 **Conclusion**

In PostgreSQL, the INNER JOIN is used to get the matching results from two or more tables based on a specific join condition. The “ON” clause is used with the INNER JOIN to define a joining condition. If the tables to be joined have the same column names, then the “USING” clause can be used instead of the “ON” clause to define a join condition. This post has explained the usage of the INNER JOIN in PostgreSQL using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-inner-join-explained-with-examples/)

---

# Check Database Size and Table Size in PostgreSQL Using pgAdmin

> In PostgreSQL, built-in functions like pg_relation_size(), pg_database_size(), pg_size_pretty(), etc. are used to get the size of the table or database.

PostgreSQL is a relational database management system that helps us store data for different web apps, mobile apps, etc. In Postgres, tables are the objects of a database that depict the data in the form of rows and columns. While working with databases, finding the sizes of the database objects can help us in storage management, memory optimization, resource management, etc.

This write-up will explain how to check the size of databases or tables in PostgreSQL using pgAdmin.

 **How to Check Database Size or Table Size in Postgres Using pgAdmin?**

In Postgres, different built-in functions are used to check the size of database objects, such as the **pg_relation_size()** , **pg_database_size()** , **pg_size_pretty()** , etc. However, pgAdmin helps us get the size of database objects with or without using these built-in functions.

 **Getting Database Size Using pgAdmin**

This section illustrates how to get the database size in pgAdmin:

\- Using pgAdmin’s Statistics  
\- Using pg_database_size() Function  
\- Using pg_size_pretty() Function

 **Example 1: Getting All Databases Size Using pgAdmin’s Statistics**

Open the pgAdmin, click on the “Databases” option under the “Servers” tree, and then select the pgAdmin’s statistics tab to get the size of all databases:

The databases’ sizes can be seen in the “Size” column.

 **Example 2: Getting the Size of a Specific Database Using pgAdmin’s Statistics**

The size of a specific database can be obtained by selecting that particular database and then clicking on the "Statistics" tab:

The above snippet shows the size of the “postgres” database.

 **Example 3: Getting the Size of a Specific Database Using pg_database_size() Function**

Alternatively, you can use the “pg_database_size()” function from the pgAdmin’s query tool to get the database size:
    
    
    SELECT pg_database_size('postgres');

The stated function retrieves the database size in bytes.

 **Example 4: Getting the Size of a Database Using pg_size_pretty() Function**

Bytes are difficult to comprehend if the databases contain enormous amounts of data. To get the data in an easily understandable format, wrap the “pg_database_size()” function within the “pg_size_pretty()” function, as follows:
    
    
    SELECT pg_size_pretty(pg_database_size('postgres'));

This time, the database size is retrieved in “KBs”.

 **Example 5: Getting the Size of All Databases Using pg_database_size() Function**

Use the pg_database_size() function with the “pg_database” catalog to get the size of all databases, including the standard system databases:
    
    
    SELECT pg_database.datname, 
    pg_database_size(pg_database.datname) AS all_databases_size 
    FROM pg_database;

\- Here, the “pg_database” is a system catalog that contains information regarding the databases.  
\- The “datname” is a column containing information regarding the database name.  
\- “pg_database_size()” is a built-in function that retrieves the database sizes.  
\- “AS” represents a column alias, used to assign a temporary name to the resultant column.

The output snippet retrieves the databases’ size in bytes.

 **Getting Tables Size Using pgAdmin**

This section demonstrates how to get tables size:

\- Using pgAdmin’s Statistics  
\- Using pg_relation_size() Function  
\- Using pg_size_pretty() Function

 **Example 1: Getting Size of All Tables Using pgAdmin’s Statistics**

Expand the “Schemas” option available under the "database” of your choice. Locate the “public” schema, select the “Tables” option, and click on the “statistics” tab to see the size of all tables:

The output shows the total size for each table available in the “postgres” database.

 **Example 2: Getting the Size of a Specific Table Using pgAdmin’s Statistics**

To get the size of only a particular table, all you need to do is select the table of your choice and click on the “statistics” tab:

The output shows that the total size of the “department_information” table is “8KB”.

 **Example 3: Getting Table Size Using pg_relation_size() Function**

Alternatively, you can specify the table name inside the “pg_relation_size()” function to get the size of the desired table:
    
    
    SELECT pg_relation_size('department_information') AS table_size;

The output shows the total number of bytes that the “department_information” table takes.

 **Example 4: Getting Table Size Using pg_size_pretty() Function**

Wrap the “pg_relation_size()” function within the “pg_size_pretty()” function to get the table’s size in human-understandable formats:
    
    
    SELECT pg_size_pretty(pg_relation_size('department_information'));

The output proves that the pg_size_pretty() function returns the table’s size in an easily understandable format.

 **Conclusion**

In PostgreSQL, built-in functions like **pg_relation_size()** , **pg_database_size()** , **pg_size_pretty()** , etc. are used to get the size of the table or database. The pgAdmin helps us get the size of database objects with or without using these built-in functions. To get the size of a database or table without using any function, you need to select the database or table of your choice and then click on pgAdmin’s statistics tab. This Postgres blog explained how to check the database size and table size using pgAdmin.

---
[View this page online](https://www.commandprompt.com/education/check-database-size-and-table-size-in-postgresql-using-pgadmin/)

---

# How to Check Current Version, Database, Schema, and User in PostgreSQL

> In Postgres, the VERSION(), CURRENT_DATABASE(), CURRENT_SCHEMA, and CURRENT_USER, functions are used to get the current version, database, schema, and user.

Postgres provides various built-in functions that are used to get the system and session information, such as VERSION(), CURRENT_DATABASE(), CURRENT_CATALOG, etc. In SQL, the CURRENT_SCHEMA, CURRENT_CATALOG, and USER functions are used without parenthesis “()”.

In Postgres, the “CURRENT_SCHEMA” function can be used with or without parenthesis while the CURRENT_CATALOG and USER functions will be used without parenthesis.

This write-up will present a detailed guide on how to get:

  * Currently Installed Postgres Version
  * Current Database or Catalog Name
  * Current Schema Name
  * Current User or Role
  * Server’s IP Address
  * Server’s Starting Time
  * Current Query



 **How to Get/Fetch the Postgres Version?**

In PostgreSQL, the “VERSION()” function is used to get the detailed information regarding the currently installed Postgres version on your system:
    
    
    SELECT VERSION();

The output snippet signifies that currently “PostgreSQL 15.1” is running on our system.

 **How to Get/Check Database Name in Postgres?**

In Postgres, the CURRENT_DATABASE() function retrieves the name of the current database:
    
    
    SELECT CURRENT_DATABASE();

The CURRENT_CATALOG function can also be used to get the current database name in Postgres:
    
    
    SELECT CURRENT_CATALOG;

The output snippet shows that both the “CURRENT_DATABASE” and “CURRENT_CATALOG” functions return the name of the current database.

 **How to Check Schema Name in Postgres?**

To get the name of the current schema, the CURRENT_SCHEMA function is used in Postgres:
    
    
    SELECT CURRENT_SCHEMA;

The output demonstrates that the name of the current schema is “public”.

 **How to Get/Check the Current User or Role in Postgres?**

In PostgreSQL, the CURRENT_ROLE, CURRENT_USER, or USER functions are used to get the current user or role:
    
    
    SELECT CURRENT_USER, CURRENT_ROLE, USER;

The output snippet validates that the stated functions return the name of the current user/role.

 **How to Find the IP Address of the Postgres Server?**

To get the server’s IP address, use the built-in INET_SERVER_ADDR() function:
    
    
    SELECT INET_SERVER_ADDR();

The output retrieves “::1”, which is nothing but an IPV6 address that represents the local machine.

 **How to Check the Server’s Starting Time in Postgres?**

Postgres provides a built-in PG_POSTMASTER_START_TIME() function to get the server’s starting time:
    
    
    SELECT PG_POSTMASTER_START_TIME();

The output shows that the stated function retrieves the DateTime at which the server was started, along with the time zone information.

 **How to Find the Current Query in Postgres?**

The CURRENT_QUERY() function in Postgres retrieves one or more queries that are currently executing:
    
    
    SELECT CURRENT_QUERY();

The output validates the working of the CURRENT_QUERY() function.

 **Conclusion**

PostgreSQL supports various in-built functions to get or fetch the system and session information. For instance, the VERSION(), CURRENT_DATABASE(), CURRENT_SCHEMA, CURRENT_USER, and CURRENT_QUERY() functions are used to get the current Postgres version, database, schema, user, and query.

To get the server’s IP address and the server’s starting time, use the INET_SERVER_ADDR() and PG_POSTMASTER_START_TIME() functions. This post explained numerous functions that are used to get the session or system information.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-current-version-database-schema-and-user-in-postgresql/)

---

# How to Reset Forgotten Password For postgres User

> To reset a forgotten password for a “postgres” user &gt; open the “pg_hba.config” file located at “C:\Program Files\PostgreSQL\15\data”, and replace the local con…

Passwords play a very crucial role in our lives. Passwords protect the data and prevent a database from unauthorized access. In database management systems, like PostgreSQL, passwords are considered the primary protection parameter against cybercrime.

> Try the new PgManage (Open Source) and get rid of PgAdmin!

While installing Postgres, users specify a superuser password that must be remembered for later use. The superuser password is required every time a user logs into the Postgres server. But what if a Postgres user forgets the password? How to reset the forgotten passwords in Postgres?

Well! Nothing to worry about! This post will present step-by-step instructions on how to reset the forgotten password for the “postgres” user.

 **How Do I Reset the Password for postgres User?**

Postgres utilizes a configuration file named “pg_hba.conf” to address the client authentication. Here, the term “hba” stands for “host-based authentication”. The stated file is placed in the data directory of Postgres, i.e., “C:\Program Files\PostgreSQL\15\data”. To reset a password, you must change the parameters in the “hba.config” file. Changing the configuration parameters will allow a user to log in without a password.

The below-provided steps will guide you on how to reset a password in Postgres.

 **Step 1: Locate the “pg_hba.config” File**

Open the “C” drive > Program Files > PostgreSQL > 15 > and finally the Data directory. In the Data director, scroll down to locate the pg_hba.config file:

 **Step 2: Open the “pg_hba.config” File**

Firstly, copy the stated file into some other location, or rename the file like “pg_hba.conf.bk” to keep the backup of the file. Next, double-click on the selected file to open it:

In the “pg_hba.config” file, replace the local connections with “trust”, as demonstrated in the following snippet:

Resetting the local connections to “trust” will allow you to log into Postgres without providing the superuser password.

 **Step 3: Restart Postgres**

Press “win + S” to open the Windows search bar, type “services”, and click on the “services” app to open it:

In the “Services” window, find the “Postgresql-x64-15”, select the service, and click on the “restart” button to restart a Postgres server:

 **Step 4: Open Postgres**

Now connect to Postgres using SQL Shell or pgAdmin:

The above snippet proves that we are successfully logged in as a “postgres” user.

 **Step 5: Reset the Password**

Now execute the “ALTER USER” or “ALTER ROLE” command with the “PASSWORD” attribute to reset the password for the “postgres” user:
    
    
    ALTER USER postgres WITH PASSWORD 'my_modified_password';

The output proves that the password for the “postgres” user has been reset successfully.

 **Conclusion**

To reset a forgotten password for a “postgres” user > open the “pg_hba.config” file located at “C:\Program Files\PostgreSQL\15\data”, and replace the local connections with “trust”. After that, open the Services manager, select the “Postgresql-x64-15” service, and click on the “restart” button to restart the Postgres server. Finally, connect to postgres, and execute the “ALTER USER” command with the “PASSWORD” attribute to reset the password for the “postgres” user. This post presented a detailed guide on resetting the forgotten password for a “postgres” user.

---
[View this page online](https://www.commandprompt.com/education/how-to-reset-forgotten-password-for-postgres-user/)

---

# How to Create User, Create Database, Grant Privileges in PostgreSQL

> Execute the “GRANT ALL PRIVILEGES” command to grant all the database privileges to the user, such as creating a database, dropping a database, etc.

In PostgreSQL, the CREATE USER statement with “PASSWORD” attributes creates a new user with login privileges. However, the newly created user can’t access or modify the database objects, such as tables, functions, views, etc. until-unless the user is granted privileges on the database objects.

To grant all the database privileges to the user/role the “GRANT ALL” statement is used in Postgres.

This write presents a step-wise guide on how to create a database, user, and grant privileges on the database to the user.

 **How to Create a User, Database, and Grant User Privileges to Database?**

Follow the below-provided steps to learn how to create a user and a database, and grant user privileges to the database:

 **Step 1: Creating a User**

Launch the SQL Shell, provide the login details, and execute the below-provided command to create a new user:
    
    
    CREATE USER example_user WITH PASSWORD 'user_12345';

You can verify the user creation by executing the “\du” command:
    
    
    \du;

The output signifies that a new user named “example_user” has been successfully created.

 **Step 2: Creating a Database**

Use the below-given command to create a new database named “example_db”:
    
    
    CREATE DATABASE example_db;

To verify the database creation, use the “\l” command:
    
    
    \l

The output snippet demonstrates that a new database named “example_db” has been successfully created.

 **Step 3: Grant All Privileges/Access to the User/Role**

Finally, execute the “GRANT ALL PRIVILEGES” command to grant all the database privileges to the user, such as creating a database, dropping a database, etc.
    
    
    GRANT ALL PRIVILEGES ON DATABASE "example_db" to example_user;

The output shows that the permissions have been successfully granted to the user.

That’s all from this post!

 **Conclusion**

In PostgreSQL, the CREATE USER statement with “PASSWORD” attributes creates a new user with login privileges. While the “CREATE DATABASE” command creates a new database. However, the newly created user can’t access or modify the database objects, such as tables, functions, views, etc. until the user is granted privileges on the database objects. To fulfill this purpose, the “GRANT ALL” statement is used in Postgres. This post presented a comprehensive guide on creating a new user, a database, and granting/assigning the database privileges to the newly created user.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-user-create-database-grant-privileges-in-postgresql/)

---

# How to Update an Array in PostgreSQL

> PostgreSQL allows us to update an already existing array using the “UPDATE SET” statement. Specify the array index with the array name to update only a specifi…

Arrays are one of the most significant data structures in programming paradigms that store the data in contiguous memory locations. In Postgres, the ARRAY data type is used to store the data of similar data types. Postgres allows us to update an already existing array using the UPDATE SET statement. In PostgreSQL, an entire array or only specific elements of an array can be updated using the UPDATE command.

This post presents a detailed guide on updating the array’s elements using the UPDATE query.

 **How to Update an Array in PostgreSQL?**

Use the UPDATE query to update a specific array element or an entire array in PostgreSQL:
    
    
    UPDATE tbl_name
    SET array_name = '{array_values}' 
    WHERE condition;

The above syntax is used to update/overwrite a whole array. Use the below-given syntax to update a specific element of an array:
    
    
    UPDATE tbl_name
    SET array_name[index] = '{array_value}' 
    WHERE condition;

Let’s learn these concepts practically!

 **Example 1: Updating an Entire Array**

A sample table named “std_info” has already been created with the following data:
    
    
    SELECT * FROM std_info;

Suppose we want to modify the “std_num” array for a student whose id is 3. To accomplish this task, the UPDATE statement will be executed as follows:
    
    
    UPDATE std_info
    SET std_num = '{52, 80, 60, 51, 60}' 
    WHERE std_id = 3;

Run the SELECT command to verify the updated array’s data:
    
    
    SELECT * FROM std_info;

The entire “std_num” array for id 3 has been updated successfully.

 **Example 2: Updating Specific Elements of an Array**

In this example, we will update some specific elements of the “std_num” array:
    
    
    UPDATE std_info
    SET std_num[2] = 68 
    WHERE std_id = 3;

The above statement will modify the second index of the “std_num” array for id 3:

Use the SELECT command to verify the updated array’s element:
    
    
    SELECT * FROM std_info;

The specified array element has been updated successfully.

 **Conclusion**

PostgreSQL allows us to update an already existing array using the “UPDATE SET” statement. In Postgres, an entire array or only specific elements of an array can be updated using the UPDATE command. Specify the array index with the array name to update only a specific element of an array. This Post has demonstrated a practical guide on how to update an array in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-update-an-array-in-postgresql/)

---

# How to Uninstall PostgreSQL From Windows

> To uninstall Postgres from windows, open control panel &gt; go to programs and features &gt; locate PostgreSQL &gt; Uninstall the PostgreSQL.

Postgres, or PostgreSQL, is an open-source object-relational database management system that is widely utilized for storing and managing data. Uninstalling Postgres from Windows means removing the Postgres software and all of its components from your computer. This can be necessary if Postgres is no longer needed on your system, or if you need to install a different version of Postgres.

This article will demonstrate a comprehensive guide on uninstalling Postgres from Windows.

 **What is the Purpose to Uninstall Postgres on Windows?**

Uninstalling Postgres ensures that all of its files, configurations, and services are removed from the computer, freeing up disk space and resources. Additionally, it is useful if users are experiencing issues with Postgres and need to perform a clean installation to troubleshoot the problem.

 **Method: Using Control Panel to Uninstall Postgres**

Uninstalling PostgreSQL on Windows can be done through the Control Panel or by using the PostgreSQL installer. Here are the steps to follow:

 **Step 1: Open the Control Panel**

Go to the Windows Start menu and search for Control Panel, then click on it to open it:

 **Step 2: Go to “Programs and Features”**

Once you reach the Control Panel, click on “ **Programs and Features** ” (or "Uninstall a program" depending on the version of Windows):

 **Step 3: Locate PostgreSQL**

Scroll down the list of programs until you find PostgreSQL. Click on it to select it:

 **Step 4: Uninstall PostgreSQL**

Click on the “ **Uninstall** ” button by pressing the right button of the mouse on the “PostgreSQL” program:

Follow the prompts to complete the uninstallation process:

Hit the “Next” button to begin the uninstallation of Postgres:

After completing the uninstallation, a new window will appear:

Hit the “Ok” button to finish.

 **Note:** Once the uninstallation is done, the user can manually delete the PostgreSQL files and folders that were left behind. These can typically be found in the “ **Program Files** ” or “ **Program Files (x86)** ” folder in the Windows installation:

Remove the “PostgreSQL” directory to completely uninstall Postgres from your Windows system.

 **Conclusion**

Uninstalling Postgres ensures that all of its files, configurations, and services are removed from the computer. To uninstall Postgres from windows, open the control panel > go to programs and features > locate PostgreSQL > Uninstall the PostgreSQL. This write-up demonstrated a step-by-step guide on uninstalling PostgreSQL from the Windows operating system.

---
[View this page online](https://www.commandprompt.com/education/how-to-uninstall-postgresql-from-windows/)

---

# How to Subtract Minutes From a Time in PostgreSQL

> In PostgreSQL, the “-” operator is used to subtract minutes from the current or specific DateTime values. Where the DateTime value can be a date, interval, tim…

Postgres offers numerous temporal data types that assist us in storing or manipulating the DateTime values efficiently. The built-in functions and operators of Postgres allow us to perform numerous tasks on DateTime values. Minus “-” is one of the built-in Postgres operators that allow us to subtract the specific minutes from a DateTime value.

The minus “-” operator has extended functionalities, however, this write-up explains how to subtract minutes from a time, date, timestamp, or interval using the “-” operator.

 **How to Subtract Minutes From a Time Using “-” Operator?**

To subtract minutes from a time, specify the “-” sign between the given times. We can specify the intervals while subtracting the DateTime values.

 **Example 1: Subtracting Minutes From a Specific Time**

In the below coding example, “19” minutes are subtracted from the given time:
    
    
    SELECT TIME '03:08' - INTERVAL '19 Minutes';

In the above snippet, the TIME and INTERVAL represent built-in temporal data types.

Nineteen minutes have been subtracted from the given time.

 **Example 2: Subtracting Minutes From Current Time**

In the following example code, “15” minutes are subtracted from the current time:
    
    
    SELECT CURRENT_TIME, 
    CURRENT_TIME - INTERVAL '15 Minutes' AS subtracted_time;

The specified minutes have been subtracted from the current time.

 **Example 3: Subtracting Minutes From a Specific Timestamp**

Let’s learn how to subtract “55” minutes from a particular timestamp:
    
    
    SELECT TIMESTAMP '2022-12-31 23:30:30' - INTERVAL '55 Minutes';

The specified minutes have been successfully subtracted from the given timestamp.

 **Example 4: Subtracting Minutes From Current Timestamp**

In this example, “15” minutes are subtracted from the current timestamp:
    
    
    SELECT CURRENT_TIMESTAMP - INTERVAL '15 Minutes';

Fifteen minutes have been successfully subtracted from the current timestamp.

 **Example 5: Subtracting Minutes From a Specific Interval**

Let’s learn how to subtract minutes from a specific interval using the “-” operator:
    
    
    SELECT INTERVAL '5 years 4 days 2 hours 10 minutes' - INTERVAL '17 Minutes';

“17” minutes have been successfully subtracted from the given interval using the “-” operator.

 **Example 6: Subtracting Minutes FROM Current Date**

In the below snippet, “75” minutes are subtracted from the current date using the “-” operator:
    
    
    SELECT CURRENT_DATE - INTERVAL '75 Minutes';

The output demonstrates that the specified minutes have been successfully subtracted from the current date.

 **Example 7: Subtracting Seconds From Specific Minutes**

In the below code, “130” seconds are subtracted from the given minutes using the “-” operator:
    
    
    SELECT TIME '00:09:00' - INTERVAL '380 Seconds';

“380” seconds have been subtracted from the given minutes.

 **Conclusion**

In PostgreSQL, the “-” operator is used to subtract minutes from the current or specific DateTime values. Where the DateTime value can be a date, interval, time, or timestamp. We can specify the intervals while subtracting the DateTime values. The minus “-” operator has extended functionalities, however, in this post, we have explained a few use cases of the “-” operator, such as how to subtract minutes from a time, date, timestamp, or interval using the “-” operator.

---
[View this page online](https://www.commandprompt.com/education/how-to-subtract-minutes-from-a-time-in-postgresql/)

---

# How to Use RPAD() Function in PostgreSQL

> RPAD() or “right padding” is a built-in function in Postgres which fills a string of a specific length with a substring. It fills/pads the given string from th…

PostgreSQL offers numerous in-built functions to deal with the TEXT data, such as TRIM(), LPAD(), REPLACE(), etc. One such function is **RPAD()** or “right padding” which fills a string of a specific length with a substring. It fills/pads the given string from the right side.

This post demonstrates a complete overview of the Postgres RPAD() function using practical examples.

 **How to Use RPAD() Function in Postgres?**

The RPAD() function accepts three arguments: a “main_string”, “length”, and “fill_string”:
    
    
    RPAD(main_string, length, fill_string);

Here, the “main_string” argument represents a string that will be filled by the “fill_string”, the length represents the string’s total length, and the “fill_string” argument represents a substring that will fill up the main string.

 **How Does the RPAD() Function Work in Postgres?**

When we use RPAD(), we have three options:

  * The substring’s length is equal to the main string’s remaining length. In such a case, the substring fills up the remaining length of the main string appropriately.
  * The substring’s length is less than the main string’s remaining length. In such a case, the substring will be repeated until-unless it fills up the remaining length of the string completely.
  * The substring’s length is greater than the main string’s remaining length. In such a case, the substring will be trimmed from the right side.



 **Example 1: Substring With Appropriate Length**

The below snippet demonstrates how the RPAD() function work in Postgres:
    
    
    SELECT RPAD('Hello World', 15, '-123');

In this code, the “Hello World” is a main string of length 10, “15” represents the total string length, and “-123” represents a substring of length 4:

The output demonstrates that the substring has filled the remaining length of the main string appropriately.

 **Example 2: Substring With Less Length**

In the following example, the substring’s length is less than the remaining length of the main string:
    
    
    SELECT RPAD('Hello World', 15, '-1');

In this code, “-1” is a substring of length 2 that will be repeated, as follows:

The output indicates that the substring repeats until the remaining length of the string fills completely.

 **Example 3: Substring With More Length**

In the following code, the substring’s length is greater than the remaining length of the main string:
    
    
    SELECT RPAD('Hello World', 15, '-12345');

In this code, the substring “12345-” is greater than the main string’s remaining length. As a result, the substring will be trimmed from the left side, as follows:

The output shows that the extra characters from the substring have been trimmed successfully.

 **Conclusion**

 **RPAD()** or “right padding” is a built-in function in Postgres which fills a string of a specific length with a substring. It fills/pads the given string from the right side. The RPAD() function accepts three arguments: “main_string”, “length”, and “fill_string”. The “main_string” argument represents a string that will be filled by a substring “fill_string”. The length represents the string’s total length. And the “fill_string” argument represents a substring that will fill up the main string. This write-up explained the usage of the RPAD() function in Postgres using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-rpad-function-in-postgresql/)

---

# How to Find Difference Between Two TIMESTAMPS in PostgreSQL

> In PostgreSQL, the minus operator “-”, the EXTRACT(), and the AGE() functions are used to find the difference between the given timestamps.

In PostgreSQL, the AGE() function, the minus operator “-”, and the EXTRACT() function is used to get the difference between two timestamps. The “-” operator and AGE() function return the timestamp difference as an interval. While to get the TIMESTAMPS difference in seconds, the EXTRACT() function is executed along with the EPOCH.

This post demonstrates how to find timestamp differences in Postgres using the AGE() function, the minus “-” operator, and the EXTRACT() function.

 **How to Find the TIMESTAMPS Difference in Postgres Using Minus Operator?**

Use the below syntax to find the timestamp difference via the “-” operator:
    
    
    TIMESTAMP 'TIMESTAMP_2' - TIMESTAMP 'TIMESTAMP_1';

The return type of the resultant value will be “INTERVAL”.

 **Example: Finding Timestamp Difference Using “-” Operator**

A sample table named “employee_data” has already been created in the database with the following data:

Suppose we have to subtract the “emp_joining_date” from the CURRENT_TIMESTAMP to get the TIMESTAMP difference as an interval:
    
    
    SELECT emp_name, emp_joining_date, CURRENT_TIMESTAMP - emp_joining_date 
    FROM employee_data;

The “-” operator successfully retrieves the timestamp difference in INTERVAL.

 **How to Find the TIMESTAMP Difference in Postgres Using AGE() Function?**

A timestamp difference as an INTERVAL can be obtained by passing the given timestamps to the AGE() function:
    
    
    AGE('timestamp_1', 'timestamp_2');

 **Example: Finding Timestamp Difference Using AGE() Function**

In this example, the AGE() function is utilized to fetch the difference between the current timestamp and the employee’s joining_date:
    
    
    SELECT emp_name, emp_joining_date, AGE(CURRENT_TIMESTAMP, emp_joining_date) 
    FROM employee_data;

The AGE() function retrieves the timestamp difference as an interval.

 **How to Find the TIMESTAMPS Difference in Postgres Using EXTRACT() Function?**

In Postgres, the EXTRACT() function is used with the collaboration of the EPOCH to get the timestamp difference in seconds:
    
    
    EXTRACT(EPOCH FROM (timestamp_1 - timestamp_2));

Let’s put this concept into practice for a profound understanding.

 **Example: Finding Timestamp Difference in Seconds**

The below-given statement illustrates how to utilize the EXTRACT() function to calculate the timestamp difference in seconds:
    
    
    SELECT emp_name, emp_joining_date, 
    EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP, emp_joining_date)) 
    FROM employee_data;

The output snippet proves that the “EXTRACT()” function succeeds in finding the timestamp difference in seconds.

 **Conclusion**

In PostgreSQL, the minus operator “-”, the EXTRACT(), and the AGE() functions are used to find the difference between the given timestamps. The “-” operator and AGE() function retrieves the timestamp difference as an interval. While the EXTRACT() function is used with the collaboration of the EPOCH and it returns the timestamp difference in seconds. This post presented a thorough overview of finding the timestamp difference using the “-” operator, the AGE() function, and the EXTRACT() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-difference-between-two-timestamps-in-postgresql/)

---

# How to Check if PostgreSQL Array Contains a Value

> PostgreSQL offers a built-in ANY() function that accepts an array as an argument, checks the presence of the given value in the array, and returns a Boolean tr…

Postgres provides a built-in function named ANY() that assists us in checking the existence of an element in an array. It accepts an array as an argument, checks the presence of the selected element, and returns a boolean true or false. The “true” value indicates that the selected value exists in the targeted array while the “false” value shows that the selected element doesn’t exist in the targeted array.

This write-up demonstrates how to check if an array contains a specific element or not.

 **How Do I Check if an Array Contains a Particular Value/Element?**

Use the following syntax to check the existence of an element in an array via the ANY() function:
    
    
    val = ANY (arr);

Here, the “val” represents a value to be checked in the targeted array, while “arr” represents the targeted array. The “arr” can be an array literal(enclosed within single quotes), a column of array data type, or a subquery that returns an array.

 **Example 1: Checking the Existence of a Text Value**

The following code checks the presence of “Henry” in the given array using the ANY() function:
    
    
    SELECT 'Henry' = ANY('{Seth, Mike, Joseph, Joe, John}') As array_contains;

The “f” in the output indicates the absence of “Henry” in the given array.

 **Example 2: Checking the Existence of a Numeric Value**

The following code checks the existence of a value “25” in an array using the ANY() function:
    
    
    SELECT 25 = ANY('{100, 12, 30, 150, 25}'::int[]) As array_contains;

The “ **::** ” operator is used in the code for string array to int array conversion:

The “t” represents that the selected element exists in the given array.

 **Example 3: How to Use ANY() Function on Table’s Data?**

Let’s create a sample table and named it “std_tbl”:
    
    
    CREATE TABLE std_tbl( 
    std_id SMALLINT, 
    std_name VARCHAR(15), 
    marks_obtained INT[] 
    );

Now, insert the data into the std_tble using the “INSERT INTO” command:
    
    
    INSERT INTO std_tbl(std_id, std_name, marks_obtained)
    VALUES (1, 'Joe', ARRAY[45, 57, 67, 70]),
    (2, 'John', ARRAY[60, 45, 47, 77]),
    (3, 'Stephen', ARRAY[55, 60, 70, 50]);

Let’s use the ANY() function to check the presence of “45” in the “marks_obtained” array:
    
    
    SELECT std_name, marks_obtained
    FROM std_tbl
    WHERE 45 = ANY(marks_obtained) As array_contains;

The ANY() function returns all those records that contain a value of “45”.

 **Conclusion**

PostgreSQL offers a built-in function named ANY() that checks the presence of a specific element in an array. It accepts an array as an argument, checks the presence of the given value in the array, and returns a boolean true or false. The “true” value represents that the selected value exists in the targeted array while the “false” value indicates that the selected element doesn’t exist in the targeted array. This guide presented a detailed guide on how to check the presence of a particular value in an array using the ANY() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-if-postgresql-array-contains-a-value/)

---

# How to Sort Multiple Columns Using ORDER BY Clause in PostgreSQL

> In Postgres, the comma-separated syntax is used in the ORDER BY clause to sort the table’s data based on multiple columns.

Querying the data from a Postgres table retrieves the data in an unspecified order. To get the table’s data into a particular order the ORDER BY clause is used in the database management systems. Using the ORDER BY clause, we can classify the Postgres tables in ascending or descending order on the basis of single/multiple columns.

This post presents a detailed guide on sorting the table’s data based on multiple columns.

 **How to Sort Multiple Columns in Postgres?**

In Postgres, the ORDER BY clause allows us to sort the table’s data on the basis of multiple columns. The comma-separated syntax is used in the ORDER BY clause to sort the table’s data based on multiple columns:
    
    
    SELECT col_list
    FROM tbl_name
    ORDER BY col_1 [ASC | DESC], col_2 [ASC | DESC], …, col_N [ASC | DESC];

Here, col_list represents the table’s columns.  
tbl_name represents a table to be sorted.  
col_1, col_2, …, col_n represent the columns based on which the table will be sorted.  
The parameter ASC or DESC decides the tables’ sorting order, i.e., ascending or descending.

 **Example 1: Sorting a Table Based on a Single Column**

A table named “emp_data” has been created with three columns: emp_id, emp_name, and joining_date. Let’s query the table’s data using the “SELECT” query:
    
    
    SELECT * FROM emp_data;

The output shows that the result set is in an unspecified order. To get the result set in a particular order, use the ORDER BY clause with a specific sorting parameter, i.e., ASC or DESC:
    
    
    SELECT * FROM emp_data
    ORDER BY emp_id ASC;

The result has been sorted into ascending order successfully.

 **Example 2: Sorting a Postgres Table Based on Multiple Columns**

Specify the multiple columns in the ORDER BY clause to sort the table’s data based on the specified columns:
    
    
    SELECT * FROM emp_data
    ORDER BY emp_id ASC, emp_name ASC;

From the result set, you can observe that the employees who have the same ids have been sorted based on their names. This is how the multi-column sorting works in Postgres.

 **Example 3: Sorting Multiple Columns Descendingly**

Specify the multiple columns in the ORDER BY clause to sort the table’s data based on the specified columns:
    
    
    SELECT * FROM emp_data
    ORDER BY emp_id DESC, emp_name DESC;

The output proves that multiple columns have been sorted descendingly.

 **Conclusion**

In Postgres, the ORDER BY clause allows us to classify the Postgres tables in ascending or descending order based on single/multiple columns. The comma-separated syntax is used in the ORDER BY clause to sort the table’s data based on multiple columns. This Postgres blog presented a thorough overview of how to sort table data based on multiple columns using the ORDER BY clause.

---
[View this page online](https://www.commandprompt.com/education/how-to-sort-multiple-columns-using-order-by-clause-in-postgresql/)

---

# How to Get the Month Name From a Date in PostgreSQL

> To get a month name from a date, specify the date/timestamp as the first and “MONTH” as the second argument to the TO_CHAR() function.

PostgreSQL provides a wide range of built-in functions to work with date and time values, such as NOW(), EXTRACT(), DATE_PART(), etc. To get a specific date filed, the EXTRACT() and DATE_PART() functions are used in Postgres. However, these functions return the date field as an integer. To get a date field as a text the built-in TO_CHAR() function is used in Postgres.

This post presents an in-depth guide on getting the month name from a date or timestamp.

 **How Do I Get the Month’s Name From a Date in Postgres?**

To get a month name from a date, specify the date/timestamp as the first and “MONTH” as the second argument to the TO_CHAR() function:
    
    
    TO_CHAR(TIMESTAMP | DATE, 'Month');

Let's put this concept into practice.

 **Example 1: Getting Month Name From Date**

In the following snippet, the TO_CHAR() function is used to get the month name from the given date:
    
    
    SELECT TO_CHAR(DATE '2010-02-10', 'Month') AS month_name;

The TO_CHAR() function fetches the month name from the given date.

 **Example 3: Getting Month Name From Current Date**

To get the month name from the current date, the CURRENT_DATE function and “Month” are passed as arguments to the TO_CHAR() function:
    
    
    SELECT TO_CHAR(CURRENT_DATE, 'Month') AS current_month_name;

The stated function succeeded in getting the month name from the current date.

 **Example 3: Getting Month Names in Different Letter Cases**

The below snippet demonstrates how to get the month names in different letter cases:
    
    
    SELECT TO_CHAR(DATE '2010-07-10', 'Month') AS init_cap,
    TO_CHAR(DATE '2010-07-10', 'month') AS lowercase,
    TO_CHAR(DATE '2010-07-10', 'MONTH') AS uppercase;

 **Example 4: Getting Abbreviated Month Names**

The following code depicts how to get an abbreviated month name in Postgres using the TO_CHAR() function:
    
    
    SELECT TO_CHAR(DATE '2010-08-10', 'Mon') AS abbreviated_month_name;

The TO_CHAR() function successfully retrieves the abbreviated month name.

 **Example 5: Getting Month Names From Table’s Data**

A sample table named “emp_data” has already been created, whose data is enlisted in the following snippet:

Let’s use the “TO_CHAR()” function to get the month names from the “joining_date” column:
    
    
    SELECT emp_name, joining_date, TO_CHAR(joining_date, 'Month') AS joining_month
    FROM emp_data;

The month names from the “joining_date” column have been retrieved successfully.

 **Conclusion**

To get a month name from a date, specify the date/timestamp as the first and “MONTH” as the second argument to the TO_CHAR() function. The letter case for the extracted month name depends on the second parameter of the TO_CHAR() function. To get the abbreviated month name, pass the first three letters, such as “MON” as the second parameter to the TO_CHAR() function. This post presented a detailed guide on getting the month's name from a date using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-month-name-from-a-date-in-postgresql/)

---

# How to Use pg_size_pretty() Function in PostgreSQL

> In PostgreSQL, the pg_size_pretty() function retrieves the size of the database object in a human-readable format, such as KB, MB, etc.

In PostgreSQL, various built-in functions are used to get the size of database objects. For instance, the pg_relation_size() function retrieves the size of a particular table, the pg_database_size() function retrieves the size of a particular database, the pg_total_relation_size() function retrieves the total size of a table, etc.

All these functions return the size in bytes, which might be difficult to read/understand when the size of the object is too big. Therefore, Postgres provides a pg_size_pretty() function that retrieves the size of the database object in a more readable format, such as KB, MB, etc.

This post presents a comprehensive guide on how to use the “pg_size_pretty()” function to get the size of a database object in a human-readable format.

 **How to Get the Size of a Database Object Using pg_size_pretty() Function in Postgres?**

To get the size of database objects in human-readable format use the pg_size_pretty() function as follows:
    
    
    pg_size_pretty (function);

Where the “function” can be the pg_relation_size(), pg_database_size(), pg_tablespace_size(), etc.

 **Example 1: Getting Database and Table Size in Postgres**

Let’s consider the following snippet to understand how the pg_relation_size() function and the pg_database_size() function work in Postgres:
    
    
    SELECT pg_database_size ('postgres') AS db_size,
    pg_relation_size('emp_data') AS table_size;

The output shows that the stated functions retrieve the size in bytes.

 **Example 2: Getting Database and Table Size in an Easily-Understandable Format**

The below snippet demonstrates how to get the database and table size in a more readable format:
    
    
    SELECT pg_size_pretty(pg_database_size ('postgres')) AS db_size,
    pg_size_pretty (pg_relation_size('emp_data')) AS table_size;

The pg_size_pretty() returns the size in a well-understandable format.

 **Example 3: Getting Tablespace Size in Postgres**

In the following code snippet, the pg_tablespace_size() function is used to fetch the size of the default tablespace:
    
    
    SELECT pg_tablespace_size('pg_default') AS tablespace_size;

The output displays the size of the default tablespace.

 **Example 4: Getting Tablespace Size in Human-Readable Format**

In the following snippet, the pg_tablespace_size() function is used along with the pg_size_pretty() function to fetch the size of the default tablespace in human-readable format:
    
    
    SELECT pg_size_pretty(pg_tablespace_size('pg_default')) AS tablespace_size;

The output shows that the default tablespace takes 44MB size.

 **Example 5: Getting the Total Size of a Table in Postgres**

The following snippet shows how to get the total size of a table using pg_total_realtion_size() and pg_size_pretty() functions:
    
    
    SELECT pg_total_relation_size('emp_data') AS table_size,
    pg_size_pretty(pg_total_relation_size('emp_data')) AS pretty_size;

The output shows the total size of a table named “emp_data”.

 **Conclusion**

In PostgreSQL, the pg_size_pretty() function retrieves the size of the database object in a human-readable format, such as KB, MB, etc. The pg_size_pretty() function accepts the built-in functions like pg_relation_size(), pg_database_size(), pg_total_relation_size(), etc. as an argument and retrieves the object size in an easily understandable format. This post illustrates a thorough guide on how to use the “pg_size_pretty()” function to get the size of a database object in a well-understandable format.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-pg_size_pretty-function-in-postgresql/)

---

# How to Use LPAD() Function in PostgreSQL

> LPAD() or “left padding” is a built-in function in Postgres which fills a string of a specific length with a substring. It fills/pads the given string from the…

PostgreSQL offers a variety of built-in functions to handle the TEXT data, such as SUBSTRING(), RPAD(), TRIM(), etc. One such function is **LPAD()** or “left padding” which fills a string of a specific length with a substring. It fills/pads the given string from the left side.

This post presents a comprehensive overview of the Postgres LPAD() function using suitable examples.

 **How to Use LPAD() Function in Postgres?**

The LPAD() function accepts three arguments: “main_string”, “length”, and “fill_string”:
    
    
    LPAD(main_string, length, fill_string);

\- The “main_string” argument represents a string that will be filled by the “fill_string”.  
\- The length represents the string’s total length.  
\- The “fill_string” argument represents a substring that will fill up the main string.

 **How Does the LPAD() Function Work in Postgres?**

When we use LPAD(), we have three options:

  * The substring’s length is equal to the main string’s remaining length. In such a case, the substring fills up the remaining length of the main string completely/appropriately.
  * The substring’s length is less than the main string’s remaining length. In such a case, the substring will be repeated until-unless it fills up the remaining length of the string completely.
  * The substring’s length is greater than the main string’s remaining length. In such a case, the substring will be trimmed from the right side.



 **Example 1: Substring With Appropriate Length**

Let’s learn how the LPAD() function work in Postgres using the following example:
    
    
    SELECT LPAD('Hello World', 15, '123-');

In this code, the “Hello World” is a main string of length 10, “15” represents the total string length, and “123-” represents a substring of length 4. Therefore the substring “123-” will pad the main string “Hello World” appropriately:

The output shows that the substring fills the remaining length of the string appropriately.

 **Example 2: Substring With Less Length**

In the following example, the substring’s length is less than the remaining length of the main string:
    
    
    SELECT LPAD('Hello World', 15, '1-');

In this code, the “Hello World” is a main string of length 10, “15” represents the total string length, and “1-” represents a substring of length 2. Here, the substring “1-” is less than the main string’s remaining length. As a result, the substring will be repeated, as follows:

The output shows that the substring repeats until the remaining length of the string fills completely.

 **Example 3: Substring With More Length**

In the following code, the substring’s length is greater than the remaining length of the main string:
    
    
    SELECT LPAD('Hello World', 15, '12345-');

In this code, the main string is of length 10, the total length is “15”, and the substring is of length 6. Here, the substring “12345-” is greater than the main string’s remaining length. As a result, the substring will be trimmed from the right side, as follows:

The output shows that the extra characters from the substring have been trimmed from the right side.

 **Conclusion**

 **LPAD()** or “left padding” is a built-in function in Postgres which fills a string of a specific length with a substring. It fills/pads the given string from the left side. The LPAD() function accepts three arguments: “main_string”, “length”, and “fill_string”. The “main_string” argument represents a string that will be filled by a substring “fill_string”. The length represents the string’s total length. And the “fill_string” argument represents a substring that will fill up the main string. This post explained how to use the LPAD() function in PostgreSQL using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-lpad-function-in-postgresql/)

---

# How to Generate Random Numbers in PostgreSQL

> In Postgres, the RANDOM() is an in-built function that generates a random numeric value between “0(inclusive)” and “1(exclusive)” or between a specific range.

Postgres offers a built-in RANDOM() function that generates a random numeric value between “0(inclusive)” and “1(exclusive)”. In PostgreSQL, the RANDOM() function can be used to get a random number between a specific range. It doesn’t require any argument/parameter.

This post presents a comprehensive guide on how to generate random numbers in PostgreSQL.

 **How to Use RANDOM() Function to Get Random in Postgres?**

The below-provided syntax is used in Postgres to get a random number between 0 and 1:
    
    
    SELECT RANDOM();

Use the below-provided syntax to get a random number between a specific range:
    
    
    SELECT RANDOM()*(Num_2- Num_1) + Num_1;

Where “Num_1” is the least value and “Num_2” represents the greatest value.

The return type of the RANDOM() function is DOUBLE PRECISION. However, the functions like FLOOR() and TRUNC() can be used with the RANDOM() function to get a random integer.
    
    
    SELECT FLOOR(RANDOM()*(Num_2- Num_1 + 1)) + Num_1;

The above-given syntax will generate a random integer between Num_1 and Num_2, inclusive.

 **Example 1: Generating a Random Number**

The following example demonstrates how to generate a random numeric value between 0(included) and 1(not included) via the RANDOM() function:
    
    
    SELECT RANDOM() AS random_number;

A random number between the range “0<=num < 1” has been generated successfully.

 **Example 2: Generating a Random Number Between Specific Range**

The below snippet shows how to get a random numeric value between a specific range, let’s say “num >=5” and “num <15”:
    
    
    SELECT RANDOM()*(15 - 5) + 5;

A random numeric value has been generated between the given range, i.e., “5<= num < 15”.

 **Example 3: Generating a Random Integer Between a Specific Range**

The below-given code will generate a random integer between 5 and 25:
    
    
    SELECT FLOOR(RANDOM()*(25 - 5 + 1)) + 5 As random_val;

A random integer has been successfully generated between the specified range.

 **Example 4: Using RANDOM() Function on Table’s Data**

In Postgres, the RANDOM() function can be used with the ORDER BY clause to get the random records of a particular table. For instance, the below snippet shows all rows of the “emp_data” table:
    
    
    SELECT * FROM emp_data;

Use the RANDOM() function to get three random records from the selected table:
    
    
    SELECT *
    FROM emp_data
    ORDER BY RANDOM() LIMIT 3;

Three random records have been generated from the “emp_data” table.

 **Conclusion**

In Postgres, the RANDOM() is an in-built function that generates a random numeric value between “0(inclusive)” and “1(exclusive)” or between a specific range. It doesn’t require any argument/parameter. The return type of the RANDOM() function is DOUBLE PRECISION. However, the functions like FLOOR() and TRUNC() can be used with the RANDOM() function to get a random integer. This post presented a comprehensive guide on how to generate random numbers in Postgres using the RANDOM() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-generate-random-numbers-in-postgresql/)

---

# How to Format a TIMESTAMP in PostgreSQL

> To format a timestamp, specify a timestamp and a valid format as arguments to the Postgres TO_CHAR() function.

PostgreSQL supports various built-in functions to deal with the timestamp values efficiently, such as CURRENT_TIMESTAMP, TO_TIMESTAMP(), DATE_PART(), etc. The **TO_CHAR()** is one of the data type formatting functions that assist us in converting/formatting the data from one type to another.

This post demonstrates how to utilize the TO_CHAR() function to format a timestamp in Postgres.

 **How Do I Format a TIMESTAMP in Postgres?**

To format a timestamp, specify a timestamp and a valid format as arguments to the TO_CHAR() function:
    
    
    TO_CHAR(TIMESTAMP, format);

The return type of the stated function is “TEXT”. Visit the [official Postgres documentation](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE>) to see the valid formats for the TO_CHAR() function.

 **Example 1: Formatting a Timestamp in Postgres**

The following example explains how to format a timestamp in Postgres via the TO_CHAR() function:
    
    
    SELECT TO_CHAR(TIMESTAMP '2001-01-01 5:55:55', 'YYYY/MM/DD HH:MI:SS');

The given timestamp has been successfully formatted to a specific format.

 **Example 2: Formatting Current Timestamp in Postgres**

To format the current timestamp, specify the CURRENT_TIMESTAMP and a particular format to the TO_CHAR() function:
    
    
    SELECT TO_CHAR(CURRENT_TIMESTAMP, 'YYYY/MM/DD HH:MI:SS');

The current timestamp has been successfully converted to the specified format.

 **Example 3: Formatting Current Timestamp into 'DAY, DD MONTH YYYY HH:MM:SS' Format**

In the following snippet, the current timestamp is formatted into the “DAY, DD MONTH YYYY HH:MM:SS” format:
    
    
    SELECT to_char(CURRENT_TIMESTAMP, 'DAY, DD MONTH YYYY HH:MM:SS');

The current timestamp has been successfully formatted into the specified format.

 **Example 4: Formatting Current Timestamp to a Date in Postgres**

Use the TO_CHAR() function with the “::” operator followed by the “DATE” data type to format a given timestamp to a date:
    
    
    SELECT TO_CHAR(CURRENT_TIMESTAMP:: DATE, 'MON DD, YYYY');

The current timestamp has been successfully formatted into the given format.

 **Example 5: Formatting Current Timestamp to Current Time in Postgres**

In the below snippet, the TO_CHAR() function is utilized to format the current timestamp into the current time:
    
    
    SELECT TO_CHAR(CURRENT_TIMESTAMP:: TIME, 'HH:MM:SS');

The current timestamp has been successfully converted into the current time.

That’s all from this Postgres post.

 **Conclusion**

To format a timestamp, specify a timestamp and a valid format as arguments to the Postgres TO_CHAR() function. To format the current timestamp, specify the CURRENT_TIMESTAMP and a particular format to the TO_CHAR() function. Use the TO_CHAR() function with the “::” operator followed by the “DATE” data type to format the given timestamp to date. This write-up presented a detailed guide on getting a timestamp into a specific format using the Postgres TO_CHAR() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-format-a-timestamp-in-postgresql/)

---

# How to Convert EPOCH Time to Timestamps in PostgreSQL

> In PostgreSQL, to convert the epoch time to a timestamp, pass the EPOCH time as an argument to the TO_TIMESTAMP() function.

The EPOCH time represents the number of seconds elapsed since "1st January 1970 00:00:00" until the present. The EPOCH time shows the DateTime in seconds, which is not easily understandable. To get the EPOCH time in appropriate DateTime representation, it must be converted into a human-readable format. To convert the EPOCH time to timestamp, the TO_TIMESTAMP() function is used in Postgres.

This post presents an in-depth overview of converting the EPOCH time to a timestamp using the TO_TIMESTAMP() function.

 **How to Convert EPOCH Time to Timestamp Using TO_TIMESTAMP()?**

To convert the epoch seconds to appropriate DateTime, pass the EPOCH time as an argument to the TO_TIMESTAMP() function:
    
    
    TO_TIMESTAMP(epoch_time);

The below-provided examples will help you understand epoch-to-timestamp conversion in a better way.

 **Example: Converting EPOCH Time to Timestamp Using TO_TIMESTAMP()**

Let’s pass a specific epoch time to the TO_TIMESTAMP() function to convert it into a timestamp:
    
    
    SELECT TO_TIMESTAMP(1231201120);

The given epoch has been successfully converted into a timestamp. The timestamp is retrieved based on the system’s timezone.

 **How to Convert EPOCH Time to Timestamp With a Specific Timezone?**

Use the “TO_TIMESTAMP()” with the collaboration of the “TIMEZONE()” function to get a converted timestamp in a different timezone:
    
    
    SELECT TIMEZONE('specific_timezone', TO_TIMESTAMP(epoch_time));

 **Example: Converting an EPOCH to Specific Timezone**

The “specific_timezone” parameter must be replaced with one of the Postgres-supported timezones. To get the list of Postgres-supported timezones use the built-in “pg_timezone_names” table, as shown in the following snippet:
    
    
    SELECT * FROM pg_timezone_names;

Suppose we wanted to convert the EPOCH to a timestamp based on the “Africa/Abidjan” time zone. To accomplish this task, we will execute the following command:
    
    
    SELECT TIMEZONE('Africa/Abidjan', TO_TIMESTAMP(1231201120));

The given EPOCH time has been successfully converted into the specified timezone.

 **Conclusion**

The EPOCH time shows the DateTime in seconds, which is not easily understandable. To get the EPOCH time in appropriate DateTime representation, it must be converted into a human-readable format. In Postgres, to convert the epoch time to a timestamp, pass the EPOCH time as an argument to the TO_TIMESTAMP() function. Use the “TO_TIMESTAMP()” with the collaboration of the “TIMEZONE()” function to get a converted timestamp in a different timezone. This post presented a detailed guide on how to convert the EPOCH time to timestamp using the TO_TIMESTAMP() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-convert-epoch-time-to-timestamps-in-postgresql/)

---

# How to Set a TIMESTAMP as a Default Column Value in PostgreSQL

> Postgres allows us to set a TIMESTAMP as the column’s default value. For this purpose, the DEFAULT keyword is used with the column name at the time of table cr…

PostgreSQL supports a TIMESTAMP data type that is used to store the DateTime values in the database. In PostgreSQL, “NULL” is used as the column’s default value, if no default value is explicitly declared. However, if a particular value is assigned as the column’s default value, then the null values will be replaced with the respective default values.

This post presented an in-depth overview of how to set a timestamp as the column’s default value.

 **How to Set a TIMESTAMP as a Column’s Default Value in Postgres?**

Postgres allows us to set a TIMESTAMP as the column’s default value. For this purpose, the DEFAULT keyword is used with the targeted column at the time of table creation, as shown below:
    
    
    CREATE TABLE tbl_name(
    col_name DATA TYPE DEFAULT default_val
    );

Postgres allows us to set the TIMESTAMP as the default value of an already existing table’s column:
    
    
    ALTER TABLE tbl_name
    ALTER COLUMN col_name SET DEFAULT default_val;

 **Example 1: Setting a Column’s Default Value While Table Creation**

Let’s create a new sample table named “std_details” with three columns: std_id, std_name, std_age:
    
    
    CREATE TABLE emp_details( 
    emp_id SMALLINT, 
    emp_name TEXT, 
    emp_joining_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );

Execute the “\d” command followed by the table’s name to see the table’s structure:
    
    
    \d emp_details;

The CURRENT_TIMESTAMP is set as the selected column’s default value. Now, insert a row in the “emp_details” table to get a profound understanding of the column’s default value:
    
    
    INSERT INTO emp_details(emp_id, emp_name)
    VALUES (1, 'Stephen');

Execute the “SELECT” query to see the table’s data:
    
    
    SELECT * FROM emp_details;

The output shows that the current DateTime has been inserted into the “emp_joining_date” column, by default.

 **Example 2: Setting a Column’s Default Value While Table Alteration**

A sample table named “std_details” has already been created in the database, whose details are depicted in the following snippet:

In the following snippet, the ALTER TABLE statement is executed to set the current DateTime as the default value of the “s_joining_date” column:
    
    
    ALTER TABLE std_details
    ALTER COLUMN s_joining_date SET DEFAULT NOW();

The “std_details” table has been altered successfully. Run the “\d” command followed by the table’s name to see the table’s structure:
    
    
    \d std_details;

The NOW() function is set as the default value for the “s_joining_date” column.

 **Conclusion**

Postgres allows us to set a TIMESTAMP as the column’s default value. For this purpose, the DEFAULT keyword is used with the column name at the time of table creation. Postgres allows us to set the TIMESTAMP as the default value of an already existing table’s column. To do that, the ALTER TABLE and ALTER COLUMN commands are used with the SET DEFAULT keyword. This post presented a comprehensive guide on how to set a TIMESTAMP as the column’s default value in Postgres using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-set-a-timestamp-as-a-default-column-value-in-postgresql/)

---

# How to Compare Arrays in PostgreSQL

> To compare arrays in PostgreSQL, the equality operators, ordering operators, containment operators, and overlap operators are used.

In PostgreSQL, the comparison, containment, and overlap operators are used to compare arrays. The comparison operators are further categorized into two categories: the equality operators and the ordering operators. All these operators serve unique functionality, for instance, the equality operators perform the element-by-element comparison, the containment operators check if an array is contained by some other array or not, etc.

This post explains the following methods to compare arrays in Postgres:

  * Method 1: Using Comparison Operators
  * Method 2: Using Containment Operators
  * Method 3: Using Overlap Operator



 **Method 1: Using Comparison Operators**

The comparison operators are of two types, i.e., equality operators, and ordering operators:

\- The equality operators perform the element-by-element comparison and retrieve a boolean true or false.  
\- The “true” value signifies that the arrays are equal while the “false” value represents that the arrays are not equal.  
\- The equality operators include an equal to operator “=” and a not equal to operator “!=”, or “<>”.  
\- The ordering operators perform the comparison based on the array’s order.  
\- The ordering operators include a greater than sign “>”, a less than sign “<”, a greater than or equal to “>=” sign, and a less than or equal to “<=” sign.  
\- The ordering operators retrieve the result based on the first distinct pair of elements.

 **Example 1: How to Perform Array Comparison Using Equality Operators?**

Use the “=” operator to test if the given arrays are equal or not:
    
    
    SELECT ARRAY['John', 'Joseph', 'Anna', 'Henry'] = ARRAY['Henry', 'John'] As is_equal;

The “=” operator performs the exact element-by-element comparison and returns “f” because the elements of the given arrays are not equal. Let’s replace the “=” with “<>” operator and see how it works:
    
    
    SELECT ARRAY['John', 'Joseph', 'Anna', 'Henry'] <> ARRAY['Henry', 'John'] As not_equal;

The boolean “t” in the output shows that the input arrays are not equal.

 **Example 2: How to Perform Array Comparison Using Ordering Operators?**

The following example demonstrates the working of Postgres ordering operators:
    
    
    SELECT ARRAY['John', 'Joseph', 'Anna', 'Henry'] > ARRAY['Henry', 'John'] As greater_than,
    ARRAY['John', 'Joseph', 'Anna', 'Henry'] < ARRAY['Henry', 'John'] As less_than,
    ARRAY['John', 'Joseph', 'Anna', 'Henry'] >= ARRAY['Henry', 'John'] As greater_than_equal_to,
    ARRAY['John', 'Joseph', 'Anna', 'Henry'] <= ARRAY['Henry', 'John'] As less_than_equal_to;

The output snippet shows the comparative analysis of the ordering operators.

 **Method 2: Using Containment Operators**

In Postgres, the containment operators check if one array contains the elements of some other array or not. The containment operators include a “@>” operator and a “<@” operator. The “ @>” operator checks if the right array is contained by the left array. While the “<@” operator checks if the left array is contained by the right array.

 **Example: How to Compare Arrays Using Containment Operators?**

In the following example, the containment operator “<@” is used to compare two arrays:
    
    
    SELECT ARRAY['John', 'Joseph', 'Anna', 'Henry'] <@ ARRAY['Henry', 'John'] As contained_by_right_arr;

The “<@” operator will check if all the elements of the left array are contained by the right array:

The “f” in the output shows that all the elements of the left array are not present in the right array. Now, use the “@>” operator to see if the elements of the right array are contained by the left array:
    
    
    SELECT ARRAY['John', 'Joseph', 'Anna', 'Henry'] @> ARRAY['Henry', 'John'] As contained_by_left_arr;

The boolean “t” in the output represents that all elements of the right array are present in the left array.

 **Method 3: Using Overlap Operator**

In PostgreSQL, the “&&” sign is referred to as the overlap operator. The “&&” operator is used to test if the given arrays have some common elements.

 **Example: How to Compare Arrays Using Overlap Operators?**

In the below example, the overlap operator is used to compare the given arrays:
    
    
    SELECT ARRAY['John', 'Joseph', 'Anna', 'Henry'] && ARRAY['Henry', 'John'] As overlapped_array;

The output signifies that the given arrays are overlapped(contain common elements).

 **Conclusion**

To compare arrays in PostgreSQL, the equality, ordering, containment, and overlap operators are used. The equality operators perform the element-by-element comparison, the ordering operators perform the comparison based on the array’s order, the containment operators check if an array is contained by some other array or not, while the overlap operator checks if the given arrays have some common elements. This post explained various methods to compare arrays in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-compare-arrays-in-postgresql/)

---

# How to Calculate EPOCH Time in PostgreSQL

> In PostgreSQL, to extract epoch time from the current or specific time, the EXTRACT() function is used with the EPOCH argument.

In Postgres, the EPOCH time represents the total number of seconds elapsed from “1st January 1970 00:00:00” till today. The EXTRACT() function is used to calculate the EPOCH time from a specific DateTime value. The EPOCH can be extracted from the current or specific DateTime values.

This write-up presents an in-depth overview of how to extract EPOCH time from DateTime values in Postgres.

 **How to Calculate EPOCH Time in Postgres?**

To extract epoch time from the current or specific time, the EXTRACT() function is used with the EPOCH argument:
    
    
    EXTRACT (EPOCH FROM DateTime);

Where DateTime can be a “TIMESTAMP”, “DATE”, “TIME”, or “INTERVAL”.

 **Example 1: Extracting EPOCH FROM a Specific Timestamp**

In the following code, a specific timestamp and EPOCH are passed as arguments to get the epoch time:
    
    
    SELECT EXTRACT (EPOCH FROM TIMESTAMP '2020-01-12 01:10:15');

The EPOCH time has been successfully calculated.

 **Example 2: Extracting EPOCH FROM the Current Timestamp**

Pass the CURRENT_TIMESTAMP function and EPOCH as arguments to the EXTRACT() function to calculate the EPOCH time from the current timestamp:
    
    
    SELECT EXTRACT (EPOCH FROM CURRENT_TIMESTAMP);

The EPOCH time has been successfully extracted from the current timestamp.

 **Example 3: Extracting EPOCH FROM a Specific INTERVAL**

Specify the EPOCH and a specific INTERVAL as arguments to the EXTRACT() function to get the EPOCH time from a specific INTERVAL:
    
    
    SELECT EXTRACT(EPOCH FROM INTERVAL '2 days 3 hours ');

The output signifies that the EPOCH seconds have been extracted from the given INTERVAL.

 **Example 4: Extracting EPOCH FROM a Specific DATE**

Pass the EPOCH and a specific DATE as arguments to the EXTRACT() function to fetch the EPOCH time from the given date:
    
    
    SELECT EXTRACT(EPOCH FROM DATE '2021-01-12 ');

The output snippet shows that the given date has been converted into the EPOCH time.

 **Example 5: Extracting EPOCH FROM a Current DATE**

To extract the EPOCH time from the current date, specify the EPOCH and CURRENT_DATE as arguments to the EXTRACT() function:
    
    
    SELECT EXTRACT(EPOCH FROM CURRENT_DATE);

The output indicates that the current date has been converted to the EPOCH time.

 **Example 6: Extracting EPOCH FROM a Specific TIME**

To fetch the EPOCH time from the given time, pass the EPOCH and a specific time as arguments to the EXTRACT() function:
    
    
    SELECT EXTRACT(EPOCH FROM DATE '12:12:12 ');

The output shows that the EPOCH seconds have been fetched from the given TIME.

 **Example 7: Extracting EPOCH FROM a CURRENT TIME**

To get the EPOCH time from the current time, specify the EPOCH and CURRENT_TIME as arguments to the EXTRACT() function:
    
    
    SELECT EXTRACT(EPOCH FROM CURRENT_TIME);

The above snippet shows the EPOCH time for the current time.

 **Conclusion**

In PostgreSQL, to extract epoch time from the current or specific time, the EXTRACT() function is used with the EPOCH argument. Using the EXTRACT() function a “TIMESTAMP”, “DATE”, “TIME”, or “INTERVAL” can be converted into an EPOCH time. The EPOCH time retrieves the time in seconds and milliseconds. This post presented a thorough guide on how to calculate the EPOCH time in PostgreSQL using the EXTRACT function.

---
[View this page online](https://www.commandprompt.com/education/how-to-calculate-epoch-time-in-postgresql/)

---

# How to Check PostgreSQL Version on Ubuntu

> To check the PostgreSQL version in Ubuntu, use the &quot;SQL Shell&quot; (psql) tool, “pg_config”, “dpkg”, or “apt-cache” commands.

Ubuntu is one of the well-known operating systems, including PostgreSQL in its official repositories. It makes it easy for Ubuntu users to install, remove and use the database system. Once installed, users can interact with PostgreSQL through a variety of interfaces, including the command line interface, and graphical user interfaces. Checking the Postgres version on Ubuntu is an important step in maintaining the stability, security, and compatibility of your system.

This article will demonstrate all possible methods to check the Postgres version in Ubuntu.

\- Method 1: Using psql Command-Line Tool  
\- Method 2: Using pg_config Utility  
\- Method 3: Using the dpkg Command  
\- Method 4: Using the apt-cache Command

Let’s start with the first method.

 **Method 1: Using psql command-line Tool**

Before checking the Postgres version, use the “ **sudo** ” command with the “ **u** ” option to log in to PostgreSQL as a superuser:
    
    
    $ sudo -u postgres psql

After executing the above command, the user enters the Postgres shell as seen above.

To check the Postgres version in Ubuntu, use the “ **SELECT** ” statement with the “version()” function. It displays the current version of PostgreSQL:
    
    
    SELECT version();

The output displays the “ **14.6** ” version of PostgreSQL that is currently installed in Ubuntu.

 **Method 2: Using pg_config Utility**

If the config utility is installed, type the “ **pg_config** ” command with the “ **version** ” option to display the version of PostgreSQL:
    
    
    $ pg_config --version

It displays the “ **14.6** ” version of PostgreSQL that is currently installed in Ubuntu.

 **Note** : If the config utility is not installed in the system, install it by running the command “sudo apt install postgresql-server-dev-all”.

 **Method 3: Using the dpkg Command**

Users can also check the Postgres version by executing the “ **dpkg** ” command with the “ **l** ” option by specifying the PostgreSQL. It displays the version of PostgreSQL:
    
    
    $ dpkg -l postgresql

It displays the “ **14** ” version of PostgreSQL which is currently installed in Ubuntu.

 **Method 4: Using the apt-cache Command**

To display the version of PostgreSQL, users can utilize the “ **apt-cache** ” with the “ **policy** ” utility:
    
    
    $ apt-cache policy postgresql

The above output displays the “ **14** ” version of PostgreSQL that is installed in Ubuntu along with the repository it was installed from.

That is all from the guide.

 **Conclusion**

To check the PostgreSQL version in Ubuntu, use the “ **psql** ” tool, “ **pg_config** ”, “ **dpkg** ”, or “ **apt-cache** ” commands. These commands provide information about the currently installed version of PostgreSQL in Ubuntu. This guide has illustrated all possible methods to check the PostgreSQL version in Ubuntu.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-postgresql-version-on-ubuntu/)

---

# How to Add Minutes to a Time in PostgreSQL

> In PostgreSQL, the “+” operator is used to add minutes to the current or specific DateTime values. Where the DateTime value can be a date, interval, time, or t…

Postgres offers numerous temporal data types, such as TIME, DATE, INTERVAL, and TIMESTAMP. These data types assist us in storing or manipulating the DateTime values efficiently. Postgres allows us to perform numerous tasks on these DateTime values using different built-in functions and operators. One such operator is the “+” operator.

The addition “+” operator has extended functionalities, however, this write-up explains how to add minutes to time, date, timestamp, or interval using the “+” operator.

 **How to Add Minutes to a Time Using “+” Operator?**

In Postgres, the “+” operator allows us to add minutes to a specific time, date, interval, or timestamp. Let’s understand it using the following examples.

 **Example 1: Adding Minutes to a Specific Time**

In the following code, “35” minutes are added to a specific time:
    
    
    SELECT TIME '05:00' + INTERVAL '35 Minutes';

Here, TIME and INTERVAL represent built-in temporal data types.

The specified minutes have been added to the given time.

 **Example 2: Adding Minutes to Current Time**

In the following code, “35” minutes are added to the current time:
    
    
    SELECT CURRENT_TIME, CURRENT_TIME + INTERVAL '35 Minutes';

The specified minutes have been added to the current time.

 **Example 3: Adding Minutes to a Specific Timestamp**

In the following code snippet, “75” minutes are added to a specific timestamp:
    
    
    SELECT TIMESTAMP '2022-12-31 23:30:30' + INTERVAL '75 Minutes';

The given minutes have been successfully added to the input timestamp.

 **Example 4: Adding Minutes to Current Timestamp**

In this example, “75” minutes are added to the current timestamp:
    
    
    SELECT CURRENT_TIMESTAMP + INTERVAL '75 Minutes';

The given minutes have been successfully added to the current timestamp.

 **Example 5: Adding Minutes to a Specific Interval**

Let’s learn how to add minutes to a specific interval using the “+” operator:
    
    
    SELECT INTERVAL '3 years 2 months 4 days 2 hours 1 minute 30 seconds' + INTERVAL '75 Minutes';

“75” minutes have been added to a specific interval using the “+” operator.

 **Example 6: Adding Minutes With Current Date**

In the below snippet, “75” minutes are added to the current date using the “+” operator:
    
    
    SELECT CURRENT_DATE + INTERVAL '75 Minutes';

The output shows that the specified minutes have been successfully added to the current date.

 **Example 7: Adding Seconds to Specific Minutes**

In the below snippet, “180” seconds are added to the specified minutes using the “+” operator:
    
    
    SELECT TIME '00:05:00' + INTERVAL '180 Seconds';

The specified seconds have been added to the given minutes.

 **Conclusion**

In PostgreSQL, the “+” operator is used to add minutes to the current or specific DateTime values. Where the DateTime value can be a date, interval, time, or timestamp. We can specify the INTERVAL data type While adding the minutes with DateTime values. The addition “+” operator has extended functionalities, however, in this write-up, we have learned how to add minutes to time, date, timestamp, or interval using the “+” operator.

---
[View this page online](https://www.commandprompt.com/education/how-to-add-minutes-to-a-time-in-postgresql/)

---

# How to Connect to Postgres Database Server

> In Postgres, various tools, such as the “SQL Shell”, “pgAdmin”, and “Command Prompt” are used to connect to a Postgres database server.

When PostgreSQL is installed on a machine, some useful tools are also installed along with it, such as pgAdmin, psql, etc. These tools provide an interactive interface that assists us in working with Postgres in a better way. Using these tools, users can interact with the Postgres database server, manage database objects and its services, execute SQL queries, etc.

This post presents a detailed understanding of connecting to a Postgres database server via the following approaches:

  * Method 1: Using SQL Shell(psql)
  * Method 2: Using pgAdmin
  * Method 3: Using Command Prompt(CMD)



Let’s start with the psql.

 **Method 1: Using SQL Shell**

Press the “win + S” button to launch the windows search bar > search the “psql” > and click on the “SQL Shell” app to open it:

If you didn’t change the default settings then there is no need to specify the server name, port number, database name, or user name; just hit the “ENTER” button. Provide the superuser password to connect to the Postgres database server:

The above snippet shows that we are successfully connected to the “postgres” database server. Execute any command/query of your choice to confirm if the connection is established or not:
    
    
    \d

The “\d” command is executed to describe the available tables.

 **Method 2: Using pgAdmin**

Press the “win + S” button to open the windows search menu > search the “pgadmin” > and click on the “pgAdmin” app to open it:

Clicking on the “pgAdmin” app will lead you to the following window:

Provide the superuser password and hit the “OK” button to connect to the Postgres Database Server.

Open the Query tool and use any command/query to confirm if the connection is established or not. To fulfill this task, expand the “SERVERS” tree > right-click on a particular database under the “Databases” tab > and select “Query Tool”:

In the query tool, execute any command of your choice, as shown below:
    
    
    SELECT VERSION();

The stated command retrieves the currently installed Postgres version.

 **Method 3: Using Command Prompt(CMD)**

In the windows search menu > search the “cmd” > and click on the “CMD” app to open it:

Once the CMD is opened, access the Postgres bin directory:
    
    
    cd \Program Files\PostgreSQL\15\bin

Now execute the below-provided command to connect to the Postgres database Server:
    
    
    psql -U postgres

The output shows that we are successfully connected to “postgres” database server via the CMD.

 **Conclusion**

In Postgres, various tools, such as the “SQL Shell”, “pgAdmin”, and “Command Prompt” are used to connect to a Postgres database server. Launch the “SQL Shell” and specify the login details to connect to the Postgres database server via the “psql”. Open the “pgAdmin”, provide the superuser password, and hit the “OK” button to connect to the Postgres Database Server via pgAdmin. Using the CMD, you need to access the Postgres bin directory and then run the "psql -U postgres" command to connect to Postgres. This post explained how to connect to the Postgres database server using three different tools.

---
[View this page online](https://www.commandprompt.com/education/how-to-connect-to-postgres-database-server/)

---

# How to Find Difference Between Two Dates in PostgreSQL

> In Postgres, the “-” operator and the AGE() function are used to find the date difference. The “-” operator returns an integer while the AGE() function returns…

In PostgreSQL, the minus operator “-” and the AGE() function retrieve the difference between two dates. The “-” operator returns an integer that represents the date difference in days while the AGE() function retrieves the date difference as an interval. The “-” function is useful when you have to find the number of days between two dates while the AGE() function is used to present the date difference with great detail.

This post demonstrates how to find date differences in Postgres using the AGE() function and the minus “-” operator.

 **How to Find the Date Difference in Postgres Using Minus Operator?**

To find the date difference in days, all you need to do is subtract the first date from the second date:
    
    
    DATE 'date_2' - DATE 'date_1';

Let’s understand it with an example.

 **Example 1: Finding Date Difference Using “-”**

In the below-provided code, the minus operator is used to get the date difference in days:
    
    
    SELECT DATE '2002-06-01' - DATE '2001-01-01' AS date_diff;

The output shows the difference between given dates in “516” days.

 **Example 2: Finding the Date Difference From the Current Date Using “-”**

The following snippet calculates the difference in days between the current date and the specified date:
    
    
    SELECT CURRENT_DATE - DATE '2020-01-01' AS date_diff;

The output authenticates that the difference between the current date and the specified date is “1153” dates.

 **Example 3: Finding the Date Difference in Days From a Table**

A sample table named “emp_data” is created in the database with the following data:

Suppose we want to subtract the “joining_date” from the current_date to get the date difference in days. To fulfill this task, we will utilize the minus operator as follows:
    
    
    SELECT emp_name, joining_date, CURRENT_DATE - joining_date AS day_diff
    FROM emp_data;

The “-” operator retrieves the date difference in days.

 **How to Find the Date Difference in Postgres Using AGE() Function?**

Specifying the dates to the AGE() function as arguments will retrieve the date difference as an INTERVAL:
    
    
    AGE('date_1', 'date_2');

Let’s understand the AGE() function using the following examples.

 **Example 1: Finding the Difference Between Two Dates Using AGE()**

In the below code, the AGE() function is used to get the date difference as an interval:
    
    
    SELECT AGE('2002-06-01', '2001-01-01') AS date_diff;

The output shows that the difference between the given dates is “1 year and 5 months”.

 **Example 2: Finding the Difference Between From Current Date Using AGE() Function**

In the following snippet, the AGE() function is used to get the difference between the current date and the employee’s joining_date:
    
    
    SELECT emp_name, joining_date, AGE(CURRENT_DATE, joining_date)
    FROM emp_data;

The AGE() function retrieves the date difference as an interval.

 **Conclusion**

In PostgreSQL, the minus operator “-” and the AGE() function are used to find the difference between two dates. The “-” operator returns an integer while the AGE() function retrieves the date difference as an interval. The “-” function is useful when you have to find the number of days between two dates while the AGE() function is used to present the date difference with great detail. This write-up demonstrated a detailed guide to finding the date difference using the “-” operator and the AGE() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-difference-between-two-dates-in-postgresql/)

---

# How to Return Data from Modified Rows in PostgreSQL

> In PostgreSQL, use the RETURNING clause with the UPDATE, DELETE, or INSERT commands to return the modified rows.

In PostgreSQL, the RETURNING clause is used with the UPDATE, DELETE, and INSERT queries to return the modified records. The RETURNING clause retrieves the modified data without executing a separate query to fetch that data and hence saves a lot of time and effort. The “RETURNING *” clause is used in PostgreSQL to get all the modified records.

This write-up presents a precise guide on how to retrieve the data from modified rows using the RETURNING clause in PostgreSQL. For better understanding, the below-mentioned concepts will be considered in this post:

  * How to RETRIEVE Data From UPDATE Command?
  * How to RETRIEVE Data From INSERT Command?
  * How to RETRIEVE Data From DELETE Command?



So, let’s start with the UPDATE command.

 **How to RETRIEVE Data From UPDATE Command?**

We have already created a table named “emp_data”, whose records are shown in the following snippet:
    
    
    SELECT * FROM emp_data;

In the following snippet, we utilize the UPDATE command with RETURNING clause to modify and retrieve the employee name whose id is 3:
    
    
    UPDATE emp_data
    SET emp_name = 'Dean'
    WHERE emp_id = 3
    RETURNING *;

The output shows that the “RETURNING” clause successfully retrieves the updated row.

 **How to RETRIEVE Data From INSERT Command?**

This example illustrates how to use the RETURNING clause with the Postgres INSERT query:
    
    
    INSERT INTO emp_data(emp_id, emp_name, joining_date)
    VALUES (8, 'Kane', CURRENT_DATE)
    RETURNING *;

The output shows that one row has been inserted into the “emp_data” table. The newly inserted record has been retrieved using the “RETURNING” clause.

 **How to RETRIEVE Data From DELETE Command?**

In the following snippet, we utilize the DELETE command with RETURNING clause to delete and retrieve the employee whose id is 7:
    
    
    DELETE FROM emp_data
    WHERE emp_id = 7
    RETURNING *;

The output shows that one row has been successfully deleted from the “emp_data” table. The deleted record has been retrieved using the “RETURNING” clause.

 **Conclusion**

In PostgreSQL, use the RETURNING clause with the UPDATE, DELETE, or INSERT commands to get/return the modified rows. The RETURNING clause retrieves the modified data without executing a separate query, so it saves a lot of time and effort. Use the “RETURNING *” clause to get all the modified records. This post explained how to return data from updated rows using the RETURNING clause in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-return-data-from-modified-rows-in-postgresql/)

---

# PostgreSQL Timestamp Data Types With or Without Precision

> In PostgreSQL, to get a timestamp without precision, users need to specify “0” as an argument to the timestamp data type or timestamp functions.

Postgres supports a couple of built-in data types to store and manipulate the timestamps, such as the TIMESTAMP and TIMESTAMPTZ. The TIMESTAMPTZ data type stores the DateTime with timezone while the TIMESTAMP stores the DateTime without timezone information. Both these data types take eight bytes to store a DateTime value in the database.

This post presents a thorough guide on how to work with timestamp data types with or without precision.

 **PostgreSQL Timestamp Data Types With or Without Precision**

Postgres offers numerous built-in functions to work with the TIMESTAMP data types, such as NOW(), CURRENT_TIMESTAMP, etc. These functions return the timestamp with precision. The term “precision” represents the fractional points kept in the seconds' field. To get a timestamp without precision an optional parameter “p” must be set to “0”.

Let’s comprehend the TIMESTAMP data types via the below-given examples.

 **Example 1: TIMESTAMP With Precision**

In the following code, the sample table is created with two columns: emp_name and check_in.
    
    
    CREATE TABLE emp_details (
    emp_name TEXT,
    joining_date_time TIMESTAMPTZ
    );

Let’s use the CURRENT_TIMESTAMP function to insert the current DateTime in the joining_date column:
    
    
    INSERT INTO emp_details (emp_name, joining_date_time)
    VALUES ('Joe', CURRENT_TIMESTAMP);

Now, check out the table’s data using the “SELECT” command:
    
    
    SELECT * FROM emp_details;

The output shows that the current DateTime is added to the selected table with precision.

 **Example 2: TIMESTAMP Without Precision**

To get a timestamp without precision, specify “0” as an argument to the timestamp data type while table creation:
    
    
    CREATE TABLE emp_details_1 (
    emp_name TEXT,
    joining_date_time TIMESTAMPTZ(0)
    );

Now use the INSERT query to insert the current DateTime in the joining_date column:
    
    
    INSERT INTO emp_details_1 (emp_name, joining_date_time)
    VALUES ('Joe', CURRENT_TIMESTAMP);

To verify the table’s data, execute the “SELECT *” command:
    
    
    SELECT * FROM emp_details_1;

This way, you can store a timestamp without precision.

 **Example 3: TIMESTAMP With or Without Precision**

The below code demonstrates the comparative analysis of retrieving the timestamp with or without precision:
    
    
    SELECT CURRENT_TIMESTAMP AS with_precision,
    CURRENT_TIMESTAMP(0) AS without_precision;

This is how you can get the TIMESTAMP with or without precision.

 **Conclusion**

Postgres offers a couple of built-in temporal data types, such as the TIMESTAMP and TIMESTAMPTZ. By default, these data types store the DateTime values with precision. To get a timestamp without precision, users need to specify “0” as an argument to the timestamp data type or timestamp functions. This post presented a detailed guide on timestamp data types with or without precision.

---
[View this page online](https://www.commandprompt.com/education/postgresql-timestamp-data-types-with-or-without-precision/)

---

# How to Select All From a Table in PostgreSQL

> The SELECT statement is executed with the “*” symbol to select all data from a particular Postgres table. Use the ORDER BY clause with the SELECT * command to …

PostgreSQL supports various commands and queries to manipulate the tables' data. For example, the CREATE TABLE command creates a new table, the UPDATE TABLE command modifies an existing table, and the DROP TABLE removes a table, etc.

SELECT is one of the most often-used commands in Postgres that selects a specific record, multiple records, or all records from a specific table. The SELECT command is executed with the “*” symbol to select all data from a Postgres table.

This post demonstrates how to select all from a specific Postgres table.

 **How to Select/Fetch All From a Postgres Table?**

Use the “SELECT *” command followed by the FROM clause and then the table’s name to select all from a specific Postgres table:
    
    
    SELECT * 
    FROM tab_name;

Let’s understand it via the following example.

 **Example 1: Selecting All From a Table**

We have already created a Postgres table named “emp_data”. To fetch all from the “emp_data” table, use the “ **SELECT *** ” command:
    
    
    SELECT * FROM emp_data;

The SELECT * command retrieves all the records from the “emp_data” table.

 **Example 2: SELECT * With ORDER BY Clause**

The ORDER BY clause is optional for sorting a table in ascending or descending order.
    
    
    SELECT * 
    FROM tab_name
    [ORDER BY col_name ASC | DESC];

The below code demonstrates how to get all table data in a particular order:
    
    
    SELECT * 
    FROM emp_data
    ORDER BY emp_id ASC;

This time, the SELECT * command returns the table’s records in ascending order. To get the data in descending order, use the “DESC” keyword in the ORDER BY clause:
    
    
    SELECT * 
    FROM emp_data
    ORDER BY emp_id DESC;

The SELECT * command fetches the table’s data in descending order.

 **Example 3: SELECT * With GROUP BY Clause**

Use the GROUP BY clause with the “SELECT *” command to fetch all the records and divide them into a specific group:
    
    
    SELECT joining_date, COUNT(emp_id)
    FROM emp_data
    GROUP BY joining_date;

In the above snippet, the COUNT() function counts the number of employee ids, and the GROUP BY clause groups the employee’s ids based on their joining_date:

This way, the group by clause groups the table’s data into specific groups.

 **Conclusion**

In PostgreSQL, the SELECT command selects a specific record, multiple records, or all records of a specific table. The SELECT statement is executed with the “*” symbol to select all the data from a particular Postgres table. The ORDER BY clause can be used with the SELECT * command to sort the result set in a particular order. This post presented detailed knowledge on selecting all from a Postgres table.

---
[View this page online](https://www.commandprompt.com/education/how-to-select-all-from-a-table-in-postgresql/)

---

# How to Compare Dates in PostgreSQL?

> To perform the date comparison in Postgres, the “BETWEEN” clause, the “DATE_TRUNC()” function, and the basic comparison operators like “=”, “!=”, “&gt;=” etc., ar…

**DATE** is an important data type that stores calendar dates in PostgreSQL. Various built-in functions, operators, clauses, etc., are used in Postgres to store and manipulate the dates. For instance, the “ **BETWEEN** ” clause, the “ **DATE_TRUNC()** ” function, and the basic comparison operators like “=”, “!=”, “>=” etc., are used to compare the dates in Postgres.

This post presents an in-depth overview of comparing dates in Postgres using practical examples.

 **How to Compare Dates Using Comparison Operators?**

The WHERE clause fetches the table’s data based on a particular condition. Use the basic comparison operators in the WHERE clause to compare various dates, as shown in the following syntax:
    
    
    SELECT col_list
    FROM tbl_name
    WHERE date_col = specific_date;

Let’s understand the “=” operator via the following example.

 **Example 1: Comparing Dates Using = Operator**

A sample table named “emp_data” with the following content:
    
    
    SELECT * FROM emp_data
    ORDER BY emp_id ASC;

Let’s fetch the employees' data whose joining date is “2019-01-15”:
    
    
    SELECT * FROM emp_data
    WHERE joining_date = '2019-01-15';

In this example, a specific date is compared with the “joining_date” column of the “emp_data” table using the “=” operator:

The “=” operator performs the date comparison and retrieves the data accordingly.

 **Example 2: Using AND Operator With Comparison Operators**

In the following example, the AND operator is used in the WHERE clause to compare dates between a specific range:
    
    
    SELECT * FROM emp_data
    WHERE joining_date >= '2019-06-01' AND joining_date <= '2022-06-01';

The comparison operators “>=” and “<=” are used along with the AND operator to fetch the employees' data between a specific range:

The comparison operators compare the dates and retrieve the employees' data accordingly.

 **How to Compare Dates Using BETWEEN Clause?**

The **BETWEEN** operator/clause compares the given dates and returns the data within a specific range:
    
    
    SELECT * FROM emp_data
    WHERE joining_date BETWEEN '2019-06-01' AND '2022-06-01';

The BETWEEN operator retrieves the employees' data within the specified dates.

 **How to Compare Dates Using DATE_TRUNC() Function?**

The DATE_TRUNC() function can also be used to compare the dates based on a specific field, such as year, month, etc.
    
    
    SELECT * FROM emp_data
    WHERE DATE_TRUNC('YEAR', joining_date) = '2019-01-01';

The DATE_TRUNC() function compares the dates and returns the data based on the specified year.

 **Conclusion**

In PostgreSQL, different built-in functions, operators, clauses, etc., are used to store and manipulate the dates. To perform the date comparison, the “BETWEEN” clause, the “DATE_TRUNC()” function, and the basic comparison operators like “=”, “!=”, “>=” etc., are used in Postgres. The AND & OR operators can be used in the WHERE clause to combine multiple conditions. A detailed analysis of the date comparison is provided in this post using various methods.

---
[View this page online](https://www.commandprompt.com/education/how-to-compare-dates-in-postgresql/)

---

# PostgreSQL JSON_AGG() Function By Practical Examples

> In PostgreSQL, the JSON_AGG() function is used to combine multiple values into a single JSON array. The return type of the JSON_AGG() function is JSON.

PostgreSQL proposes various built-in functions to deal with JSON data. The **JSON_AGG()** is one such function that combines multiple values into a single JSON array. Using the JSON_AGG() function, a single column, multiple columns, or all columns of a table can be aggregated. The return type of the **JSON_AGG()** function is JSON.

This post demonstrates the usage of the **JSON_AGG()** function in PostgreSQL using numerous examples.

 **How to Use JSON_AGG() Function in Postgres?**

To use the JSON_AGG() function in Postgres, the below-provided syntax is used:
    
    
    JSON_AGG(expression);

In place of the “expression” parameter, you can specify any constant, table column, expression, or table reference. The stated function can aggregate the “NULL” values as well.

Let’s comprehend the usage of the JSON_AGG() function using the following examples.

 **Example 1: Basic Usage of the JSON_AGG() Function**

A sample table named “emp_data” has already been created with the following content:

Suppose we want to aggregate the employees' names. For this purpose, the JSON_AGG() function can be utilized as follows:
    
    
    SELECT JSON_AGG(emp_name) as employee_names
    FROM emp_data;

The output shows that all values(including null) of the “emp_name” column have been aggregated into a single JSON array.

 **Example 2: Using the JSON_AGG() Function With ORDER BY Clause**

Use the ORDER BY clause with the JSON_AGG() function to sort a JSON array into a specific order:
    
    
    SELECT JSON_AGG(emp_name ORDER BY emp_id DESC) as employee_names
    FROM emp_data;

The returned JSON array is sorted in descending order.

 **Example 3: Using the JSON_AGG() Function With WHERE Clause**

Use the WHERE clause with the JSON_AGG() function to aggregate the filtered data only:
    
    
    SELECT JSON_AGG(emp_name) as employee_names
    FROM emp_data
    WHERE emp_id <= 5;

The JSON_AGG() function aggregates only those employees’ names whose id is less than or equal to 5.

 **Example 4: Using the JSON_AGG() Function With GROUP BY Clause**

Use the GROUP BY clause with the JSON_AGG() function to group the aggregated data:
    
    
    SELECT joining_date, JSON_AGG(emp_name) as employee_name
    FROM emp_data
    GROUP BY joining_date;

The data have been aggregated based on the employees’ joining date.

 **Example 5: Using the JSON_AGG() Function to Aggregate All Columns**

The **JSON_AGG()** function can be used to aggregate all columns of a specific table into a single array:
    
    
    SELECT JSON_AGG(emp_data.*) as employee_info
    FROM emp_data;

The **JSON_AGG()** function successfully aggregated an entire table’s data into a single array.

 **Example 6: Using the JSON_AGG() Function to Aggregate Multiple Columns**

Passing multiple column names as arguments to the JSON_AGG() function will result in an error. Use the **WITH** clause to aggregate multiple columns without encountering any errors.
    
    
    WITH emp_info AS
    (SELECT emp_name, joining_date 
    FROM emp_data
    )
    SELECT JSON_AGG(emp_info.*)
    FROM emp_info;

\- The WITH clause(an auxiliary statement) is used in the above snippet to define a temporary table named “emp_info”.  
\- Multiple columns of the “emp_data” table are fetched using the SELECT statement and stored in the temporary table: “emp_info”.  
\- Finally, the JSON_AGG() function is used to aggregate multiple columns based on the temporary table “emp_info”:

The output snippet signifies that multiple columns of the “emp_data” table have been aggregated into a single array.

 **Conclusion**

In PostgreSQL, the **JSON_AGG()** function is used to combine multiple values into a single JSON array. The return type of the **JSON_AGG()** function is JSON. Passing multiple column names as arguments to the JSON_AGG() function results in an error. So, use the WITH clause to aggregate multiple columns without encountering any errors. This post demonstrated numerous examples to explain the working of the Postgres JSON_AGG() function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-json_agg-function-by-practical-examples/)

---

# PostgreSQL ALTER DATABASE Statement

> Postgres’ ALTER DATABASE command modifies the already existing databases, such as renaming a database, modifying the database attributes, changing the database…

Postgres supports an **ALTER DATABASE** statement that assists us in modifying the already existing databases. For instance, the ALTER DATABASE command allows Postgres users to rename a database, modify the database attributes, change the database ownership, reset configuration parameters, etc.

This Postgres guide presents a detailed overview of the **ALTER DATABASE** command using suitable examples.

 **How to Rename a Database in Postgres?**

Utilize the below-provided syntax to rename an already existing database via the **ALTER DATABASE** command:
    
    
    ALTER DATABASE db_name RENAME TO modified_name;

To rename a database, you must be a superuser or database owner with CREATEDB privileges. Moreover, the current database can’t be renamed in PostgreSQL. To accomplish this task, you need to establish a connection with some other database.

 **Example: Renaming a Database Via ALTER DATABASE Command**

Firstly, execute the “\l” command to list the available databases:
    
    
    \l

Suppose we want to rename a database named “postgres_copy” to “postgres_db”. For this purpose, the ALTER DATABASE command will be executed as follows:
    
    
    ALTER DATABASE postgres_copy
    RENAME TO postgres_db;

Let’s verify the database modification using the “\l” command:
    
    
    \l

The output clarifies that the selected database has been renamed to “postgres_db”.

 **How to Alter Database Attributes in Postgres?**

Utilize the below syntax to modify the attributes of an already existing database via the **ALTER DATABASE** command:
    
    
    ALTER DATABASE db_name WITH option;

Where the “option” parameter can be replaced with one of the following:

 **\- IS_TEMPLATE** : the value of the stated parameter can be either true or false. “true” indicates that the selected database can be cloned/copied by any user having CREATEDB rights. While specifying “false” means only superusers or the database owner can clone the selected database.  
**-** **ALLOW_CONNECTIONS** : If the "false" value is specified, establishing a connection with the selected database will not be possible.  
 **-** **CONNECTION LIMIT** : It determines how many concurrent connections can be established with a particular database. Specifying -1 indicates no connection limit.

To modify database attributes, you must be a superuser or database owner.

 **Example 1: Modifying Database Attributes**

The following example demonstrates how to modify a database attribute in Postgres:
    
    
    ALTER DATABASE postgres_db
    ALLOW_CONNECTIONS = FALSE;

The above query specifies a “ **false** ” value for the “ **ALLOW_CONNECTIONS** ” parameter so that no one can establish the connection with the “postgres_db” database:

Let’s execute the “\c” command followed by the respective database name to verify the working of the “ALLOW_CONNECTIONS” parameter:
    
    
    \c postgres_db;

The output clearly states that you can’t establish a connection with the “postgres_db”.

 **Note:** Similarly, the IS_TEMPLATE and CONNECTION LIMIT parameters can be used to change the database attributes.

 **How to Alter Database Owners in Postgres?**

Use the ALTER DATABASE command with the OWNER TO clause to alter the database owner:
    
    
    ALTER DATABASE db_name
    OWNER TO new_db_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER;

The superuser and database owner with CREATEDB privileges can alter the database owner.

 **Example: Changing the Database Owner in Postgres**

As shown in the following snippet, "postgres" owns the "postgres_db" database:

To change the owner of “postgres_db”, execute the below-provided command:
    
    
    ALTER DATABASE postgres_db
    OWNER TO sample_user;

Execute the “\l” command to verify the owner of the “postgres_db”:
    
    
    \l

The owner of the selected database has been changed successfully.

 **How to Alter Default Tablespace in Postgres?**

The “tablespace” represents a directory/location where Postgres saves the data files. To alter a tablespace of a particular database, the “ **ALTER DATABASE** ” command is used with the “ **SET TABLESPACE** ” clause:
    
    
    ALTER DATABASE db_name
    SET TABLESPACE new_tablespace;

To alter the database tablespace, you must be a superuser or database owner.

 **Example: Changing Databse’s Tablespace**

We have already created a tablespace named “sample_tablespace”. In the following example, we will execute the ALTER DATABASE command to change the default tablespace of the “postgres_db” database:
    
    
    ALTER DATABASE postgres_db
    SET TABLESPACE  sample_tablespace;

The tablespace has been successfully changed.

 **How to Alter Defaults Runtime Configuration Parameters in Postgres?**

By default, PostgreSQL loads the configuration parameters from the "postgresql.conf" file when it establishes a connection with a database. However, the ALTER DATABASE command assists us in overriding or altering these settings for a specific database:
    
    
    ALTER DATABASE db_name
    SET configuration_parameter = parameter_value;

Only the superusers and database owners can alter the database’s default run-time configuration parameters.

 **Example: Changing Defaults Runtime Configuration Parameters/Variables**

The following example addresses the “escape_string_warning” parameter for a database named “postgres_db”:
    
    
    ALTER DATABASE postgres_db
    SET escape_string_warning = off;

The database named “ **postgres_db** ” has been successfully altered.

 **Conclusion**

Postgres’ **ALTER DATABASE** command modifies the already existing databases, such as renaming a database, modifying the database attributes, changing the database ownership, setting the configuration parameters, etc. Only superusers or database owners can modify the existing databases. This post presented an in-depth understanding of the ALTER DATABASE statement using numerous examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-alter-database-statement/)

---

# How to Set Windows PATH for Postgres Tools

> To set Windows PATH for Postgres tools, open System Properties &gt; “Environment Variable” &gt; “Path” variable &gt; “Edit..” button &gt; “NEW” button &gt; specify Postgres b…

Postgres users may encounter a “psql not recognized as an internal/external command” error while executing the SQL Shell from CMD. The primary reason that causes the stated error is that the “Windows Path for Postgres tools is not set”. To overcome this problem and to get error-free output, Postgres’s bin directory must be added to the PATH system variable.

This post presents a practical guide on how to set up Windows PATH for Postgres tools. So, let’s begin.

 **How to Set Windows PATH for PostgreSQL Tools?**

To set the windows path for Postgres tools, you need to follow the steps listed below:

 **Step 1: Open the System Properties**

Firstly, press the “ **WIN + S** ” button to open the windows search menu:

In the search text bar, type “ **Edit the System Environment Variables** ”, and click on the respective option when you find it:

Clicking on the “Edit the System Environment Variables” will open the “ **system properties** ”:

 **Step 2: Open Environment Variables Window**

Once the “ **system properties** ” window is opened, select the “ **Environment Variables…** ” button under the “ **Advanced** ” tab:

Clicking on the“ **Environment Variables…** ” button will pop up a new window named “Environment variables”:

The “ **environment variables** ” window is split into two parts: “User Variables for HP” and “System Variables”.

 **Step 3: Set Environment Variables**

Select the “ **Path** ” variable under the system variables, and click on the “Edit..” button to get the list of all Path variables:

Clicking on the “ **Edit…** ” button will lead you to a new window where you can add a new path variable, edit a path variable, or delete a path variable:

To set the windows path for Postgres tools, you need to click on the “NEW” button and specify the Postgres bin directory’s path:

Click on the “OK” button to keep all the changes.

Alright! The Windows Path for the PostgreSQL tools has been “set” successfully. Now, you can use any Postgres tool on your Windows system.

 **Conclusion**

To set Windows PATH for PostgreSQL tools, firstly, open System Properties > open the “Environment Variable” window > select the “Path” variable under the system variables > click on the “Edit..” button > select the “NEW” button > specify the Postgres bin directory’s path > and click on the “OK” button to save all the modifications. This Post presented a practical guide on how to set the Windows Path for the Postgres tools.

---
[View this page online](https://www.commandprompt.com/education/how-to-set-windows-path-for-postgres-tools/)

---

# Different Methods to Copy or Clone a Table in PostgreSQL

> In Postgres, different commands, such as CREATE TABLE AS SELECT, CREATE TABLE AS TABLE, etc. are used to duplicate a table with or without data.

Postgres allows us to copy, clone, or duplicate a table with or without data. For this, different built-in commands, such as CREATE TABLE AS SELECT, CREATE TABLE AS TABLE, INHERITS, etc. are used in Postgres. Postgres supports all sorts of scenarios like copying an entire table, a partial table, or only the table’s structure.

This post demonstrates how to create a copy of a table in Postgres using four different methods.

  * Method 1: Using CREATE TABLE AS SELECT Command
  * Method 2: Using CREATE TABLE AS TABLE Command
  * Method 3: Using CREATE TABLE LIKE Command
  * Method 4: Using INHERITS Option



Users can use any of the stated methods depending on their needs.

 **Sample Table**

A sample table named “author_info” is created with the following data:

 **Method 1: Using CREATE TABLE AS SELECT Command**

The “CREATE TABLE AS SELECT” statement allows a user to copy an entire table, some specific records, or the table’s structure only. The stated command is not able to copy the indexes or constraints, such as NOT NULL, PRIMARY KEY, FOREIGN KEY, etc. Users need to follow the below-provided syntax to acquire the functionality of the stated command:
    
    
    CREATE TABLE new_table_name AS 
    SELECT * FROM existing_table_name
    WITH NO DATA
    WHERE condition;

Here, “ **new_table_name** ” represents a new table to be created while “ **existing_table_name** ” represents a table to be copied. However, if the " **WITH NO DATA** " option is specified, only the table structure will be copied. The “WHERE” clause will be utilized to copy a partial table.

 **Example 1: Duplicating a Complete Table**

To create the copy of the selected table, i.e., “author_info”, we will execute the “ **CREATE TABLE AS SELECT** ” command as follows:
    
    
    CREATE TABLE author_table_copy AS 
    SELECT * FROM author_info;

Execute the below-provided command to verify the working of the “CREATE TABLE AS SELECT” command:
    
    
    SELECT * FROM author_table_copy
    ORDER BY author_id ASC;

The clone of the “author_info” table has been created successfully.

 **Example 2: Duplicating a Partial Table**

To duplicate a partial table, use the CREATE TABLE AS SELECT statement with WHERE clause, as shown below:
    
    
    CREATE TABLE author_table_copy AS 
    SELECT author_id, author_name, author_exp
    FROM author_info
    WHERE author_id <= 5;

Execute the below-provided command to see the data from the duplicated table:
    
    
    SELECT * FROM author_table_copy
    ORDER BY author_id ASC;

A partial table has been copied successfully.

 **Example 3: Duplicating Table’s Structure**

Execute the “CREATE TABLE AS SELECT” command to duplicate only the table’s structure:
    
    
    CREATE TABLE author_table_copy AS 
    SELECT * FROM author_info
    WITH NO DATA;

Execute the below-mentioned command to see the data from the duplicated table:
    
    
    SELECT * FROM author_table_copy;

The table’s structure has been copied successfully.

 **Method 2: Using CREATE TABLE AS TABLE Command**

In PostgreSQL, the “ **CREATE TABLE AS TABLE** ” Command is used to duplicate the entire table or table’s structure only. However, you can’t copy indexes, NOT NULL, PRIMARY KEY, FOREIGN KEY constraints, etc. using the “CREATE TABLE AS TABLE” command.
    
    
    CREATE TABLE new_table_name AS 
    TABLE original_table
    WITH DATA | WITH NO DATA;

Specify the “ **WITH DATA** ” clause to duplicate a table with complete data. However, when the "WITH NO DATA" option is specified, only the table structure will be copied.

 **Example 1: Copying a Complete Table**

In the following code snippet, we will duplicate the entire table’s data via the “ **CREATE TABLE AS TABLE** ” command:
    
    
    CREATE TABLE new_table_name AS 
    TABLE original_table
    WITH DATA;

Execute the “SELECT” query to verify the table’s duplication:

 **Example 2: Copying Table’s Structure**

If you want only the table’s structure(without data), you must execute the “ **CREATE TABLE AS TABLE** ” statement with the “ **WITH NO DATA** ” clause:
    
    
    CREATE TABLE author_info_copy1 AS 
    TABLE author_info
    WITH NO DATA;

Execute the “SELECT” query to describe the table’s structure:

From the output snippet, you can observe that the table’s structure has been copied successfully.

 **Method 3: Using CREATE TABLE LIKE Command**

In Postgres, the “ **CREATE TABLE LIKE** ” statement is used to copy the table’s structure along with constraints, such as NOT NULL. The stated command has a pretty straightforward syntax, as shown in the following snippet:
    
    
    CREATE TABLE table_name (LIKE original_table_name);

Let’s put the above-stated syntax into practice.

 **Example: Copying Table Via the LIKE Option**

In the following example, the “CREATE TABLE” statement is executed with the “LIKE” option to create a copy of the “author_info” table:
    
    
    CREATE TABLE author_info_copy
    LIKE author_info;

Run the “SELECT” query to fetch the table’s structure:
    
    
    SELECT * FROM author_info_copy;

The output signifies that a copy of the “author_info” table has been created successfully.

 **Method 4: Using INHERITS Option**

Postgres offers an “INHERITS” option that is used to propagate the modifications made in the parent table to the child table. The “INHERITS” option not only inherits the data from the parent table but also allows us to add some new columns to the child table:
    
    
    CREATE TABLE child_table(
    col_name data_type constraint
    ) 
    INHERITS (parent_table);

Use the below query to inherit a table without including new columns in the child column:
    
    
    CREATE TABLE child_table()
    INHERITS (parent_table);

Let’s comprehend the usage of the “INHERITS” option via the below-provided example.

 **Example: Inherit Parent Table**

The below-given code inherits the “author_info” table via the **INHERITS** option:
    
    
    CREATE TABLE author_info_copy(
    author_age SMALLINT
    ) 
    INHERITS (author_info);

Execute the SELECT query to see the structure of the child(inherited) table:
    
    
    SELECT * FROM author_info_copy;

The output authenticates the usage of the “INHERITS” option.

 **Conclusion**

Postgres offers different built-in commands, such as CREATE TABLE AS SELECT, CREATE TABLE AS TABLE, INHERITS, etc. to copy, clone, or duplicate a table with or without data. For instance, the “CREATE TABLE AS SELECT” statement allows a user to copy an entire table, some specific records, or the table’s structure only, the “CREATE TABLE LIKE” statement is used to copy the table’s structure along with constraints, and so on. This post explained various methods to copy a table in Postgres.

---
[View this page online](https://www.commandprompt.com/education/different-methods-to-copy-or-clone-a-table-in-postgresql/)

---

# How to Start, Stop, or Restart the PostgreSQL Server?

> There are various ways to start, stop, or restart the Postgres server on Windows, such as using the “net start” command, “pg_ctl” utility, or “services” manage…

PostgreSQL is an advanced, freely available, and highly stable relational database management system that offers numerous features, such as accuracy, integrity, resilience, etc. The Postgres database is widely used for storing data of web apps, mobile apps, analytical apps, etc. However, to attain any Postgres features, you must know how to start, stop, or restart a Postgres Server.

To tackle such scenarios, Postgres offers different methods, such as the “pg_ctl” utility, “services” manager, etc. This post presents a practical guide on how to start, stop, or restart the PostgreSQL server on the Windows Operating System.

 **How Do I Start the Postgres Server?**

There are various ways to start the Postgres server on Windows, such as using the “ **net start** ” command, “ **pg_ctl** ” utility, or “ **services** ” manager.

 **Method 1: Starting Postgres Server Using “net start”**

Launch the Windows CMD as an administrator and execute the “net start” command to start the Postgres Server:
    
    
    net start postgresql-x64-15

 **Method 2: Starting Postgres Server Using “pg_ctl”**

Firstly, you need to find the directory’s path where Postgres is located. If you didn’t change the default path while installing Postgres, then it must be located in the “ **Program Files** ” directory inside the “ **C** ” drive.

The complete path will look something like this: “ **C:\Program Files\PostgreSQL\15\data** ”:

Once you find the complete path, open the CMD and execute the following command to “ **start the Postgres Server** ”:
    
    
    pg_ctl -D "C:\Program Files\PostgreSQL\15\data" start

 **Note:** Windows Path for Postgres tools must be set to get the error-free output. Else you will encounter a “not recognized as an internal/external command” error.

 **Method 3: Starting Postgres Server Using Services Manager**

Press the “win” key + “R” to launch the “Run” window. Type the “services.msc” and hit the “OK” button to open the Services Manager:

In the “Services Manager”, search for “Postgresql-x64-15”, select the service, and hit the “Start/play” button to start a Postgres server via the “services” manager:

Once you press the “start” button the service’s status will be changed to “running”:

 **How to Stop the Postgres Server on Windows?**

A Postgres server can be stopped using the “ **net stop** ” command, the “ **pg_ctl** ” utility, or the “ **services** ” manager.

 **Method 1: Stopping the Postgres Server Using “net stop”**

Execute the below-mentioned command from the Command prompt to stop the Postgres Server:
    
    
    net stop postgresql-x64-15

 **Method 2: Stopping the PostgreSQL Server via the “pg_ctl”**

Users may use the “pg_ctl” utility to stop the Postgres server:
    
    
    pg_ctl -D "C:\Program Files\PostgreSQL\15\data" stop

 **Method 3: Stopping the Postgres Server Using the Services Manager**

Open the “Services Manager”, search for “Postgresql-x64-15”, select the service, and hit the “Stop” button to stop a Postgres server via the “services” manager:

Clicking on the “Stop” button will stop the Postgres Server.

 **Note:** Similarly, to pause a Postgres Server on Windows, you can select the “ **pause** ” button from the Services manager or execute the “ **net pause postgresql-x64-15** ” command from the command prompt.

 **How Do I Restart the Postgres Server on Windows?**

You can restart the Postgres server on the windows operating system using the “ **Services** ” Manager and “ **pg_ctl** ” utility.

 **Method 1: Restarting the Postgres Server via the “pg_ctl”**

Run the below-given command from the CMD to restart the Postgres Server:
    
    
    pg_ctl -D "C:\Program Files\PostgreSQL\15\data" restart

 **Method 2: Restarting the Postgres Server Using the Services Manager**

Launch the “Services Manager”, locate the “Postgresql-x64-15”, select the desired service, and hit the “restart” button to restart a Postgres server via the “services” manager:

Clicking on the Restart button will restart the Postgres Server.

 **Conclusion**

There are various ways to start, stop, or restart the Postgres server on Windows, such as using the “ **net start** ” command, “ **pg_ctl** ” utility, or “ **services** ” manager. To get the error-free output, Windows Path for Postgres tools must be set. Else you will encounter a “not recognized as an internal/external command” error. This post presented a practical guide on how to start, stop, or restart the PostgreSQL server on the windows operating system.

---
[View this page online](https://www.commandprompt.com/education/how-to-start-stop-or-restart-the-postgresql-server/)

---

# How Do I Set/Change the Default Schema in PostgreSQL

> A schema in database management systems represents a set of rules that regulate/handle a database. It is a logical structure that holds various database object…

A schema in database management systems represents a set of rules that regulate/handle a database. It is a logical structure that holds various database objects like views, tables, indexes, sequences, etc. In Postgres, “public” is a Default schema. So, by default, Postgres users can access the "public" schema and create objects in it, such as views, tables, etc.

The **SET SEARCH_PATH** command, however, allows a user to set any other schema as the default schema. This post demonstrates how to change a schema in Postgres using the methods described below:

  *  **Method 1:** Change Schema for User’s Current Session
  *  **Method 2:** Change the Default Schema Permanently



 **Method 1: Change Schema for User’s Current Session**

This section presents stepwise instructions to change the schema for the current session only:

 **Step 1: Check the Current/Default Schema**

Execute the below-provided command to check the current/default schema:
    
    
    SHOW SEARCH_PATH;

The above snippet shows that the default schema is “public”.

 **Step 2: Change the Default Schema**

Now run the “\dn” command to see available schemas:
    
    
    \dn

Suppose we want to set the “example” schema as the default schema. For this purpose, use the “SET SEARCH_PATH” command, as follows:
    
    
    SET SEARCH_PATH = example;

The “SET” message in the output indicates that the selected schema has been set as the default schema.

 **Step 3: Confirm the Current Schema**

You can verify the default schema for the current session, using the below-provided command:
    
    
    SHOW SEARCH_PATH;

The “example” schema has been set as the default schema. However, it will remain the default schema for the current session only. Once the current session expires, the default schema will be reset to the “public” schema.

 **Method 2: Change the Default Schema Permanently**

This section describes the following aspects of changing the default schema permanently:

\- Changing the Schema at Database Level  
\- Changing the Schema at the User Level

 **How to Change Default Schema Permanently at the Database Level?**

To change a default schema at the database level, the “ **ALTER DATABASE** ” command is used with the “ **SET SEARCH_PATH** ” clause:
    
    
    ALTER DATABASE db_name SET search_path TO schema_name;

Replace the “ **db_name** ” and “ **schema_name** ” with the database and schema name of your choice.

 **Step 1: Connect to the Database**

First, use the “\l” command to see the available databases:
    
    
    \l

Let’s establish a connection to a database named “sample_db”:
    
    
    \c sample_db;

 **Step 2: Check the Current Schema**

Execute the below-provided command to check the current/default schema for the selected database:
    
    
    SHOW SEARCH_PATH;

To change the “ **public** ” schema to the “example” schema at the database level, the “ **ALTER DATABASE** ” command will be used as follows:
    
    
    ALTER DATABASE sample_db SET SEARCH_PATH TO example;

 **Step 3: Confirm the Current Schema**

You can check the current schema using the below-provided command:
    
    
    SHOW SEARCH_PATH;

Now, whenever you establish a connection with the “sample_db” database, the default schema for that particular database would be “example”.

 **How to Change Default Schema Permanently at User Level?**

To change a default schema at the user/role level, the “ **ALTER USER** ” or “ **ALTER ROLE** ” command is used with the “ **SET SEARCH_PATH** ” clause:
    
    
    ALTER ROLE|USER role_name SET search_path TO schema_name;

Specify the user name and schema name of your choice in place of “role_name” and “schema_name”.

 **Step 1: Current Default Schema**

We are currently logged in as the “postgres” user whose default schema is “public”, as shown in the following snippet:

 **Step 2: Change the Default Schema Permanently at the User Level**

To change the “ **public** ” schema to the “ **example** ” schema at a user level, the “ **ALTER USER** ” command will be used as follows:
    
    
    ALTER USER postgres SET SEARCH_PATH TO example;

 **Step 3: Confirm the Current Schema**

To verify the current schema, use the below-provided command:
    
    
    SHOW SEARCH_PATH;

Now, whenever you logged in as a “postgres” user, the default schema would be “example”.

 **Conclusion**

In PostgreSQL, the “ **SET SEARCH_PATH** ” command is used to change a schema temporarily. To change a schema permanently at the database level or user lever, the “ **ALTER DATABASE** ” and " **ALTER USER** " commands are used with the “ **SET SEARCH_PATH** ” command, respectively. This post presented a step-by-step guide on how to change the default schema in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-setchange-the-default-schema-in-postgresql/)

---

# How to Create a Copy of a Database in PostgreSQL

> In PostgreSQL, use the CREATE DATABASE command along with the “WITH TEMPLATE” parameter to copy or clone a database.

Copying an existing database or cloning a database is an important task in any database management system. Copying a database provides numerous features like time-saving, efficiency, data recovery, etc. Postgres allows us to create a new database based on the existing one. To accomplish this task the “ **CREATE DATABASE** ” command is used in Postgres.

This write-up presents a practical guide on how to copy a database in Postgres.

 **Copying or Cloning a Database in Postgres**

There are various methods to copy a database in Postgres, such as **CREATE DATABASE** , CREATEDB, etc. Among them, the most convenient way of copying a database is the “ **CREATE DATABASE** ” command, whose syntax is depicted in the following snippet:
    
    
    CREATE DATABASE [new_database_name]
    WITH TEMPLATE [original_database]
    OWNER [username];

Let’s comprehend the above syntax step-by-step:

  * The CREATE DATABASE statement creates a new database in Postgres.
  * The “new_database_name” represents the name of the duplicate/copied database.
  * The “WITH TEMPLATE” parameter is used to create a new database based on an already existing database template.
  * The “original_database” represents the name of the database to be copied.



Let’s put this syntax into practice.

 **Example 1: Copying a Database With CREATE DATABASE Command in Postgres**

Follow the below-provided steps to create a copy of a particular database in Postgres:

 **Step 1: Launching SQL Shell (psql)**

Open the psql and provide the necessary details to log in:

 **Step 2: Listing the Available Databases**

Once you are successfully logged in, execute the “\l” command to get the list of available databases:
    
    
    \l

Pick a database to be copied.

 **Step 3: Select a Database**

Suppose the user wants to copy the “postgres” database. Use the “\d” command to see the content of the selected database:
    
    
    \d

 **Step 4: Copying a Database**

Now, use the CREATE DATABASE command to copy the selected database:
    
    
    CREATE DATABASE postgres_copy
    WITH TEMPLATE postgres
    OWNER postgres;

A duplicate database named “postgres_copy” has been created successfully.

 **Step 5: Verify the Copied Database**

To verify if the selected database has been copied or not. Users must follow the below-provided instructions:

Firstly, connect to the newly created database via the “\c” command:
    
    
    \c postgres_copy;

The output snippet demonstrates that we have been successfully connected to the selected database, i.e. “postgres_copy”. Now, use the “\d” command to verify if the content of the original database has been copied to the “postgres_copy” database or not:
    
    
    \d

From the above snippet, you can clearly observe that the selected database has been copied successfully.

 **Example 2: 'Other Users are Accessing the Source Database' ERROR in Postgres**

While copying a database you may encounter a “Source Database is Being Accessed by Other Users” error, as shown in the following snippet:

In the above snippet, we encountered an error while creating a copy of the “postgres” database. The error states that multiple users are accessing/using the selected database. To rectify the stated error, you must terminate the other connections that are accessing the selected database. For this purpose, the below-provided query can be executed:
    
    
    SELECT pg_terminate_backend(pg_stat_activity.pid)
    FROM pg_stat_activity
    WHERE pg_stat_activity.datname = 'postgres'
    AND pid != pg_backend_pid();

The open connections have been terminated. Now, execute the **CREATE DATABASE** command to create the copy of the selected database:
    
    
    CREATE DATABASE postgres_copy1
    WITH TEMPLATE postgres
    OWNER postgres;

The output shows that the copy of the selected database has been created successfully.

 **Conclusion**

Postgres offers various commands to create a copy of a database, such as the **CREATE DATABASE** command, the CREATEDB command, etc. The most convenient way of copying or cloning a database is the “ **CREATE DATABASE** ” statement. To copy or clone a database, use the **CREATE DATABASE** command along with the “ **WITH TEMPLATE** ” parameter. This post presented a practical guide on how to create a copy of an already existing database in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-copy-of-a-database-in-postgresql/)

---

# PostgreSQL Conditional Expressions - Explained With Examples

> In PostgreSQL, conditional expressions are used to select one of the multiple values based on the Boolean condition.

In PostgreSQL, conditional expressions are used to select one of the multiple values based on the Boolean condition. The conditional expressions perform the comparison on the given values and return the result based on a Boolean condition. The most frequently used conditional expressions include the CASE expression, COALESCE() function, NULLIF() function, GREATEST() function, and LEAST() function.

This write-up demonstrates a detailed guide on how to work with conditional expressions in PostgreSQL. For a profound understanding, the below-listed topics will be covered in this blog with practical examples:

  * How to Use CASE Expression in Postgres?
  * What is COALESCE() and How to Use it in Postgres?
  * How to Use NULLIF() in Postgres?
  * How to Use the GREATEST() and LEAST() Functions in PostgreSQL?



 **How to Use CASE Expression in Postgres?**

 **CASE** is one of the conditional expressions that create conditional queries. It works the same way as the if-else statements do. The below-provided syntax is used to write a CASE expression:
    
    
    CASE 
        WHEN cond_1  THEN res_1
        WHEN cond_2  THEN res_2
        …
        WHEN cond_N THEN res_N
        ELSE else_result
    END

The specified conditions retrieve a Boolean true or false. If a condition specified within the “WHEN” returns true, then the result specified in the respective “THEN” block will execute.

 **Example: How Does the CASE Statement Work in Postgres?**

The below snippet illustrates the data of a sample table named “emp_data”:

Suppose we want to check the employees’ job status, i.e. probation, contract, or permanent:

\- If any of the staff members have less than one year of experience then he is on probation.  
\- If the employee has more than or equal to one year of experience but less than three years then he is on  
contract.  
\- While if the employee has more than or equal to three years of experience then he is permanent.

For this purpose, we will write a CASE expression as follows:
    
    
    SELECT emp_name,
    CASE 
    WHEN AGE(current_date, emp_joining_date) < '1 year'
    THEN 'Probation'
    WHEN AGE(current_date, emp_joining_date) >=  '1 year' AND AGE(current_date, emp_joining_date) < '3 year' 
    THEN 'Contract'
    WHEN AGE(current_date, emp_joining_date) >=  '3 year' 
    THEN 'Permanent'
    END CASE
    FROM emp_data
    ORDER BY emp_id ASC;

In the above query, the [AGE() function](<https://www.commandprompt.com/education/postgresql-age-function-with-examples/>) is used to calculate the employees’ experience:

The output shows that the CASE statement retrieves the result based on the stated conditions.

 **What is COALESCE() and How to Use it in Postgres?**

The COALESCE() function belongs to the category of conditional expressions that retrieves the first non-null value from the given values. It can accept unlimited values as arguments and return only the first non-null value:
    
    
    COALESCE (arg_1, arg_2, …, arg_n);

It is equivalent to MySQL’s NVL() function and ORACLE’s IFNULL() function. A common use case of the COALESCE() function is to replace the NULL values with some meaningful values.

 **Example: How Does the COALESCE() Function Work in Postgres?**

In the following snippet, we have passed multiple values including the null values to the COALESCE() function:
    
    
    SELECT COALESCE(NULL, NULL, 19, NULL, 12, 36);

The output shows that the COALESCE() function skips the null values and retrieves the first non-null value.

 **Note:** Read the [following](<https://www.commandprompt.com/education/postgresql-coalesce-function-with-examples/>) article for a profound understanding of Postgres’ COALESCE() function.

 **How to Use NULLIF() in Postgres?**

The NULLIF() function accepts two values as arguments:

  * It retrieves NULL if both values are equal.
  * It returns the first value if the given values are not equal.
  * If any of the given values are NONE, then the NULL value will be retrieved.
  * The values to be compared must have a compatible data type.
  * The return type of the result value depends on the data type of the first value.



The below-provided syntax is used to employ the NULLIF() function in Postgres:
    
    
    NULLIF(val_1, val_2);

Let’s understand the working of the **NULLIF()** function using the following example.

 **Example: How Does the NULLIF() Function Work in Postgres?**

A sample table named “book_info” is created with the following records:

In the following snippet, the NULLIF() function is used on a sample table named “book_info”:
    
    
    SELECT book_name, best_selling_book, NULLIF(book_name, best_selling_book)
    FROM book_info;

The output shows that the NULLIF() function returns NULL when both values are equal, else it returns the first value.

 **How to Use the GREATEST() and LEAST() Functions in Postgres?**

In Postgres, the GREATEST() and LEAST() functions are used to get the greatest and smallest value from the given data. Moreover, these functions are used to compare multiple values at once, making it easy to find the maximum or minimum value among a group of values.

The below-mentioned syntax is used to employ the GREATEST() function in Postgres:
    
    
    GREATEST(value_1, value_2, value_3, …., value_n);

The stated function will return the greatest value.

The following syntax is used to avail the functionality of the LEAST() function in Postgres:
    
    
    LEAST(value_1, value_2, value_3, …., value_n);

The stated function will return the smallest value.

 **Example: How Do the GREATEST() and LEAST() Functions Work in Postgres?**

In the following snippet, the GREATEST() function and the LEAST() function accept different dates as arguments:
    
    
    SELECT GREATEST('2020-10-01', CURRENT_DATE, '2018-12-14'), 
    LEAST('2020-10-01', CURRENT_DATE, '2018-12-14');

The output snippet shows that the GREATEST() and LEAST() function returns the greatest and smallest dates, respectively.

 **Conclusion**

In PostgreSQL, conditional expressions are used to select one of the multiple values based on the boolean condition. The most frequently used conditional expressions include the CASE statement, COALESCE() function, NULLIF() function, GREATEST() function, and LEAST() function. The CASE expression works the same as the if-else statements, COALESCE() and NULLIF() functions are used to deal with the NULL values, while the LEAST() and GREATEST() functions are used to find the smallest and greatest values from the given values.

---
[View this page online](https://www.commandprompt.com/education/postgresql-conditional-expressions-explained-with-examples/)

---

# How to Query JSON Column in Postgres

> Postgres supports a couple of native JSON operators to query the data from a JSON column. These operators include a short arrow “-&gt;” and a long arrow “-&gt;&gt;”.

PostgreSQL offers a couple of native JSON operators to query the JSON data, such as the short arrow “->” and the long arrow “->>”. The short arrow “->” queries the JSON object by “key”, while the long arrow “->>” retrieves the JSON object by “text”. Using these operators, users can get a specific node of a JSON object.

This write-up presents a detailed guide on how to query JSON data in Postgres via suitable examples.

 **How to Query JSON Data in Postgres?**

This section will show you how to query a JSON column in PostgreSQL using the JSON operators.

 **Example 1: Querying a JSON Column Using SELECT Statement**

To retrieve data from a sample table named "product_order_details", use the SELECT query:
    
    
    SELECT * FROM product_order_details
    ORDER BY o_id ASC;

The SELECT statement can be used to query the data from the JSON column:
    
    
    SELECT o_details FROM product_order_details;

The output signifies that the SELECT statement successfully retrieves the data from the JSON column.

 **Example 2: Querying a JSON Column Using Short Arrow “- >”**

In the following snippet, the “->” operator is used to get the JSON object field by “key”:
    
    
    SELECT o_details -> 'cust_name' As cusatomer_names
    FROM product_order_details;

The output proves that the “->” operator retrieves the data in JSON format.

 **Example 3: Querying a JSON Column Using Long Arrow “- >>”**

Replace the “->” operator with the “->>” operator to get the data in text format:
    
    
    SELECT o_details ->> 'cust_name' As cusatomer_names
    FROM product_order_details;

The “->>” operator retrieves the data in TEXT format.

 **Example 4: Querying a Specific Node From a JSON Object in Postgres**

Use the short arrow “->” and the long arrow “->>” combinedly to query a specific node from a JSON object. The short arrow will return a JSON object while the long arrow will retrieve a specific node from that object.

For instance, in the following snippet, we use the “->>” operator with the “->” operator to get only the “pro_name” node from the JSON object:
    
    
    SELECT o_details -> 'pro_description' ->> 'pro_name' As product_name
    FROM product_order_details;

From the output, you can observe that the selected node has been accessed from the JSON object.

 **Example 5: Querying Filtered Data From the JSON Column**

The WHERE clause is used with the JSON operators to filter the data based on a certain criterion. For instance, in the following snippet, the WHERE clause is used with the JSON operators to filter the result set of a query based on the given condition:
    
    
    SELECT o_details -> 'cust_name' As customer_name
    FROM product_order_details
    WHERE o_details -> 'pro_description' ->> 'pro_name' = 'Laptop';

The above statement will show the customer’s name who bought the “laptop”:

The output shows that the WHERE clause filtered the JSON data based on the condition specified within it.

 **Conclusion**

Postgres supports a couple of native JSON operators to query the data from a JSON column. These operators include a short arrow “->” and a long arrow “->>”. The short arrow queries the JSON object by “key”, while the long arrow retrieves the JSON object by “text”. Using these operators, users can get a specific node of a JSON object. This post illustrated various examples to show the usage of JSON operators in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-query-json-column-in-postgres/)

---

# How to Convert a Unix Timestamp to a Date or Time Value in PostgreSQL

> In PostgreSQL, the TO_TIMESTAMP() function is used to convert a Unix or Posix Timestamp to a date or time value.

The “ **UNIX TIMESTAMP** ” or “ **POSIX time** ” is a widely used DateTime representation that is used in computing. It represents the DateTime in seconds that elapsed since 00:00:00 UTC, January 1st, 1970. It is also known as the “ **Unix Epoch** ”, “ **POSIX** ”, or “ **Unix** ” time. The UNIX timestamp or POSIX time is formed as the system time of the Unix-based operating systems.

While manipulating the dates and times, a database user may encounter a situation where he needs to convert a UNIX timestamp to a date or time value. To tackle such a situation, the TO_TIMESTAMP() function is used in Postgres.

This post illustrates a practical guide on converting the Unix TIMESTAMP to a date or Time value using the built-in TO_TIMESTAMP() function.

 **Converting a Unix Timestamp to a DateTime in Postgres**

In Postgres, the TO_TIMESTAMP() function is used to convert a Unix or Posix Timestamp to a DateTime value. To achieve this, pass the Unix timestamp as an argument to the TO_TIMESTAMP() function, as a result, TO_TIMESTAMP will convert it into an equivalent timestamp.

 **Syntax**

Consider the below-given snippet to understand the basic syntax of the TO_TIMESTAMP() function:
    
    
    TO_TIMESTAMP(unix_timestamp);

Let’s comprehend this concept via practical examples.

 **Example 1: Converting UNIX Timestamp to DateTime**

In the following snippet, a specific UNIX timestamp is passed to the TO_TIMESTAMP() function. The TO_TIMESTAMP() function will convert the given Unix timestamp to the equivalent DateTime value:
    
    
    SELECT TO_TIMESTAMP(1540295216.157677);

The **TO_TIMESTAMP()** function converts the input Unix timestamp to an equivalent date, time, and timezone.

 **Example 2: Converting UNIX Timestamp to Date**

Suppose the user wants to convert the UNIX timestamp to the equivalent date only. For this purpose, the Scope Resolution “::” Operator must be used with the DATE data type, as shown in the following snippet:
    
    
    SELECT TO_TIMESTAMP(1540295216.157677) :: DATE;

The TO_TIMESTAMP() function converted the Unix timestamp to an equivalent date using the scope resolution operator.

 **Example 3: Converting UNIX Timestamp to Time**

Similarly, a Unix Timestamp can be converted into an equivalent time by specifying the TIME data type with the Scope Resolution “::” Operator:
    
    
    SELECT TO_TIMESTAMP(1540295216.157677) :: TIME;

The output proves that the TO_TIMESTAMP() function converted the Unix timestamp to an equivalent time using the scope resolution operator.

That’s all from this Postgres guide!

 **Conclusion**

In PostgreSQL, the TO_TIMESTAMP() function is used to convert a Unix or Posix Timestamp to a DateTime value. Pass the Unix timestamp as an argument to the TO_TIMESTAMP() function, as a result, the TO_TIMESTAMP() function will convert the given Unix timestamp to an equivalent date-time value. The Scope Resolution “::” Operator can be used with the TO_TIMESTAMP() function to cast the given Unix timestamp into a date or time value. This blog post considered numerous examples to demonstrate how to convert the Unix timestamp to the date time value in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-convert-a-unix-timestamp-to-a-date-or-time-value-in-postgresql/)

---

# PostgreSQL CASE Statement - Explained With Examples

> The CASE statement is one of the conditional expressions that is used to create conditional queries. Postgres supports two forms of the CASE statement: A Searc…

Conditional statements are the core concepts in any programming paradigm. These statements include if, if-else, case, etc. The **CASE** statement is one of the conditional expressions that is used to create conditional queries. PostgreSQL allows us to use the WHEN-THEN case, if-else statements, etc. with the CASE statement to create or formulate a query/expression.

This post illustrates several use cases of the **CASE** statement in PostgreSQL via practical examples.

 **What is CASE Statement and How to Write it in Postgres?**

As stated earlier, the CASE statement is a conditional expression, so it can be used with any statement or clause where an expression can be used, such as a WHERE clause, SELECT statement, etc. Postgres supports two forms of the CASE statement: A Searched CASE and a Simple CASE.

 **Basic Syntax: Searched CASE Statement**

The below snippet depicts the syntax of a searched CASE statement:
    
    
    CASE 
        WHEN cond_1  THEN res_1
        WHEN cond_2  THEN res_2
        …
        WHEN cond_n THEN res_n
        ELSE else_result
    END

Let’s comprehend the above syntax line-by-line:

\- The conditions, such as codition_1, condition_2, …, condition_n, are the boolean conditions that will retrieve either true or false.  
\- The CASE statement will execute each condition specified within the CASE statement from top-to-bottom.  
\- When a condition retrieves a “TRUE” value then the result associated with that condition will be retrieved. For instance, when “condition_1” becomes true, then “result_1” will be retrieved.  
\- Once the CASE statement encounters that an expression retrieves a TRUE value, then immediately, it will stop evaluating the remaining expressions.  
\- However, if a condition retrieves a “FALSE” value, then the CASE expression will evaluate the next condition. This process will continue until an expression retrieves true.  
\- If all the conditions/expressions retrieve “FALSE” then the result associated with the “ELSE” block will be executed.

 **Basic Syntax: Simple CASE Statement**

The below snippet illustrates the syntax of a simple CASE statement:
    
    
    CASE search_expression
        WHEN cond_1  THEN res_1
        WHEN cond_2  THEN res_2
        …
        WHEN cond_n THEN res_n
        ELSE else_result
    END

In the above syntax:

\- The “Search_expression” represents an expression to be evaluated against the expression specified in each “WHEN” case.  
\- When a condition retrieves a “TRUE” value then the result associated with that condition will be retrieved. For instance, if “condition_1” satisfies the “search_expression” then “result_1” will be retrieved.

 **Example 1: How Does the Searched CASE Statement Work in Postgres?**

In this example, we will apply the CASE statement on the “author_info” table, whose data is shown in the following snippet:
    
    
    SELECT * 
    FROM author_info
    ORDER BY author_id ASC;

In the following statement, we will use the CASE expression to check if the author is a “freshman” “junior”, “senior”, or “expert”:
    
    
    SELECT author_name, author_exp,
    CASE 
    WHEN author_exp >= 0 AND author_exp <= 1 
    THEN 'Freshman'
    WHEN author_exp > 1 AND author_exp <= 3 
    THEN 'Junior Author'
    WHEN author_exp > 3 AND author_exp <= 5 
    THEN 'Senior Author'
    WHEN author_exp > 5 THEN 'Expert'
    END CASE
    FROM author_info
    ORDER BY author_id ASC;

The output shows the usage of the CASE statement in PostgreSQL.

 **Example 2: How Does the Simple CASE Statement Work in Postgres?**

The following snippet demonstrates the working of the simple CASE statement:
    
    
    SELECT author_name, author_exp,
    CASE gender
    WHEN 'M' THEN 'Male'
    WHEN 'F' THEN 'Female'
    END CASE
    FROM author_info
    ORDER BY author_id ASC;

In the above snippet, the CASE statement is used to add the gender description to the output:

This is how the **Simple CASE Statement** works in PostgreSQL.

 **Example 3: How to Use the CASE Statement With Aggregate Functions in Postgres?**

Postgres allows us to use the simple and searched CASE statements with the aggregate functions. In the below-provided query, we will use the COUNT() function to count the number of “junior”, and “senior” authors:
    
    
    SELECT
    COUNT(CASE 
    WHEN author_exp >= 0 AND author_exp <= 4 
    THEN 'Junior Author'
    END) As Junior_authors,
    COUNT(CASE 
    WHEN author_exp >= 5 
    THEN 'Senior Author'
    END) As Senior_authors
    FROM author_info;

This way, you can use any aggregate function with the CASE statement to achieve different functionalities.

 **Conclusion**

The **CASE** statement is one of the conditional expressions that is used to create conditional queries. Postgres supports two forms of the CASE statement: A Searched CASE and a simple CASE. We can use the WHEN-THEN case with the CASE statement to create or formulate a query/expression. It can be used with any statement or clause where an expression can be used, such as with a WHERE clause, with the SELECT statement, etc. This post has presented various examples to explain the usage of the case statement in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-case-statement-explained-with-examples/)

---

# PostgreSQL Not equal to (!=) Operator

> The NOT EQUAL operator is one of the comparison operators that check if the input values are equal or not. It is symbolized as “!=” or “&lt;&gt;”.

In Postgres, an operator is nothing but a reserved keyword, character, or symbol that offers unique functionality. In Postgres, there are various categories of operators, such as comparison operators, logical operators, arithmetic operators, etc. All these operators are used for different purposes.

The NOT EQUAL operator, symbolized as “!=” or “<>”, is one of the comparison operators that check if the input values are equal or not.

This post demonstrates what is a “NOT EQUAL” operator and how it works in Postgres. For a profound understanding, the content of this Postgres blog is classified as follows:

 **How to Use the Postgres NOT EQUAL Operator:**  
\- With Integers  
\- With Floating Points  
\- With Text Data  
\- On Postgres Table’s Data

 **How to Use the NOT EQUAL Operator in Postgres?**

Postgres Not Equal to (!=) Operator compares the left operand with the right operand and retrieves true if the given operands are not equal, and false if the operand values are equal. For instance, the below syntax shows the basic syntax of the NOT EQUAL operator:
    
    
    SELECT operand_1 != operand_2;

The operands must be valid (i.e., both operands must have implicitly convertible data types).

In Postgres, the comparison operators are most often used in the WHERE Clause of any statement. For instance, the below syntax shows the syntax of the NOT EQUAL “!=” operator with the WHERE clause:
    
    
    SELECT column_list
    FROM table_name
    WHERE col_name != value;

Alternatively, the “<>” operator can be employed to commit the same functionality.

 **Example 1: Using Not Equal Operator “!=” With Integers**

The following example considers a simple expression to show the usage of the Postgres **NOT EQUAL** “!=” operator:
    
    
    SELECT 200 + 300 != 400 As result;

In the above snippet, the left operand is not equal to the right one; so, it retrieves a boolean “true”.

 **Note:** users may also use the “<>” operator in place of the “!=” operator.

 **Example 2: Using Not Equal Operator “!=” With Floating Points**

The below expression utilizes the Postgres **NOT EQUAL** “<>” operator with the floating point values:
    
    
    SELECT 200.25 + 200.75 <> 401.0 As result;

In the stated expression, the left operand is equal to the right one; so, it returns “ **false** ”.

 **Example 3: Using Not Equal Operator “!=” With Text Data in Postgres**

In the following snippet, the “!=” operator performs the string comparison:
    
    
    SELECT 'Hello' != 'Hello' As result;

This operator performs a case-sensitive comparison on the given strings. For instance, in the below snippet, we utilize the “!=” operator to compare a “lowercase” string with “uppercase”:
    
    
    SELECT 'hello' != 'HELLO' As result;

The output signifies that the “!=” operator performs a case-sensitive comparison.

 **Example 4: Using Not Equal Operator “!=” on Postgres Table’s Data**

A sample table named “std_data” has already been created with the following records:
    
    
    SELECT * FROM std_data;

The following query will fetch all those students whose age is not equal to “20”:
    
    
    SELECT std_name, std_age
    FROM std_data
    WHERE std_age != 20;

The “!=” operator retrieves all the students except those who are 20 years old.

 **Conclusion**

The NOT EQUAL operator is one of the comparison operators that check if the input values are equal or not. It is symbolized as “!=” or “<>”. Postgres “Not Equal to” Operator compares the left operand with the right operand and retrieves true if the given operands are not equal, and false if the operand values are equal. This post presented numerous examples to explain the usage of the not equal to operator.

---
[View this page online](https://www.commandprompt.com/education/postgresql-not-equal-to-operator/)

---

# How to Convert Timestamp to Date in PostgreSQL

> Postgres offers various ways to convert a TIMESTAMP to a DATE, such as TO_CHAR() function, CAST operator, EXTRACT function, etc.

PostgreSQL is a free and open-source advanced database management system that offers numerous built-in date, and time functions. These functions allow us to perform different tasks on the DateTime values efficiently. In database management systems as well as in programming paradigms converting a timestamp to date is a common task.

Converting a timestamp to a date assists us in data manipulation and analysis. Postgres offers various ways to convert a TIMESTAMP to a DATE, such as **TO_CHAR()** function, **CAST** operator, **EXTRACT** function, etc.

This blog illustrates the following methods to convert a timestamp to date in Postgres:

\- **Method 1:** Using Postgres DATE() Function  
\- **Method 2:** Using Postgres CAST Operator  
\- **Method 3:** Using Postgres TO_CHAR() Function  
\- **Method 4:** Using Scope Resolution “::” Operator  
\- **Method 5:** Using Postgres EXTRACT() Function  
\- **Method 6:** Using Postgres DATE_PART() Function

Let’s start with the DATE() function.

 **Method 1: Using Postgres DATE() Function**

The built-in DATE() function is one of the most convenient ways of converting a timestamp to a date. For instance, the following code snippet demonstrates how to convert the current timestamp to date using the DATE() function:
    
    
    SELECT CURRENT_TIMESTAMP, DATE(CURRENT_TIMESTAMP);

\- The CURRENT_TIMESTAMP function returns today’s DateTime(timestamp) With timezone.  
\- Passing the CURRENT_TIMESTAMP to the DATE() function will convert the current timestamp to the current date.  
\- The below snippet shows the “current timestamp” and the “current timestamp converted to date”:

 **Method 2: Using Postgres CAST Operator**

The CAST operator in Postgres allows us to convert one data type to another. Similarly, a timestamp can be converted to a date using the CAST operator, as shown in the following code snippet:
    
    
    SELECT CAST('2023-01-09 20:41:12.791354-08' AS DATE);

In the above query:

\- A timestamp is passed as an argument to the CAST operator.  
\- “AS DATE” represents that the given timestamp should be converted into a date.

 **Method 3: Using Postgres TO_CHAR() Function**

The TO_CHAR() function assists us in converting the given timestamp into a date using a specific format. Here is an example:
    
    
    SELECT TO_CHAR(NOW(), 'YYYY-MM-DD') As Current_Date;

\- The NOW() function is passed as an argument to the TO_CHAR() function.  
\- The NOW() function returns today’s DateTime.  
\- The “YYYY-MM-DD” format is passed as an argument to the TO_CHAR() function.  
\- The TO_CHAR() function will convert the given timestamp to the specified date format.

 **Method 4: Using Scope Resolution “::” Operator**

Alternatively, the scope resolution operator can be used to convert a specific timestamp into a date. For this purpose, specify the DATE data type along with the scope resolution operator, as shown in the following snippet:
    
    
    SELECT '2023-01-09 20:41:12.791354-08' :: DATE;

The given timestamp has been successfully converted to a date using the scope resolution operator.

 **Method 5: Using Postgres EXTRACT() Function**

Postgres offers another DateTime function named EXTRACT() that enables us to extract only a specific field from the given timestamp. In the following snippet, the “month” is passed as the first argument to the EXTRACT() function. Consequently, the EXTRACT() function will extract the month from the given timestamp:
    
    
    SELECT EXTRACT(MONTH FROM CURRENT_TIMESTAMP) as current_month;

The output shows that it’s the second month of the year, i.e. February.

 **Method 6: Using Postgres DATE_PART() Function**

The DATE_PART() function offers the same functionality as the EXTRACT() function. The following snippet will provide you with more clarity regarding the DATE_PART() function:
    
    
    SELECT DATE_PART(YEAR, CURRENT_TIMESTAMP) as current_year;

The year from the current timestamp has been extracted using the DATE_PART() function.

 **Conclusion**

Postgres offers various ways to convert a TIMESTAMP to a DATE, such as **TO_CHAR()** function, **CAST** operator, **EXTRACT** function, etc. The DATE() function, scope resolution operator, cast operator, and TO_CHAR() functions are used to convert a timestamp to a date. While the DATE_PART() and EXTRACT() functions are used to convert a timestamp to a specific date field, such as a year, month, day, etc. This blog presented a detailed guide on converting the timestamp to a date in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-convert-timestamp-to-date-in-postgresql/)

---

# How to Get the Unix Timestamp in PostgreSQL

> To get the Unix Timestamp in PostgreSQL, the EXTRACT() and DATE_PART() functions are used with the EPOCH argument.

The “ **UNIX TIMESTAMP** ” also known as the “ **Unix Epoch** ” or “ **POSIX** ” represents a DateTime in seconds, elapsed since 00:00:00 UTC, January 1, 1970. Database users may need to retrieve the UNIX timestamp when manipulating the date and time values. In such situations, the EXTRACT() and DATE_PART() functions can be used with the EPOCH argument.

This post illustrates a practical guide to getting the Unix TIMESTAMP in Postgres via the EXTRACT() and DATE_PART() functions.

 **How to Get the Unix Timestamp in Postgres?**

Pass the EPOCH argument to the **EXTRACT()** function or the **DATE_PART()** function to get a timestamp in Unix format.

The below syntax explains how to get a Unix timestamp using the EXTRACT() function:
    
    
    EXTRACT(EPOCH FROM 'timestamp');

The below snippet demonstrates how to get a Unix timestamp using the DATE_PART() function:
    
    
    DATE_PART('EPOCH', 'timestamp');

Let’s put these concepts into practice!

 **Example 1: How to Get Unix Timestamp From Current Timestamp**

In Postgres, the CURRENT_TIMESTAMP function returns the current DateTime. However, passing EPOCH and the CURRENT_TIMESTAMP as arguments to the EXTRACT() function will retrieve the current DateTime as Unix Timestamp:
    
    
    SELECT CURRENT_TIMESTAMP, 
    EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) As Unix_timestamp;

Alternatively, you can use the DATE_PART() function to get the Unix Timestamp from the current timestamp:
    
    
    SELECT CURRENT_TIMESTAMP, 
    DATE_PART('EPOCH', CURRENT_TIMESTAMP) As Unix_timestamp;

 **Example 2: How to Get Unix Timestamp From a Specific Timestamp**

The EXTRACT() function and the DATE_PART() function assist us in getting the Unix timestamp from a specific timestamp:
    
    
    SELECT DATE_PART('EPOCH', TIMESTAMP '2020-12-11 02:12:16.906072'),
    EXTRACT('EPOCH' FROM TIMESTAMP '2020-12-11 02:12:16.906072');

This way, you can get a Unix timestamp from a specific timestamp using the EXTRACT() and DATE_PART() functions.

 **Example 3: How to Get Unix Timestamp From a Specific TIMESTAMPTZ**

Similarly, you can use the EXTRACT() or DATE_PART() functions to get the Unix timestamp from a “timestamp with a time zone”:
    
    
    SELECT DATE_PART('EPOCH', TIMESTAMP '2020-12-11 02:12:16.906072-08'),
    EXTRACT('EPOCH' FROM TIMESTAMP '2020-12-11 02:12:16.906072-08');

 **Example 4: How to Get Unix Timestamp From Current Date**

To get a Unix timestamp from the current date or a specific date, the EXTRACT() or DATE_PART() functions can be used as follows:
    
    
    SELECT DATE_PART('EPOCH', CURRENT_DATE),
    EXTRACT('EPOCH' FROM DATE '2020-12-11');

The Unix timestamp is extracted from the current date using the DATE_PART() function. While the Unix timestamp is extracted from a specific date using the EXTRACT() function.

 **Example 5: How to Get Unix Timestamp From an Interval**

In the following example, the DATE_PART() and EXTRACT() functions are used to get the Unix timestamp from a specific interval:
    
    
    SELECT DATE_PART('EPOCH', INTERVAL '1 Month 2 Days'),
    EXTRACT('EPOCH' FROM INTERVAL '1 Month 2 Days');

That’s all from this post.

 **Conclusion**

To get the Unix Timestamp in PostgreSQL, the EXTRACT() and DATE_PART() functions are used with the EPOCH argument. Using these functions, a user can get a Unix timestamp from a date, interval, or timestamp. To do that, pass the EPOCH as a first argument to the EXTRACT() function or the DATE_PART() function and a date, interval, or timestamp as the second argument to get a timestamp in Unix format. This post explained various methods to return a Unix timestamp in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-unix-timestamp-in-postgresql/)

---

# How to Query Arrays in PostgreSQL

> To query the ARRAY data in Postgres, the SELECT statement is used. Postgres allows us to query the data of an entire array or a specific array index.

Arrays are essential data structures in any programming paradigm. Arrays allow us to store the data in contiguous memory locations. PostgreSQL offers an ARRAY data type that creates an array of any built-in or user-defined data types. However, arrays store data of the same data type. For instance, a string array contains text data only, an integer array contains integers only, etc.

To query the ARRAY data in Postgres, the SELECT statement is used in Postgres. You can use different operators to query the filtered data from an array based on specific conditions.

This post explains how to query an array’s data in Postgres using various practical examples.

 **How to Query an Array’s Data in Postgres?**

We have created a sample table named “staff_data” whose details are shown in the following snippet:
    
    
    SELECT * FROM staff_info;

Postgres allows us to query the data of an entire array or a specific index of an array.

 **Example 1: Querying Entire Array**

To query an entire array, the SELECT statement can be used. For instance, in the following snippet, the SELECT statement is used to query the “st_email” array:
    
    
    SELECT st_name, st_email
    FROM staff_info;

 **Example 2: Querying Specific Index of an Array**

Specify the index number of the array in the square bracket to query only a specific index of an array:
    
    
    SELECT st_name, st_email[1]
    FROM staff_info;

The above-given query will query/fetch only the first element of the selected array:

 **Example 3: Querying Specific Records**

The WHERE clause can be used to fetch the array’s data based on a specific condition:
    
    
    SELECT st_name
    FROM staff_info
    WHERE st_email[1] = 'mike@gmail.com';

The above statement will fetch the employee name whose email id at index 1 is 'mike@gmail.com':

The output signifies that the “SELECT” statement queries the filtered data only.

 **Example 4: Querying Array’s Data Using Built-in Operators**

You can also use built-in operators like ANY, SOME, etc. to compare the array elements with some specific value. For instance, in the following snippet, we utilize the ANY operator to check if an employee has an email “john123@gmail.com”:
    
    
    SELECT st_name
    FROM staff_info
    WHERE 'john123@gmail.com' = ANY(st_email);

The output shows that an employee named “John” has an email address “john123@gmail.com”.

 **Example 5: Expanding the Array’s Values in Postgres**

The built-in UNNEST() function is used in Postgres to expand the selected array to multiple records. For instance, the following query will expand the “st_email” array to multiple rows:
    
    
    SELECT st_id, st_name,
    UNNEST(st_email)
    FROM staff_info;

The UNNEST() function expanded the selected array into multiple rows.

 **Conclusion**

To query the ARRAY data in Postgres, the SELECT statement is used. Postgres allows us to query the data of an entire array or a specific index of an array. Moreover, different built-in operators can be used to query the data from an array based on specific conditions. The built-in UNNEST() function is used in Postgres to expand the selected array to multiple records. This blog explained how to query array data using numerous examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-query-arrays-in-postgresql/)

---

# How to Query Date and Time in PostgreSQL

> In PostgreSQL, different built-in functions are used along with the SELECT statement to query date and time. This blog post explained how to query date and tim…

PostgreSQL facilitates us with numerous date and time functions, such as CURRENT_DATE, NOW(), EXTRACT(), etc. These functions allow us to work with the date and time efficiently. In PostgreSQL, different built-in functions are used along with the SELECT statement to query date and time values.

This write-up presents a detailed guide on how to query date and time in Postgres. The below-provided topics will be studied in this blog with appropriate examples:

  * How to Query Current DateTime in Postgres?
  * How to Find Age/Interval Between Two Timestamps in Postgres?
  * How to Query Data Between Two Timestamps Using the BETWEEN Operator?
  * How to Get/Extract the Day of the Week From a Specific Timestamp?
  * How to Get/Extract a Specific Field From the Given Timestamp?
  * How to Convert a Specific Timestamp to a UNIX Timestamp?



 **How to Query Current DateTime in Postgres?**

PostgreSQL facilitates us with numerous date and time functions, such as CURRENT_DATE, NOW(), EXTRACT(), etc. These functions allow us to work with the date and time efficiently. To query the current date or time, the CURRENT_DATE, CURRENT_TIME, NOW(), TIMEOFDAY(), CURRENT_TIMESTAMP, and LOCALTIMESTAMP functions are used in Postgres.

 **Example 1: CURRENT_DATE Function**

Use the CURRENT_DATE function to query the current date only:
    
    
    SELECT CURRENT_DATE;

 **Example 2: CURRENT_TIME Function**

Use the CURRENT_TIME function to query the current time only:
    
    
    SELECT CURRENT_TIME;

 **Example 3: NOW() Function**

Use the NOW() function to query the current date, time, and timezone:
    
    
    SELECT NOW();

 **Example 4: TIMEOFDAY() Function**

Use the TIMEOFDAY() function to query the current date, time, and time zone in text format:
    
    
    SELECT TIMEOFDAY();

 **Example 5: CURRENT_TIMESTAMP Function**

Use the CURRENT_TIMESTAMP to query the current timestamp with the time zone.
    
    
    SELECT CURRENT_TIMESTAMP;

 **Example 6: LOCALTIMESTAMP Function**

Use the LOCALTIMESTAMP to query the current timestamp without the time zone.
    
    
    SELECT LOCALTIMESTAMP;

This way, you can use these built-in date time functions to query the current date, current time, or both current date and time in PostgreSQL.

 **How to Find Age/Interval Between Two Timestamps in Postgres?**

In Postgres, AGE() is a built-in function that is used to calculate the ages/intervals. In the following example, we will use the AGE() function to calculate the employee’s total experience in the company. Firstly, let’s describe the table’s data:
    
    
    SELECT * FROM emp_data;

Let’s learn how to query data between two timestamps using the AGE() function:
    
    
    SELECT emp_name, emp_joining_date, 
    AGE(CURRENT_DATE, emp_joining_date) AS Experience
    FROM emp_data
    ORDER BY emp_id ASC;

The output shows that the AGE() function retrieves an interval that shows the difference between the current date and the date specified in the “emp_joining_date” column.

 **How to Query Data Between Two Timestamps Using the BETWEEN Operator?**

Suppose we want to find those employees who joined a company between “ **2020-01-01** ” and “ **2023-01-01** ”. For this purpose, use the **BETWEEN** operator as follows:
    
    
    SELECT emp_name, emp_joining_date
    FROM emp_data
    WHERE emp_joining_date BETWEEN '2020-01-01' AND '2023-01-01';

The BETWEEN operator queries the employees’ data between the specified dates only.

 **How to Get/Extract the Day of the Week From a Specific Timestamp?**

In Postgres, the TO_CHAR() function is used with the “DAY” argument to get the day of the week as a String. While the DATE_PART() function is used with the “DOW” argument to fetch the day of the week as an integer/numeric value.

For instance, in the following example, we pass CURRENT_DATE and DAY as arguments to the TO_CHAR() function. As a result, the TO_CHAR() will retrieve the current day of the week:
    
    
    SELECT TO_CHAR(CURRENT_DATE, 'DAY') AS current_day;

Now, pass the CURRENT_DATE function and the ‘DOW’ as arguments to the DATE_PART() function to fetch the week’s current day as an integer/number:
    
    
    SELECT DATE_PART(CURRENT_DATE, 'DOW') AS current_day;

The output states that it's the third day of the week.

 **How to Get/Extract a Specific Field From the Given Timestamp?**

Using the DATE_PART() function, you can extract any part from a timestamp, such as a day, month, year, hour, minute, etc. For this purpose, you must pass a valid format as an argument to the DATE_PART() function.

For instance, in the following code snippet, the DATE_PART() function is used to extract the year from the current timestamp:
    
    
    SELECT DATE_PART('YEAR', CURRENT_TIMESTAMP) AS current_year;

Similarly, you can extract the month, day, day of the week, hours, minutes, etc. from a DateTime field using the DATE_PART() or EXTRACT() function.

 **How to Convert a Specific Timestamp to a UNIX DateTime?**

Pass the “EPOCH” as an argument to the DATE_PART() function to convert the given timestamp into a UNIX timestamp. The DATE_PART() will retrieve the converted UNIX timestamp in seconds:
    
    
    SELECT DATE_PART('EPOCH', NOW()) AS converted_timestamp;

That’s all from this Postgres guide!

 **Conclusion**

In PostgreSQL, different built-in functions are used along with the SELECT statement to query date and time. For instance, to query the current date or time, the CURRENT_DATE, CURRENT_TIME, NOW(), TIMEOFDAY(), CURRENT_TIMESTAMP, and LOCALTIMESTAMP functions are used, to find the interval between two dates/timestamps the AGE() function is used, to extract any part from a timestamp, such as a day, month, year, hour, minute, etc., the DATE_PART() function is used, and so on. This post explained how to query date and time in Postgres using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-query-date-and-time-in-postgresql/)

---

# PostgreSQL DELETE USING Statement - Drop Duplicate Rows

> In Postgres, the COUNT() function finds duplicate records. While the “DELETE USING” statement drops the duplicates.

Finding and deleting duplicate records is a frequently performed task while working with databases. To find duplicates, an aggregate function named **COUNT()** is used in Postgres. At the same time, Postgres offers various methods for deleting duplicate records. One such method is the “ **DELETE USING** ” statement.

This post demonstrates removing duplicate records in Postgres using the “ **DELETE USING** ” statement.

 **How to Drop Duplicates Using Postgres DELETE USING Statement?**

Let’s learn how to find and remove duplicates in Postgres:

 **Finding Duplicates**

The following syntax shows how to find duplicates in Postgres via the **COUNT()** function:
    
    
    SELECT col_name, COUNT(col_name)
    FROM tab_name
    GROUP BY col_name
    HAVING COUNT(col_name)> 1;

The above query will count if the selected column has some duplicates or not.

 **Removing Duplicates**

To remove duplicates from a Postgres table, you need to use the following syntax:
    
    
    DELETE FROM tab_name 
    row_1 USING tab_name row_2 
    WHERE condition;

Let’s put these concepts into practice for a profound understanding.

 **Sample Table**

Execute the below-provided statement to create a sample table named “product_details”:
    
    
    CREATE TABLE product_details(
    pro_id SERIAL PRIMARY KEY,
    pro_name TEXT NOT NULL
    );

Now use the INSERT INTO statement to insert the product’s info into the product_details table:
    
    
    INSERT INTO product_details(pro_name)
    VALUES('Laptops'),
    ('Chargers'),
    ('Tablets'),
    ('Personal Computers'),
    ('Laptops'),
    ('Chargers'),
    ('Tablets'),
    ('Random Access Memory (RAM)'),
    ('Hard drive'),
    ('Laptops'),
    ('Chargers'),
    ('Tablets'),
    ('Laptops'),
    ('Chargers');

Now use the “SELECT *” command to query/fetch the data from the “product_details” table:
    
    
    SELECT * FROM product_details;

The output snippet proves that the “product_details” table has various duplicates.

 **Example 1: Finding Duplicates Via the COUNT() Function**

This example will teach you how to find the duplicates in Postgres via the **COUNT()** function:
    
    
    SELECT pro_name, COUNT(pro_name)
    FROM product_details
    GROUP BY pro_name
    HAVING COUNT(pro_name)> 1;

The count function retrieves all duplicate records grouped by product names.

 **Example 2: Removing Duplicates Via the DELETE USING Statement**

To remove the duplicates from a specific table, execute the DELETE USING statement as follows:
    
    
    DELETE FROM product_details pd
    USING product_details pd_new
    WHERE pd.pro_id < pd_new.pro_id
    AND pd.pro_name = pd_new.pro_name;

Let’s comprehend the above query stepwise:

\- Specify the targeted table in the DELETE statement, for instance, “product_details”.  
\- The USING clause is used to join the product_details table with itself.  
\- Next, the WHERE clause is used to check if two different rows(pd.pro_id <pd_new.pro_id) have the same product name.

This way, all those records will be deleted from the selected table that satisfies the criteria specified within the WHERE clause:

The above snippet states that eight records have been deleted from the product_details table. Let’s verify whether the product_details table still has duplicates or not:
    
    
    SELECT * FROM product_details;

The output demonstrates that the “product_details” table has unique records only.

 **Conclusion**

In PostgreSQL, an aggregate function named **COUNT()** is used to find duplicate records. While to drop the duplicate rows, the “ **DELETE USING** ” statement is used in PostgreSQL. The **COUNT()** function checks if the selected column has some duplicates or not. Once the duplicates are found, after that, you can use the DELETE USING statement to delete those records. This post explained how to find and remove duplicates in Postgres using practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/postgresql-delete-using-statement-drop-duplicate-rows/)

---

# Configuring Binary Replication with pgBackRest

> PostgreSQL has two forms of native replication: logical replication and binary replication. Logical replication offers tuple-by-tuple changes streamed from a p…

## Introduction

PostgreSQL has two forms of native replication: logical replication and binary replication. **Logical replication** offers tuple-by-tuple changes streamed from a primary server to a secondary server. **Binary replication** , also known as physical replication, sends changes at a disk block level.

Binary replication allows for backing up an entire database and recovering it to a specific point in time, called _point-in-time-recovery_ (PITR). PostgreSQL accomplishes this by using a [_write-ahead log_ (WAL)](<https://www.commandprompt.com/blog/the_write_ahead_log/>), which details the transactions that occur. This tutorial provides a guide for implementing binary replication between a primary and secondary server.

## Assumptions

This tutorial assumes that you are operating on a Linux OS, and the examples shown are specific to Ubuntu 22.04 LTS. It is also assumed that PostgreSQL 14 is already installed on your server, and data in the database already exists. The user performing commands should have sudo access to the postgres user. You will need ssh access to your machines for this tutorial, if you are unaware of how to enable that, please see this tutorial.

## Variables

The primary server has an example IP address of 198.168.0.1, and the secondary server has an IP address of 198.168.0.2. The user, database, table, target directories/files, etc. are examples and will need modification specific to you and your system. These are highlighted green in the code examples.

____________________________________________________________________________

## Primary Server Procedure

### Step 1: PgBackRest Installation and Configuration

PgBackRest is a reliable backup and restore option for PostgreSQL. Since we are using pgBackRest to backup the data in our database, we’re installing it on both the primary and secondary servers. With pgBackRest on both machines, we can call it from the secondary, and it will execute on the primary.

Let us begin by installing it on our primary server. We update the repositories on the servers with:

> sudo apt update

And now we install pgBackRest with:

> sudo apt -y install pgbackrest

Now that we have pgBackRest installed, we need to configure it for binary replication. It is good practice when altering an important file to first back it up. We shall do so with:

> sudo cp /etc/pgbackrest.conf /etc/pbackrest.conf.backup

Now we can edit the configuration without a care in the world (except probably that it works). Let’s edit the configuration file with:

> sudo nano /etc/pgbackrest.conf

The following are settings we will alter for this tutorial:

The _[global]_ section in the configuration file defines the location of backups and logging settings.

  *  _repo1-path_ defines the path to the location where backups are stored.
  *  _repo1-retention-full_ defines how many full backups are kept (2).
  *  _log-level-console_ set to info will display detailed information of processes to the console.
  *  _log-level-file_ set to _debug_ allows enough information to be sent to the log file for us to troubleshoot if necessary.



The _[tutorial]_ section is the name of the stanza that we are creating.

  *  _pg1-path_ defines the path to the data being backed up.



More detailed options can be found [here](<https://pgbackrest.org/configuration.html#section-backup/option-backup-standby>).

Let’s edit the configuration to set the desired parameters:

> [global]  
> repo1-path=/var/lib/pgbackrest  
> repo1-retention-full=2  
> log-level-console=info

> log-level-file=debug

> [tutorial]  
> pg1-path=/var/lib/postgresql/14/main

### Step 2: Create Replication Role

To securely access the data and replicate it, it is important for us to create a role specifically for that purpose.

Let’s launch _psql_ with:

> sudo -iu postgres psql

Create the replication role, _replicator_ :

> CREATE ROLE replicator WITH REPLICATION LOGIN;

Next, we want to securely set our password. You can set the password while establishing the role, but we do it in a separate command to ensure our password is not displayed on-screen and not recorded in terminal logs. We do so by using the password meta-command and telling psql which role we want to change:

> \password replicator

This prompts you to enter and repeat your desired password. Now we have set up our replication role and pgBackRest. Next, it is time to configure PostgreSQL.

### Step 3: Primary Server PostgreSQL Configuration

We need to configure postgresql.conf and pg_hba.conf to enable binary replication. Configuration files are found in different places on different systems, but we can locate our configuration file with:

> sudo -iu postgres psql -U postgres -c 'SHOW config_file'

In this case, the return was:

> config_file  
>  \-----------------------------------------  
>  /etc/postgresql/14/main/postgresql.conf  
> (1 row)

So, let’s edit the contents with your favorite text editor:

> sudo nano /etc/postgresql/14/main/postgresql.conf

The comment hash (#) must be removed from the beginning of each line we want to enable so the system will recognize it as an active setting. Find the line with _listen_addresses_ and alter the text within quotes to be the IP address of the primary server, or a wildcard (*) to indicate that PostgreSQL will listen to all addresses it has access to. It will look something like this:

> listen_addresses = '198.168.0.1'

or

> listen_addresses = '*'

To keep the connection secure, we want the encryption on passwords set to _scram_sha_256_. Since _scram_sha_256_ is the default setting for PostgreSQL 14, we don’t need to change anything in the file. But, if you are working with PostgreSQL 13 or older, we can do so by uncommenting the _password_encryption_ line and adding _scram_sha_256_ to look like this:

> password_encryption = scram_sha_256

 **NOTE:** If you choose to use a different encryption method, be sure to include the correct encryption method in the pg_hba.conf file.

The Write-Ahead Log (WAL) is the log of changes made to a database cluster to be used as part of the database recovery process or, as in this case, to replay changes in the database for replication. The _wal_level_ setting determines how much information is written into the WAL file. We only need enough information in the WAL file to perform binary replication, and this is set to _replica_ by default. If you are working with a version older than PostgreSQL 10, this will not be default, and we should set _wal_level_ to _replica_ , like so:

> wal_level = replica

The _max_wal_senders_ setting determines the maximum number of concurrent connections from secondary servers or streaming base backup clients. The default setting for _max_wal_senders_ is 10, which is an appropriate setting for a production environment. However, since we will only have one physical replica connected, we can just set this to 3:

> max_wal_senders = 3

To archive any data, we must set the _archive_mode_ to _on_. Doing so allows completed WAL segments to be sent to archive storage:

> archive_mode = on

With archiving enabled, we now need to tell PostgreSQL where we want to send the WAL segments. We do so with the _archive_command_ setting, which tells the local shell to archive a completed WAL file segment. With this command, we are telling pgBackRest to point to the configuration settings of the _tutorial_ stanza and push the archive to the designated path, _%p (repo1-path)_ :

> archive_command = 'pgbackrest --stanza=tutorial archive-push %p'

Now that we have made the changes to this configuration file, we will save and exit the postgresql.conf file.

### Step 4: Primary Server Host-Based Authentication Configuration

Next up is configuring the host-based authentication file, pg_hba.conf. This file should be located in the same directory as postgresql.conf, so we open it to edit with:

> sudo nano /etc/postgresql/14/main/pg_hba.conf

The pg_hba.conf file has 5 fields that need to be filled out to authenticate a client to use PostgreSQL: the host type (TYPE), database name (DATABASE), user name (USER), IP address (ADDRESS), and encryption method (METHOD).

  * Set TYPE to _host_ to match connection attempts using TCP/IP.
  * Enter _replication_ as the record for DATABASE to have access to databases set up for replication.
  * Enter _replicator_ under USER because the role we created will need access from the secondary.
  * Under ADDRESS, enter the IP address of the secondary server that will be accessing the database.
  * Under METHOD, enter the password encryption method we are using, which is _scram-sha-256_.



Add the following line to pg_hba.conf:

> # TYPE DATABASE USER ADDRESS METHOD  
>   
>  host replication replicator 198.168.0.2/32 scram-sha-256

Now our PostgreSQL configuration is complete, but we still need to enable the changes.

### Step 5: Restart PostgreSQL

To enable the configuration changes made to postgresql.conf and pg_hba.conf, we need to restart PostgreSQL. The systemd service unit name varies depending on the OS and software package source you are using. In Debian (Ubuntu) and most Linux systems, we can do so with the _systemctl_ command:

> sudo systemctl restart postgresql

The green highlighted portion is likely to vary between systems and versions of PostgreSQL. For example, it is possible that you need to use a command like this:

> sudo systemctl restart postgresql-14

Or this:

> sudo systemctl restart postgresql@14-main

In these examples, you replace the 14 with the version you are working with.

Secondary Server Procedure

### Step 6: Edit Secondary pgBackRest Configuration

Let’s begin by installing pgBackRest on the secondary. First, we update the repositories:

> sudo apt update

And now we install pgBackRest with:

> sudo apt -y install pgbackrest

Now let’s configure pgBackRest on the secondary server. It is very similar to how we have pgBackRest configured on the primary, but we are adding extra settings to allow binary replication from the primary. Under the _[global]_ section we include:

  * The _repo1-host_ , which is the IP address to the primary server (where the repository is located).
  * We will also include _repo1-host-user_ , which we set to _postgres_ as the OS user who owns the repository. By default, this is the pgbackrest user on the primary server, which is not configured.
  * We also include _delta_ set to _y_ , which automatically uses the delta restore option.



Additionally, we include a few _recovery-option_ settings in the _[tutorial]_ stanza section.

  * The _primary_conninfo_ setting details the connection information to the primary server, and we include the host IP address and the PostgreSQL user responsible for the replication.
  * The _recovery_target_timeline_ set to _latest_ tells PostgreSQL to use the latest WAL file for recovery.



Let’s configure /etc/pgbackrest.conf on the secondary to look like this:

> [global]  
> repo1-path=/var/lib/pgbackrest

> repo1-host=198.168.0.1

> repo1-host-user=postgres

> repo1-retention-full=2  
> log-level-console=info  
> log-level-file=debug  
> delta=y  
>   
> [tutorial]  
> pg1-path=/var/lib/postgresql/14/main  
> recovery-option=primary_conninfo=host=198.168.0.1 user=replicator  
> recovery-option=recovery_target_timeline=latest

## Data Transfer

### Step 7: Backup on the Primary

We are ready to create the stanza on the primary server.

The _\--stanza_ option is the name of our stanza, which should match the section we added to pgbackrest.conf. The _stanza-create_ command creates the stanza:

> pgbackrest --stanza=tutorial stanza-create

Now let’s confirm we have information created with the previous command using the _check_ command:

> pgbackrest --stanza=tutorial check

And finally, we arrive at our backup. We use the _backup_ command with the _\--type_ option set to _full_ , indicating that we want a full backup:

> pgbackrest --stanza=tutorial --type=full backup

Now we have a full backup of our database!

### Step 8: Restore on the Secondary

Let’s restore the backup of our primary database on the secondary.

First things first, we need to stop the cluster from running before restoring. The simplest way to do this is to stop PostgreSQL on the primary with:

> sudo systemctl stop postgresql

Now that the cluster is not running processes, we use the restore command on the secondary to recreate the data from the primary:

> sudo -u postgres pgbackrest --stanza=tutorial --type=standby restore

Let’s start PostgreSQL to enable the changes in a functioning secondary database.

> sudo systemctl start postgresql

## Follow-Up Procedures

### Step 9: Confirm Successful Replication

Let’s confirm that the replication was successful.

Enter the _psql_ prompt and run the following query:

> sudo -iu postgres psql

> SELECT * FROM select_table;

If the data on the secondary matches the data from the primary, the replication has been successful. Let’s confirm that the data is streaming properly.

Return to primary and insert some data into our _select_table_ (substitute data to match your schema):

> INSERT INTO select_table VALUES ('some data', 101);

Make sure the data was inserted properly (substitute data to match what you inserted):

> SELECT * FROM select_table WHERE select_column='some data';

For the changes to be reflected on the secondary, we must first backup the data from the primary. Let’s exit _psql_ , and do so as before:

> exit

> sudo -u postgres pgbackrest --stanza=tutorial --type=full backup

Now, let’s return to the _psql_ prompt on the secondary to make sure the changes have been made:

> sudo -iu postgres psql

> SELECT * FROM select_table WHERE select_column='some data';

If the data matches the data from the primary, you have successfully set up streaming binary replication!

### Step 10: Automate Backups

Now that we have streaming binary replication set up, we want to automate backups to keep our secondary up-to-date with the latest changes. This can be done for a plethora of intervals, but let’s keep it simple and backup every night. We are using the _cron_ service to automate this task. We want our cron job to be carried out by the _postgres_ user, so we will become the _postgres_ user:

> sudo -iu postgres

Now we open a cron table ( _crontab_ ) with:

> crontab -e

The format of the crontab is laid out in the following format:

> minute hour day-of-month month day-of-week command

To set up daily backups, we add a line to the end of the file.

  * The minute setting is _0_ (zero; will occur on the hour)
  * The hour setting is _23_ (will occur at 11 pm).
  * The day-of-month, month, and day-of-week settings are the wildcard (*), so it occurs for each of these.



The command is the same used for our full backup:

> 0 23 * * * pgbackrest --stanza=tutorial --type=full backup

Our primary will now backup each night, and our secondary will be updated daily.

## Summary

There you have it! We installed and configured pgBackRest, configured PostgreSQL for binary replication, set up a passwordless SSH connection, transferred data between servers using binary replication, and automated the process to keep our backup current. From now on, you should have a functioning secondary for your primary database server.

---
[View this page online](https://www.commandprompt.com/education/configuring-binary-replication-with-pgbackrest/)

---

# Executing Citus Across Nodes for PostgreSQL

> Welcome back to our Citus blog series! So far in this series, we have installed and configured the Citus extension for PostgreSQL. Now that we are up and runni…

Welcome back to our Citus blog series! So far in this series, we have installed and configured the Citus extension for PostgreSQL. Now that we are up and running, it is time to distribute some data.

Let’s begin by inserting some sample data for demonstration purposes. First, we need a table in which to put the data. **On the coordinator node** , let’s enter our _demo_ database, in which we have loaded the Citus extension:

> sudo -iu postgres psql demo

Now that we are in the demo database, let’s create our table.

> CREATE TABLE stores (  
>  store_id SERIAL NOT NULL,  
>  address VARCHAR(255),  
>  city VARCHAR(255),  
>  state CHAR(2),  
>  zip INT,  
>  PRIMARY KEY(store_id)  
> );

Now, insert some data into our new table:

> INSERT INTO stores (address, city, state, zip)

> VALUES ('123 Test Dr.', 'Narnia', 'CA',56789);

> INSERT INTO stores (address, city, state, zip)

> VALUES ('456 Pickup Ave.', 'Tiny Town', 'BZ',13579);

> INSERT INTO stores (address, city, state, zip)

> VALUES ('789 Sesame St.', 'Generic', 'AP',12345);

> INSERT INTO stores (address, city, state, zip)

> VALUES ('321 Barber Blvd.', 'Anywhere', 'AP',12345);

Before we distribute the data, let’s confirm that there is no data on either worker node. **Let’s run this command within the** **_demo_** **database on each worker node** :

 _SELECT * FROM stores;_

Since we have not created the _stores_ table in the _demo_ database on either worker, it will return:

 _ERROR: relation "stores" does not exist_

Our table has data on the coordinator, but we need to distributed the data to the worker nodes. To do so, we will need to tell Citus which table we will be distributing and on which distribution key it will be distributed. The distribution key determines to what nodes Citus will distribute the shards created by the following command. We will create a distributed table from the _stores_ table, and _store_id_ will be the distribution key:

> SELECT create_distributed_table('stores', 'store_id');

We get output to the screen that looks like this:

> NOTICE: Copying data from local table...  
> NOTICE: copying the data has completed  
> DETAIL: The local data in the table is no longer visible, but is still on disk.  
> HINT: To remove the local data, run:

> SELECT truncate_local_data_after_distributing_table($$public.stores$$)  
>  create_distributed_table  
>  \--------------------------  
>   
>  (1 row)

This output tells us that Citus has successfully copied the data, but that the data remains on the disk (although hidden). It is suggested that we remove the local data from the coordinator node, since the coordinator node ideally contains only metadata and no production data. Before doing so, let’s check whether we can access the data **from the coordinator and each worker node** with:

> SELECT * FROM stores;

We should get the output of data we previously inserted:

> store_id | address | city | state | zip  
>  \----------+------------------+-----------+-------+-------  
>  1 | 123 Test Dr. | Narnia | CA | 56789  
>  2 | 456 Pickup Ave. | Tiny Town | BZ | 13579  
>  3 | 789 Sesame St. | Generic | AP | 12345  
>  4 | 321 Barber Blvd. | Anywhere | AP | 12345  
> (4 rows)

Now that we have confirmed we can access the data from each node, we should remove the data from local data as suggested. We are given an option to remove the local data from the coordinator node with:

> SELECT truncate_local_data_after_distributing_table($$public.stores$$);

Another option to drain the coordinator node is:

> SELECT citus_drain_node('10.1.1.1', 5432);

Since we are able to view the data from each worker node. It appears as though we have distributed the data, but how do we know for sure. Thankfully, the coordinator node has tables and views that provide information about the data across the nodes. One such view will show us where each shard is located, what kind of table it belongs to, and its size. Let’s view this information with:

> SELECT * FROM citus_shards;

It should return something that looks like this:

> table_name | shardid | shard_name | citus_table_type | colocation_id | nodename | nodeport | shard_size  
>  \------------+---------+---------------+------------------+---------------+------------+----------+------------  
>  stores | 102008 | stores_102008 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102009 | stores_102009 | distributed | 1 | 10.2.2.2 | 5432 | 8192  
>  stores | 102010 | stores_102010 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102011 | stores_102011 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102012 | stores_102012 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102013 | stores_102013 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102014 | stores_102014 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102015 | stores_102015 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102016 | stores_102016 | distributed | 1 | 10.1.1.1 | 5432 | 8192  
>  stores | 102017 | stores_102017 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102018 | stores_102018 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102019 | stores_102019 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102020 | stores_102020 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102021 | stores_102021 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102022 | stores_102022 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102023 | stores_102023 | distributed | 1 | 10.2.2.2 | 5432 | 8192  
>  stores | 102024 | stores_102024 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102025 | stores_102025 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102026 | stores_102026 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102027 | stores_102027 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102028 | stores_102028 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102029 | stores_102029 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102030 | stores_102030 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102031 | stores_102031 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102032 | stores_102032 | distributed | 1 | 10.1.1.1 | 5432 | 8192  
>  stores | 102033 | stores_102033 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102034 | stores_102034 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102035 | stores_102035 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102036 | stores_102036 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102037 | stores_102037 | distributed | 1 | 10.2.2.2 | 5432 | 0  
>  stores | 102038 | stores_102038 | distributed | 1 | 10.1.1.1 | 5432 | 0  
>  stores | 102039 | stores_102039 | distributed | 1 | 10.2.2.2 | 5432 | 0  
> (32 rows)

So, what are we looking at? Let’s break down the view:

  * This query has returned 32 rows, indicating that we have 32 shards of data. This is the default number of shards produced when creating a distributed table unless otherwise specified.
  * Each _shardid_ corresponds with the _shard_name_ for identification
  * The _citus_table_type_ column indicates what type of table the shard belongs to, which is the _distributed_ table stores, indicated by the _table_name_ column
  * The _colocation_id_ column indicates which shards belong to the same group. The value is 1 for each row, so they are placed together.
  * As you can see, the _nodename_ column lists the IP addresses of the worker nodes we designated during configuration.
  * The _shard_size_ column shows the size of the shard. You can see that two shards with data reside on one worker node, while the two other shards reside on the other worker node, with even distribution of the shards.



### Summary

And there you have it! We have used Citus to distribute data across multiple nodes. Citus has made distributed tables into a turn-key solution for PostgreSQL. Tune in for the next Citus blog post where we will add a node to the cluster!

### Related articles

  * [A quick guide to installing Citus](<https://commandprompt.com/education/a-quick-guide-to-installing-citus/>)
  * Citus Configuration

---
[View this page online](https://www.commandprompt.com/education/executing-citus-across-nodes/)

---

# How to Use REPEAT() Function in PostgreSQL

> The REPEAT() function in Postgres is a string function that retrieves a string consisting of the given string repeated an ‘n’ number of times.

PostgreSQL provides numerous string functions to work with the strings data, such as the **RIGHT()** function, **CONCAT()** function **, REPLACE()** function, etc. The **REPEAT()** is an inbuilt function in postgres that repeats a string a specific number of times. A frequent use case of the REPEAT() function is repeating a special character in a string, such as *, -, #, etc. This function is useful for creating test data or generating repeated string patterns.

This postgres blog demonstrates how to use the REPEAT() function in Postgres using various practical examples.

 **How to Use the REPEAT() Function in Postgres?**

The REPEAT() function in Postgres is a string function that retrieves a string consisting of the given string repeated an ‘n’ number of times:
    
    
    REPEAT(input_string, number);

It takes two arguments: an “input_string” and the “number_of_times” to repeat the string. For instance, REPEAT('Postgres, 2) would return the string 'PostgresPostgres'.

Let’s implement it practically.

 **Example 1: How Does the REPEAT() Function Works in Postgres?**

A string and a number are passed to the REPEAT() function; as a result, it will repeat the given string based on the specified number:
    
    
    SELECT REPEAT('Welcome ', 5);

The output shows that the stated function repeats the input string “n” times.

 **Example 2: Repeat a Special Character**

In the following example, a special character and an integer are passed to the REPEAT() function. Consequently, the REPEAT() function will repeat the given string based on the specified number:
    
    
    SELECT REPEAT('# ', 5);

The REPEAT() function repeats the input symbol five times.

 **Example 3: REPEAT() Function With CONCAT() Function**

In the following code, the REPEAT() function is used with the CONCAT() function to repeat a special character five times and concatenates it with a string:
    
    
    SELECT CONCAT('Welcome ', REPEAT('=', 5),'> Geeks');

In the above snippet, the “=” is repeated five times and is concatenated with “Welcome” and “> Geeks”.

 **Example 4: How to Use the REPEAT() Function Table’s Columns?**

We have already created a sample table named “staff_info”, whose data is enlisted in the following snippet:
    
    
    SELECT * FROM staff_info;

Let’s use the REPEAT() function with the CONCAT() function to repeat a special symbol and concatenate it with multiple columns:
    
    
    SELECT CONCAT(staff_name, REPEAT('=', 3), '> ', staff_designation)
    FROM staff_info;

This is how the REPEAT() function works in Postgres.

 **Conclusion**

Postgres offers an inbuilt string function named **REPEAT()** that repeats a string a specific times. The REPEAT() function in Postgres is a string function that retrieves a string consisting of the given string repeated an ‘n’ number of times. It takes two arguments: the “input_string” and the “number_of_times” to repeat the targeted string. The REPEAT() function is used with different string functions, such as the CONCAT() function, to maximize the functionality of the REPEAT() function. This blog post has presented an in-depth overview of how to use the REPEAT() function in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-repeat-function-in-postgresql/)

---

# How to Get a Day From a Date in PostgreSQL

> To get a day from a date, specify the “Day” as the first argument and a specific date, timestamp, or interval as the second argument to the EXTRACT().

PostgreSQL provides a built-in date function named the EXTRACT() function that extracts a specific field from a date, time, or timestamp. It allows us to pull out any date/time field, such as a day, month, hour, minute, etc., from any specific DateTime. You can use the EXTRACT() function with the “DAY” or “DOW” argument to get the day from the given date.

This write-up demonstrates various examples to explain how to get the day from a date in Postgres.

 **How to Get or Extract a Day From a Date in Postgres?**

Specify the “Day” as the first argument and a specific date, timestamp, or interval as the second argument to the EXTRACT() function to get a day from the given date, timestamp, or interval:
    
    
    EXTRACT('Day' FROM source_field);

The above syntax extracts the day of a month(1-31) from a given date, timestamp, or interval. However, if you want to extract the day of the week(DOW), then you can specify the “DOW” as the first argument to the EXTRACT() function:
    
    
    EXTRACT(‘DOW’ FROM source_field);

It will retrieve a value between 0 and 6, where “0” represents “Sunday” and 6 indicates “Saturday”.

 **Example 1: How to Get a Day From the Current Date?**

Specify the “Day” as the first argument and “CURRENT_DATE” as the second argument to get a day from the current date:
    
    
    SELECT EXTRACT('Day' FROM CURRENT_DATE);

The output shows that it’s the 31st of the current month.

 **Example 2: How to Get a Day From a Specific Date?**

To get a day from a specific date, you need to specify the “Day” as the first argument and the targeted date as the second argument:
    
    
    SELECT EXTRACT('Day' FROM DATE '2022-12-17');

The output shows that the EXTRACT() function extracts the day from the specified date.

 **Example 3: How to Get a Day of Week From the Current Date?**

Pass the DOW argument to the EXTRACT() function to get a day of the week from the current date:
    
    
    SELECT EXTRACT('DOW' FROM CURRENT_DATE);

The EXTRACT() function retrieves 2, indicating its second day of the week, i.e., Tuesday.

 **Example 4: How to Get a Day of Week From a Specific TIMESTAMP?**

To get a day from a specific date, you need to specify the “Day” as the first argument and the targeted date as the second argument:
    
    
    SELECT EXTRACT('DOW' FROM TIMESTAMP '2022-12-17 11:30:30');

This way, you can use the EXTRACT() function to get a day of the week from the given timestamp.

 **Example 5: How to Get a Day and DOW From the Table’s Data?**

We have already created a sample table named “staff_info”, whose data is enlisted in the following snippet:
    
    
    SELECT * FROM staff_info;

Suppose we want to extract the day and DOW from the “joining_date”; for this purpose, we will use the EXTRACT() function as follows:
    
    
    SELECT staff_name, joining_date,
    EXTRACT('Day' FROM joining_date) As day,
    EXTRACT('DOW' FROM joining_date) As DOW
    FROM staff_info;

The output signifies that the EXTRACT() function extracts the day and DOW from the selected column.

 **Conclusion**

In PostgreSQL, the extract function extracts a specific field from a date, time, or timestamp. To get a day from a date, specify the “Day” as the first argument and a specific date, timestamp, or interval as the second argument to the EXTRACT(). To extract the day of the week(DOW) from a date, interval, or timestamp, you must specify the “DOW” as the first argument to the EXTRACT() function. This blog post has presented an in-depth overview of how to get a day from a date in Postgres using the EXTRACT() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-a-day-from-a-date-in-postgresql/)

---

# Postgres SQRT() Function With Practical Examples

> In PostgreSQL, the SQRT() is a built-in mathematical function that accepts a positive numeric value and retrieves its square root.

While working with Mathematical data, one of the most frequently performed tasks is finding the square root of a number. Postgres users may encounter a situation where they need to find a specific number's square root. Postgres provides a built-in SQRT() function to deal with such situations efficiently.

This post illustrates the Postgres SQRT() function and its working via practical examples.

 **How to Use SQRT() in PostgreSQL?**

The SQRT() function accepts a positive numeric value and retrieves its square root. The below-given syntax is used to calculate the square root of a positive numeric value using the SQRT() function:
    
    
    SQRT(num);

The “num” must be a positive value.

 **Example 1: Calculating the Square Root of a Positive Integers**

The below snippet demonstrates the usage of the SQRT() function:
    
    
    SELECT SQRT(144);

The output shows that the square root of “144” is 12.

 **Example 2: Calculating the Square Root of a Positive Floating Point Value**

Let’s learn how the SQRT() function work with floating point values:
    
    
    SELECT SQRT(145.22);

The output shows that the square root of “145.22” is 12.05072.

 **Example 3: Calculating the Square Root of a Negative Numeric Value**

Let’s pass a negative value to the SQRT() function and see how it deals with the negative values:
    
    
    SELECT SQRT(-145);

The SQRT() function throws an error stating that it “can’t accept a negative value”.

 **Example 4: Finding the Square Root of the Table’s Data**

Suppose we have a sample table that stores numeric data, as shown in the following snippet:

The task is to find the square root of each entry. To achieve this particular task, we will utilize the following statement:
    
    
    SELECT Value_1, SQRT(value_1)
    FROM example_data;

This way, you can get the square root of the positive numbers using the Postgres SQRT() function.

 **Conclusion**

The SQRT() is a built-in mathematical function that accepts a positive numeric value and retrieves its square root. It accepts only positive numbers, and passing negative values to the stated function results in an error. It can find the square root of any numeric value, such as fractional point values, integer values, etc. This blog post considered several use cases of the SQRT() function with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgres-sqrt-function-with-practical-examples/)

---

# Postgres Modulo Function With Examples

> PostgreSQL provides a built-in math function named MOD() that accepts numeric values as arguments, performs division, and retrieves the remainder after divisio…

When we divide two numbers, sometimes the given numbers are fully divided, while sometimes the given numbers are not equally divided. In such a case, we get a remainder. In Postgres, the DIV() function performs the division on the input numbers and retrieves the quotient. What if the user wants the remainder instead of a quotient? How to deal with such cases? Well! Nothing to worry about! Because postgres facilitates us with a MOD() function that retrieves the remainder.

This post explains various use cases of the MOD() function via practical demonstration.

 **How Does the MOD() Function Work in Postgres?**

PostgreSQL provides a built-in math function named MOD() that accepts numeric values as arguments, performs division, and retrieves the remainder after division. The return type of the MOD() relies on the data type of the input values.

 **Example 1: MOD() Function With Integer Values**

We pass the integer values to the MOD() function in the following query:
    
    
    SELECT MOD(125, 12) As Remainder;

The MOD() function retrieves an integer as a remainder.

 **Example 2: MOD() Function With Float Values**

We pass the floating point values to the MOD() function in the below snippet:
    
    
    SELECT MOD(125.25, 12.70) As Remainder;

The MOD() function retrieves a float value as a remainder.

 **Example 3: MOD() Function With Negative Numerator**

We pass a negative numerator to the MOD() function in the below snippet:
    
    
    SELECT MOD(-125, 12) As Remainder;

The MOD() function retrieves a negative remainder when a negative numerator is passed to the MOD() function.

 **Example 4: MOD() Function With Negative Denominator**

In the below example, we pass a negative denominator to the MOD() function:
    
    
    SELECT MOD(125, -12) As Remainder;

The MOD() function retrieves a positive remainder when a negative denominator is passed to the MOD() function.

 **Example 5: MOD() Function With Both Negative Values**

In the following code snippet, we pass a negative numerator and negative denominator to the MOD() function:
    
    
    SELECT MOD(-125, -12) As Remainder;

The MOD() function retrieves a negative numerator.

 **Note:** from the above examples, we can conclude that the remainder’s sign depends on the numerator. If the numerator is positive, we will get a positive remainder; if the numerator is negative, we will get a negative remainder.

 **Example 6: How to Use the MOD() Function With Postgres Tables?**

We have a sample table named “example_data” that contains the following data:
    
    
    SELECT * FROM example_data;

The below snippet demonstrates the usage of the MOD() function on the table’s data:
    
    
    SELECT value_1, value_2, MOD(value_1, value_2)
    FROM example_data;

This way, you can use the MOD() function to find the "remainder" of two values.

 **Conclusion**

PostgreSQL provides a built-in math function named MOD() that accepts numeric values as arguments, performs division, and retrieves the remainder after division. The return type of the MOD() relies on the data type of the input values. The remainder’s sign depends on the numerator. If the numerator is positive, we will get a positive remainder; if the numerator is negative, we will get a negative remainder. This post used practical examples to explain a comprehensive guide on the MOD() function.

---
[View this page online](https://www.commandprompt.com/education/postgres-modulo-function-with-examples/)

---

# Difference Between DIV() and MOD() Function in PostgreSQL

> The DIV() and MOD() functions in Postgres perform the division on numeric values. However, the DIV() function retrieves a quotient while the MOD() function ret…

PostgreSQL provides various built-in mathematical and trigonometric functions to deal with numeric data. For instance, the ROUND() function rounds a number; the RANDOM() function generates the random numbers, the abs() function retrieves the absolute value, etc. The DIV() and MOD() are also mathematical functions that perform the division on the given values.

This post uses practical examples to present a comparative analysis of the Postgres MOD() and DIV() functions.

 **Difference Between DIV() and MOD() Function in Postgres**

The DIV() and MOD() are built-in math functions that accept the numeric values and perform division on them. However, the DIV() function retrieves a quotient while the MOD() function retrieves the remainder.

Let’s put these functions into practice for a profound understanding.

 **Example 1: How Does the DIV() Function Work in Postgres?**

In the following example, we will pass two numeric values to the DIV() function:
    
    
    SELECT DIV(5000, 4);

The output shows that the DIV() function retrieves the quotient integer.

 **Example 2: How Does the MOD() Function Work in Postgres?**

In the following example, we pass the same numeric values to the MOD() function:
    
    
    SELECT MOD(5000, 4);

The output shows that the MOD() function retrieves the remainder instead of a quotient integer.

 **Example 3: How Does the DIV() Function Work With Negative Values in Postgres?**

Let’s pass a negative value to the DIV() function and see how the DIV() function treats the negative values:
    
    
    SELECT DIV(-5000, 4);

The output clarifies that this time the DIV() function returns a negative quotient.

 **Example 4: How Does the MOD() Function Work With Negative Values in Postgres?**

Let’s pass a negative value to the MOD() function and see how it works:
    
    
    SELECT MOD(-5000, 3);

The MOD() function retrieves the remainder with the negation sign.

 **Example 5: How Do the DIV() and MOD() Functions Work on Table’s Data?**

We have a sample table named “example_data” that contains the following data:

Let’s learn how to use the DIV(), and MOD() functions on the table’s data:
    
    
    SELECT value_1, value_2,
    DIV(value_1, value_2) AS div_result,
    MOD(value_1, value_2) AS mod_result
    FROM example_data;

The output shows that when both the numerator and denominator are negative, the DIV() function retrieves a positive value, while the MOD() function retrieves a negative value.

This is how the DIV() and MOD() functions work on Postgres tables.

 **Conclusion**

The DIV() and MOD() are built-in math functions that accept the numeric values and perform division on them. However, the DIV() function retrieves a quotient while the MOD() function retrieves the remainder. When both the numerator and denominator are negative, the DIV() function retrieves a positive value, while the MOD() function retrieves a negative value. This Post explained the difference between DIV() and MOD() functions using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/difference-between-div-and-mod-function-in-postgresql/)

---

# PostgreSQL RIGHT() Function: Extract Characters From the Right of a String

> The RIGHT() function takes a string and the number of characters to extract as arguments and retrieves the extracted/modified string.

PostgreSQL offers a variety of string functions to manipulate the strings data, such as the **LENGTH()** function, **LOWER()** function **, REPLACE()** function, etc. **RIGHT()** is one of the built-in string functions that extract the characters from the right of the targeted string. It can extract the “n” number of characters from a string, where n can be a positive or negative value.

This postgres blog demonstrates how to use the RIGHT() function in Postgres using various practical examples.

 **How Does the RIGHT() Function Work in PostgreSQL?**

The RIGHT() function takes a string and the number of characters to extract as arguments and retrieves the extracted/modified string:
    
    
    RIGHT(string, n);

The “n” represents the number of characters extracted from a string's right. It can be positive or negative. If the value of “n” is negative, then all the string characters will be extracted except the ‘n’ leftmost characters.

 **Example 1: Using the RIGHT() Function With a Positive Value of n**

In the following query, we will extract the six characters from the rightmost of the given string using the RIGHT() function:
    
    
    SELECT RIGHT('Hello! Welcome to Commandprompt', 6);

The output signifies that the RIGHT() function retrieves the six characters from the right of the input string.

 **Example 2: Using the RIGHT() Function With a Negative Value of n**

The following statement illustrates how the RIGHT() function work if the “n” parameter has a negative value:
    
    
    SELECT RIGHT('Hello! How are You', -6);

The output indicates that the RIGHT() function retrieves all the characters from a string except the six leftmost characters.

 **Example 3: Extracting Specific Records Via the RIGHT() Function**

We have created a sample table named “staff_info” with the following data:

Now we will utilize the RIGHT() function to extract all those employees whose name ends with “e”:
    
    
    SELECT staff_name, staff_designation
    FROM staff_info 
    WHERE RIGHT(staff_name, 1)='e';

The output demonstrates that the **RIGHT()** function retrieves the details of all those staff members whose names end with “ **e** ”.

This is how you can use the RIGHT() function in Postgres.

 **Conclusion**

The RIGHT() function takes a string and the number of characters to extract as arguments and retrieves the extracted/modified string. It can extract the “n” number of characters from a string, where n can be a positive or negative value. If the value of “n” is negative, then all the string characters will be extracted except the “n” leftmost characters. This post explained the usage of the RIGHT() function using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-right-function-extract-characters-from-the-right-of-a-string/)

---

# How to Describe Postgres Tables Using SQL Shell (psql)

> SQL Shell supports various commands and queries to describe the Postgres tables, such as “\d”, “\d+”, information_schema, etc.

In database management systems like PostgreSQL, describing tables provides us with detailed information about the tables of a specific database. For this purpose, different commands and queries are used in Postgres, such as **“\d”** , **“\d+”** , **information schema** , etc. These commands and queries allow us to describe a specific table or all the tables of a database. Postgres users can execute these commands from the SQL Shell(psql).

This Post presents a practical guide on describing the Postgres tables using SQL Shell. This post will discuss the following methods of describing the tables using SQL Shell:

  * How to Describe All the Postgres Tables Using “\d” Command in SQL Shell?
  * How to Describe All the Postgres Tables Using “\d+” Command in SQL Shell?
  * How to Describe a Specific Postgres Table Using “\d” Command in SQL Shell?
  * How to Describe a Specific Postgres Table Using “information_schema” in psql?



 **How to Describe All the Postgres Tables Using “\d” Command in SQL Shell?**

Executing the “ **\d** ” command from SQL Shell will describe all the tables of the selected database. Here is an example:
    
    
    \d

The output shows that the “\d” command describes all the relations of the “postgres” database. It retrieves the schema name, table name, type, and owner.

 **How to Describe All the Postgres Tables Using “\d+” Command in SQL Shell?**

Alternatively, you can use the “\d+” command to describe all the tables with more details like table size, access method, persistence, etc.
    
    
    \d+

 **How to Describe a Specific Postgres Table Using “\d” Command in SQL Shell?**

The “\d” command can also be used to describe only a specific table in Postgres. It will retrieve the complete structure of the selected table. To do that, all you need to do is, specify the “\d” command followed by the table name. For instance, the below statement describes the “employee_info” table:
    
    
    \d employee_info;

The output signifies that the “\d” command describes the complete structure of the selected table, such as column name, type, default value, etc. Moreover, it also provides details regarding the table constraints, such as primary, foreign key constraints, etc.

 **Note:** You can also use the “\d+” Command followed by the table name to describe the table with more details, such as access method, description, etc.

 **How to Describe All the Postgres Tables Using “information_schema” in psql?**

You can also use the built-in information_schema to describe a specific table or all the schema tables.
    
    
    SELECT COLUMN_NAME, DATA_TYPE
    FROM information_schema.columns;

In the above snippet, we described all the tables' column names and data types using information_schema.

 **How to Describe a Specific Postgres Table Using “information_schema” in psql?**

You can also use the information_schema to describe only a specific table. For this purpose, you must specify the table’s name in the WHERE clause:
    
    
    SELECT COLUMN_NAME, DATA_TYPE
    FROM information_schema.columns
    WHERE table_name = 'employee_info';

This way, you can describe a specific table using the built-in ‘information_schema”.

 **Conclusion**

SQL Shell supports various commands and queries to describe the Postgres tables, such as “\d”, “\d+”, information_schema, etc. These commands and queries allow us to describe a specific table or all the tables of a database. The “\d+” command describes all the tables with more details like table size, access method, persistence, etc. This post explained several methods to describe the Postgres tables using SQL Shell.

---
[View this page online](https://www.commandprompt.com/education/how-to-describe-postgres-tables-using-sql-shell-psql/)

---

# PostgreSQL LEFT() Function: Extract Characters From the Left of a String

> The LEFT() function takes a string and the number of characters to extract as arguments and retrieves the extracted/modified string.

PostgreSQL facilitates us with numerous string functions, such as **CONCAT()** function, **LENGTH()** function, **INITCAP(),** etc. The **LEFT()** function is also a string function that is used to extract the characters from the left of the targeted string. It can extract the “n” number of characters from a string, where n can be a positive or negative value.

This postgres blog demonstrates how to use the LEFT() function in Postgres using various practical examples.

 **How to Use LEFT() Function in PostgreSQL?**

The LEFT() function takes a string and the number of characters to extract as arguments and retrieves the extracted/modified string:
    
    
    LEFT(string, n);

The “n” represents the number of characters extracted from a string's left. It can be positive or negative. If the value of “n” is negative, then all the string characters will be extracted except the ‘n’ rightmost characters.

 **Example 1: Using the LEFT() Function With a Positive Value of n**

In the following query, we will extract the five characters from the leftmost of the given string using the LEFT() function:
    
    
    SELECT LEFT('Hello! How are You', 5);

The output signifies that the LEFT() function retrieves the five characters from the left of the given string.

 **Example 2: Using the LEFT() Function With a Negative Value of n**

The following statement demonstrates how the LEFT() function work if the “n” parameter has a negative value:
    
    
    SELECT LEFT('Hello! How are You', -5);

The output indicates that the LEFT() function retrieves all the characters from a string except the five rightmost characters.

 **Example 3: Using the LEFT() Function on Tables Data**

We have created a sample table named “staff_info” with the following data:

Let’s learn how to extract the first three characters of the employee's name using the LEFT() function:
    
    
    SELECT LEFT(staff_name, 3)
    FROM staff_info;

The output demonstrates that the LEFT() function retrieves the first three characters of all the employees’ names.

 **Example 4: Extracting Specific Records Via the LEFT() Function**

Now we will utilize the LEFT() function to extract all those employees whose name starts with “Jo”:
    
    
    SELECT staff_name, staff_designation
    FROM staff_info 
    WHERE LEFT(staff_name, 2)='Jo';

The output demonstrates that the **LEFT()** function retrieves the designation of all those staff members whose names start with “ **Jo** ”.

 **Conclusion**

The LEFT() function takes a string and the number of characters to extract as arguments and retrieves the extracted/modified string. It can extract the “n” number of characters from a string, where n can be a positive or negative value. If the value of “n” is negative, then all the string characters will be extracted except the “n” leftmost characters. This post explained the usage of the LEFT() function using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-left-function-extract-characters-from-the-left-of-a-string/)

---

# How to Perform Division in PostgreSQL

> Postgres offers several built-in functions and operators that are used to perform division on different numeric values, such as the “/” operator, DIV() functio…

Postgres offers several built-in functions and operators that are used to perform division on different numeric values. For instance, the **“/”** operator, **DIV()** function, **MOD()** function, etc. The return type of all these functions/operators depends on the data type of the given values.

This post will demonstrate all the possible ways to perform division on the given numbers in Postgres.

 **How to Use DIV(), MOD(), /, and % in Postgres?**

The **“/”** operator and **DIV()** function perform the division on given numbers and retrieves the integer quotient. On the other hand, the MOD() function and “%” operator perform the division on the given numbers and retrieve the remainder instead of the quotient.

Let’s put these functions and operators into practice.

 **Example 1: A Comparative Analysis**

In this example, we will use DIV() function, MOD() function, “/” operator, and the “%” operator side-by-side for a profound understanding:
    
    
    SELECT DIV(550, 2) AS div_function, 
    (550/2) AS Division_operator, 
    MOD(550, 2) AS mod_function, 
    (550%2) AS Remainder;

The output shows that the “DIV()” function and “/” operator retrieves the same result, i.e., quotient integer. On the other hand, the MOD() function and the “%” operator retrieves the same result, i.e., the remainder of two numbers.

 **Example 2: How to Perform Division in Postgres Using DIV() Function?**

We have a sample table named “emp_data” that contains the following data:

Suppose we have to find the half salary of each employee; for this purpose, we will use the DIV() function as follows:
    
    
    SELECT emp_name, emp_salary, DIV(emp_salary, 2) AS half_salray
    FROM emp_data;

The output shows that the stated function successfully performs the division and retrieves the quotient.

 **Example 3: How to Perform Division in Postgres Using / Operator?**

The below coding example will help you understand the usage of the “/” operator in a better way:
    
    
    SELECT emp_name, emp_salary, (emp_salary/2) AS half_salray
    FROM emp_data;

The output shows that the “/” operator retrieves the same results as the DIV() function.

 **Example 4: How to Perform Division in Postgres Using MOD() Function?**

The below code illustrates how the MOD() function work in Postgres:
    
    
    SELECT emp_name, emp_salary, MOD(emp_salary, 2)
    FROM emp_data;

The output shows that the MOD() function retrieves the remainder instead of the quotient.

 **Example 5: How to Perform Division in Postgres Using % Operator?**

The below coding example will help you understand this concept better:
    
    
    SELECT emp_name, emp_salary, (emp_salary%2) AS REMAINDER
    FROM emp_data;

The output snippet signifies that the “%” operator generates the same results as the MOD() function.

 **Conclusion**

Postgres offers several built-in functions and operators that are used to perform division on different numeric values. For instance, the **“/”** operator, **DIV()** function, **MOD()** function, etc. The **“/”** operator and **DIV()** function perform the division on given numbers and retrieves the integer quotient. On the other hand, the MOD() function and “%” operator perform the division on the given numbers and retrieve the remainder instead of the quotient. This post presented various examples of performing division on the given numbers in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-perform-division-in-postgresql/)

---

# INITCAP: How to Capitalize the First Letter of Every Word in PostgreSQL

> The INITCAP() is a built-in string function that accepts a string as an argument and converts the first letter of every word into uppercase and the remaining l…

Postgres supports various letter case functions to convert the letters from one case to another, such as **LOWER()** , **UPPER()** , and **INITCAP()**. In PostgreSQL, the INITCAP() is used to capitalize the first character/letter of every word. The function name is derived from two words: “ **INIT** ” means “ **initials** ”, and “ **CAP** ” means “ **Capital** ”.

This post presents a comprehensive guide on how to use the INITCAP() function in Postgres via practical examples.

 **What is the INITCAP() Function, and how it Works in Postgres?**

The INITCAP() is a built-in string function that accepts a string as an argument and converts the first letter of every word into uppercase and the remaining letters into lowercase:
    
    
    INITCAP(input_string);

Specify the string of your choice in place of “input_string”.

 **Example 1: How Does the INITCAP() Work in Postgres?**

Pass a string to be converted as an argument to the INITCAP() function and see how the INITCAP() function works:
    
    
    SELECT INITCAP('welcome to commandprompt.com');

The output snippet signifies that the first letter of each word has been successfully converted into uppercase.

 **Example 2: How Does the INITCAP() Work on Table’s Data in Postgres?**

We have created a sample table named “employee_info”, whose data is shown in the following snippet:

Let’s use the “INITCAP()” function on the “e_email” column to capitalize the first letter of each word:
    
    
    SELECT e_name, INITCAP(e_email)
    FROM employee_info;

The first letter of each word of the selected column has been capitalized successfully.

 **Example 3: How to Use the INITCAP() Function With CONCAT() Function in Postgres?**

The INITCAP() function can be used with different string functions to achieve different functionalities. For instance, the INITCAP() function can be used with the CONCAT() function to concatenate multiple columns and capitalize the first letter of every word:
    
    
    SELECT e_name, e_email, 
    INITCAP(CONCAT(e_name,' - ', e_email)) As emp_details
    FROM employee_info;

The output snippet clarifies that the selected columns have been concatenated and the first letter of each word in capital.

This is how you can implement the INITCAP() function on the string data.

 **Conclusion**

The **INITCAP()** function is used in PostgreSQL to capitalize the first character/letter of every word. The function name is derived from two words: “ **INIT** ” means “ **initials** ”, and “ **CAP** ” means “ **Capital** ”. The INITCAP() is a built-in string function that accepts a string as an argument and converts the first letter of every word into uppercase and the remaining letters into lowercase. This post presented a comprehensive guide on capitalizing the first letter of every word using the Postgres INITCAP() function.

---
[View this page online](https://www.commandprompt.com/education/initcap-how-to-capitalize-the-first-letter-of-every-word-in-postgresql/)

---

# Citus Configuration for PostgreSQL sharding

> Welcome back to our Citus blog series! Previously, we introduced Citus, reviewed use cases, reviewed Citus structure, and installed Citus alongside PostgreSQL …

Welcome back to our Citus blog series! Previously, we introduced Citus, reviewed use cases, reviewed Citus structure, and installed Citus alongside PostgreSQL 14. This post will focus on configuring settings to make sure Citus is communicating between all instances.

## Multi-Node Configuration

Now that we have Citus and PostgreSQL installed per our previous blog post, let’s configure our servers to communicate with one another and transfer data. **The following steps should be repeated on the coordinator node and each worker node.** Let’s begin by configuring postgresql.conf:

> sudo vi /etc/postgresql/14/main/postgresql.conf

First, we will instruct the database server to listen on all IP interfaces, not just the localhost:

> listen_addresses = '*'

Since Citus uses logical replication to move shards, we set the wal_level to logical:

> wal_level = logical

We need to preload the Citus extension. Find the line with _shared_preload_libraries_ , and modify it to look like so:

> shared_preload_libraries = 'citus'

We have successfully set up configuration for PostgreSQL server. Next, let’s edit the host-based authentication file to allow access to the cluster. We can open the file in a text editor with:

> sudo vi /etc/postgresql/14/mian/pg_hba.conf

Once we have the file open in the editor, scroll down to the bottom and make sure the following lines are present to ensure PostgreSQL is able to communicate between all local and private IP addresses:

> host all all 10.0.0.0/8 scram-sha-256  
> host all all 127.0.0.1/32 scram-sha-256  
> host all all ::1/128 scram-sha-256

If your network does not match the _10.0.0.0/8_ subnet mask, then you can replace that line with the following line to match any address in any subnet that the server is connected to directly:

> host all all samenet scram-sha-256

Now that we have made these changes to _postgresql.conf_ and _pg_hba.conf_ , it is important for us to restart PostgreSQL in order for the changes to take effect. We can do so with:

> sudo systemctl restart postgresql

Next up is adding the Citus extension to every database that will be used in the cluster. We’ll begin by creating the _demo_ database:

> sudo -iu postgres psql -c "CREATE DATABASE demo;"

Next, we add the Citus extension to the _demo_ database:

> sudo -iu postgres psql -d demo -c "CREATE EXTENSION citus;"

We can confirm that Citus has been loaded into our _demo_ database with:

> sudo -iu postgres psql -d demo -c "SELECT * FROM pg_extension;"

And it should print out something like this:

> oid | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition

> \-------+----------------+----------+--------------+----------------+------------+-----------+--------------

> 13781 | plpgsql | 10 | 11 | f | 1.0 | |

> 16385 | citus_columnar | 10 | 11 | f | 11.1-1 | |

> 16441 | citus | 10 | 11 | f | 11.1-1 | |

> (3 rows)

The rows with _citus_ and _citus_columnar_ that have _extversion 11.1-1_ confirm that we have successfully loaded into our _demo_ database.

## Setting Up .pgpass

To increase security for our replication process, we will store PostgreSQL user passwords in the .pgpass file. We want this file to be located in the postgres user’s home directory, which is /var/lib/postgresql in Debian-based systems and /var/lib/psql in Red Hat systems. We want to become the postgres user for the following series of commands:

> sudo -iu postgres

Before we store our password in the .pgpass file, we shall first set our password. Launch _psql_ :

> psql

Now, set the postgres password using the password meta-command:

> \password

This prompts you to enter a password and repeat to confirm. We are now going to exit _psql_ and return to the postgres user:

> exit

Let’s create the .pgpass file with:

> touch .pgpass

Since we created the .pgpass file with the postgres user, we ensure postgres owns the file. For security purposes, we will restrict access to the file so only the postgres user can write on and read the file. We can change the ownership and change the mode of the .pgpass file with the following command:

> chmod 600 .pgpass

Now that its data is properly protected, let’s open .pgpass with:

> vi .pgpass

You will see that the lines in this file follow the format:

> hostname:port:database:username:password

For increased security levels, you can be specific and explicitly name the hostname, port, and database. When using more specific parameters, it is important to include a line in .pgpass for each instance with unique parameters to ensure proper communication. For the simplicity of this tutorial, we will use wildcards (*) in the hostname, port, and database fields. The wildcards indicate that the username and password will be applicable to any hostname, port, or database to which the user has access. We set the username to the postgres user, and we set the password to postgres, since that is what we set it to earlier in this step. We are able to do this since we have set the _postgres_ user password to ‘postgres’ on each instance we will be accessing. If you have set a different password for the postgres user on any instance, that instance will need its own line in the .pgpass file with specific parameters. Let’s add this line to .pgpass:

> *:*:*:postgres:postgres

Now let’s save and exit the file.

### Coordinator Node Configuration

In addition to the previous steps we performed for all nodes, we need to include some important information on the coordinator node so it can properly communicate with the worker nodes. As the postgres user, launch _psql_ and move to the _demo_ database:

> psql demo

Let’s begin this portion by setting the coordinator host with:

> SELECT citus_set_coordinator_host('10.1.1.1', 5432);

Next, we will add the worker nodes from the coordinator:

> SELECT * from citus_add_node('10.2.2.2', 5432);  
> SELECT * from citus_add_node('10.3.3.3', 5432);

Let’s verify that worker configuration has been set correctly with:

> SELECT * FROM citus_get_active_worker_nodes();

The print out should read something like:

> node_name | node_port  
>  \-------------+-----------  
>  10.2.2.2 | 5432  
>  10.3.3.3 | 5432  
> (2 rows)

### Summary

We have covered multi-node Citus configuration in postgresql.conf, pg_hba.conf, .pgpass, and node assignment. We reviewed configuration settings that need to be set for all instances where we will be using Citus, as well as the assignment of nodes from the coordinator. The next blog post in this series will cover distributing data across the Citus nodes.

### Related articles

  * [A quick guide to installing Citus](<https://commandprompt.com/education/a-quick-guide-to-installing-citus/>)
  * Executing across Citus Nodes

---
[View this page online](https://www.commandprompt.com/education/citus-configuration/)

---

# How to Get Day Names in PostgreSQL

> To extract the day name from a specific date, you need to pass the date/timestamp as a first argument and a valid day format as the second argument to the “TO_…

In PostgreSQL, the **EXTRACT()** function is used to get a day, month, year, etc., from a DATE, TIME, or TIMESTAMP. We can use this function to get/extract the day from the specified date or time stamp. However, it retrieves the specific part/field from the specified date as a number. If we have to get/extract the day names from a specific date, then we must use the **TO_CHAR()** function.

This post demonstrates a practical guide on how to get or extract the day of the week from a specific date.

 **How to Extract Day Names in Postgres?**

To extract the day name from a specific date, you need to pass the date/timestamp as a first argument and a valid day format as the second argument to the “ **TO_CHAR()** ” function:
    
    
    SELECT TO_CHAR(DATE  'specific_date', 'day-format');

Postgres supports the below-listed day formats:

  * “ **DAY”** : It retrieves the full day name in uppercase, for instance, “MONDAY”.
  * “ **day** ”: It retrieves the full day name in lowercase, for instance, “monday”.
  * “ **DY** ”: It retrieves the first three letters of the day's name in uppercase, for instance, “MON”.
  * “ **dy** ”: It retrieves the first three letters of the day's name in lowercase, for instance, “mon”.



 **Example 1: How to Get the Day of Week in Uppercase?**

Suppose we want to extract the day of the week from the current date; for this, we will execute the TO_CHAR() function as follows:
    
    
    SELECT TO_CHAR(CURRENT_DATE, 'DAY');

The output demonstrates that the current day of the week is Monday.

 **Example 2: How to Get the Day of Week in Lowercase?**

Suppose we want to get the day of the week(lowercase) from a specific date; for this, we will execute the TO_CHAR() function as follows:
    
    
    SELECT TO_CHAR(DATE '2022-12-14', 'DAY');

The TO_CHAR() function retrieves the day of the week in lowercase.

 **Example 3: How to Get the Abbreviated Day of Week in Uppercase?**

To get the first three letters of the day’s name in uppercase from a specific date, you need to execute the TO_CHAR() function as follows:
    
    
    SELECT TO_CHAR(DATE '2022-12-14', 'DY');

The TO_CHAR() function retrieves the abbreviated day of the week in uppercase.

 **Example 4: How to Get the Abbreviated Day of Week in Lowercase?**

To extract the abbreviated day of the week in lowercase, pass the “dy” format as the second argument to the TO_CHAR() function:
    
    
    SELECT TO_CHAR(DATE '2022-12-14', 'dy');

The TO_CHAR() function retrieves the abbreviated day of the week in lowercase.

 **Example 5: How to Get the Day of Week From Table’s Data?**

A sample table named “staff_info” has already been created with the following content:
    
    
    SELECT * FROM staff_info;

Let’s execute the TO_CHAR() function to get the day names from the “joining_date” column:
    
    
    SELECT staff_name, TO_CHAR(joining_date, ‘DAY’) AS joining_day
    FROM staff_info;

This is how you can get/extract the name of the weekdays from a specific date or timestamp.

 **Conclusion**

In PostgreSQL, the TO_CHAR() function is used to extract the day’s name from a specific date or timestamp. For this purpose, you must pass the date/timestamp as the first argument and a valid day format as the second argument to the “ **TO_CHAR()** ” function. Postgres offers various formats to get the day names, such as “DAY”, “DY”, “day”, and “dy”. This post demonstrates various examples of how to get day names in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-day-names-in-postgresql/)

---

# PostgreSQL ORDER BY RANDOM

> In PostgreSQL, the ORDER BY clause is used with the RANDOM() function to get the random data from large tables.

In PostgreSQL, the tables maintain the default insertion order. To specify the table records in a particular order(ascending or descending), the “ORDER BY” clause is used in Postgres. However, if we have to specify the table’s records in a random order, then we can use the “ **ORDER BY RANDOM** ” function.

This post demonstrates various methods to explain the usage of the Postgres ORDER BY RANDOM function.

 **How to Use PostgreSQL ORDER BY RANDOM?**

In Postgres, the ORDER BY clause is used with the RANDOM() function to get the random data from large tables.
    
    
    SELECT col_list
    FROM tab_name
    ORDER BY RANDOM();

It retrieves the data faster because the “ORDER BY RANDOM” returns a random number from the table.

 **Example 1: How Does ORDER BY RANDOM() Work in Postgres?**

A sample table named “staff_info” has already been created with the following content:
    
    
    SELECT * FROM staff_info;

Now execute the SELECT command with the “ORDER BY RANDOM” to get the table’s data in random order:
    
    
    SELECT * FROM staff_info
    ORDER BY RANDOM();

The output shows that the “ORDER BY RANDOM()” function retrieves the table’s data in random order.

 **Example 2: How Does ORDER BY RANDOM() Work With the WHERE Clause in Postgres?**

Use the “ **ORDER BY RANDOM()** ” with the “ **WHERE** ” clause to get the filtered random records:
    
    
    SELECT * FROM staff_info
    WHERE staff_id <= 8
    ORDER BY RANDOM();

The ORDER BY RANDOM retrieves the random records, but according to the condition specified within the WHERE clause.

 **Example 3: How Does ORDER BY RANDOM() Work With the LIMIT Clause in Postgres?**

Use the “ **ORDER BY RANDOM()** ” with the “ **LIMIT** ” clause to get only limited random records from the selected table:
    
    
    SELECT * FROM staff_info
    ORDER BY RANDOM()
    LIMIT 5;

In the above snippet, the limit is specified as “5”; as a result, the RANDOM() function will retrieve only five random records from the “staff_info” table:

Whenever you use the "ORDER BY RANDOM()" function with the LIMIT clause, you'll get the tables' records within the specified limit but in a different/random order.

 **Example 4: How Does ORDER BY RANDOM() Work With the BETWEEN Operator in Postgres?**

Use the “ **ORDER BY RANDOM()** ” with the “ **BETWEEN** ” operator to get the random records from the selected table, but within the specified range:
    
    
    SELECT * FROM staff_info
    WHERE staff_id BETWEEN 5 AND 10
    ORDER BY RANDOM();

This time the “ORDER BY RANDOM” function retrieves the random records within the specified range.

 **Example 5: How Does ORDER BY RANDOM() Work With the IN Operator in Postgres?**

Use the “ **ORDER BY RANDOM()** ” with the “ **IN** ” operator to get the random records based on the specific condition:
    
    
    SELECT * FROM staff_info
    WHERE staff_id BETWEEN 5 AND 10
    ORDER BY RANDOM();

The above output shows that the ORDER BY RANDOM retrieves the random records from the staff_info table based on the condition specified in the “IN” operator.

 **Conclusion**

In Postgres, the ORDER BY clause is used with the RANDOM() function to get the random data from large tables. The ORDER BY RANDOM can be used with different clauses and operators to avail maximum functionality, such as it can be used with WHERE clause, LIMIT clause, BETWEEN operator, etc. ORDER BY RANDOM is very useful when working with large Postgres tables. This post has explained the usage of the ORDER BY RANDOM in Postgres via numerous examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-order-by-random/)

---

# PostgreSQL ARRAY_AGG() Function With Examples

> The ARRAY_AGG() function in Postgres is an aggregate function that takes a column as input and returns an array of values from all the rows in the specified gr…

The **ARRAY_AGG()** in PostgreSQL is a built-in aggregate function used for grouping and aggregating data. The ARRAY_AGG() function is an efficient and convenient way to aggregate data. It accepts a column as input and retrieves an array of values from all the rows in a group. It is useful for combining multiple values into a single data structure, such as when aggregating data from multiple rows.

This blog will explain what exactly the **ARRAY_AGG()** is and how to use it in Postgres. In this regard, the below-provided concepts will be covered in this post:

How to Use ARRAY_AGG() Function in Postgres? **  
**\- Example 1: How to Use ARRAY_AGG() Function on a Single Column?  
\- Example 2: How to Use ARRAY_AGG() Function With ORDER BY Clause in Postgres?  
\- Example 3: How to Use ARRAY_AGG() Function on Multiple Columns?  
\- Example 4: How to Use ARRAY_AGG() Function With WHERE Clause?  
\- Example 5: How to Use ARRAY_AGG() Function on Multiple Tables?

 **How to Use ARRAY_AGG() Function in Postgres?**

The ARRAY_AGG() function in Postgres is an aggregate function that combines several values into a single array. It takes a column as input and returns an array of values from all the rows in the specified group:
    
    
    ARRAY_AGG(expression [ORDER BY [sort_expression|col_name {ASC | DESC}], [....]);

 **Example 1: How to Use ARRAY_AGG() Function On a Single Column?**

We have created a sample table named “employee_info” that contains the following data:

Let’s exercise the ARRAY_AGG() function to get the list of employee names:
    
    
    SELECT ARRAY_AGG(e_name)
    FROM employee_info;

The output shows that the ARRAY_AGG() function retrieves an array of employee names.

 **Example 2: How to Use ARRAY_AGG() Function With ORDER BY Clause?**

In the previous example, we witnessed that the ARRAY_AGG() function retrieves an array of employee names. However, the array elements were not sorted in any order. To sort the array elements ascending or descending, we need to use the ORDER BY clause with the ARRAY_AGG() function:
    
    
    SELECT ARRAY_AGG(e_name
    ORDER BY e_name DESC)
    FROM employee_info;

This time the ARRAY_AGG() function retrieves an array of employee names from the employee_info table in descending order.

 **Example 3: How to Use the ARRAY_AGG() Function on Multiple Columns?**

We will implement the **ARRAY_AGG()** function on “e_id” and “e_name” columns using the concatenation operator:
    
    
    SELECT ARRAY_AGG(e_id || ' - ' || e_name)
    FROM employee_info;

This is how the ARRAY_AGG() function works on multiple columns.

 **Example 4: How to Use ARRAY_AGG() Function With WHERE Clause?**

To get a filtered array using ARRAY_AGG() function, you must use the WHERE clause as follows:
    
    
    SELECT ARRAY_AGG(e_id ||' - '|| e_name ||' - ' || e_email)
    FROM employee_info
    WHERE e_id > 3;

This time the **ARRAY_AGG()** function retrieves an array of only those employees whose id is greater than 3.

 **Example 5: How to Use ARRAY_AGG() Function on Multiple Tables?**

We have created two sample tables: “employee_info” and “department_info”. Both these tables are linked with each other via a foreign key. The below snippets illustrate the table’s content:

The department_info table contains the following data:

Suppose we want to get an array of employee ids and names based on their respective departments. For this purpose, we will use the ARRAY_AGG() function with the help of INNER JOIN, as shown in the following snippet:
    
    
    SELECT dpt_name, ARRAY_AGG(e_id ||'-' || e_name)
    FROM employee_info
    INNER JOIN department_info USING (e_id)
    GROUP BY dpt_name;

In the above code snippet:

\- Two columns are passed as the first argument to the **ARRAY_AGG()** function.  
\- The concatenation symbol is used to aggregate/combine the columns.  
\- The **INNER JOIN** joins the employee_info and department_info tables.  
\- The **GROUP BY** clause groups the table’s data with respect to the department name.

This way, you can use the ARRAY_AGG() function in Postgres.

 **Conclusion**

Data aggregation in PostgreSQL is made easy and efficient with ARRAY_AGG(). The ARRAY_AGG() function in Postgres is an aggregate function that combines several values into a single array. It takes a column as input and returns an array of values from all the rows in the specified group. This blog explained various use cases of the ARRAY_AGG() function using examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-array_agg-function-with-examples/)

---

# PostgreSQL TIMEZONE | Explained With Examples

> In Postgres, a time zone represents a region of the earth with a uniform standard time. Time zones allow us to convert local time to UTC or vice versa.

In Postgres, a time zone represents a region of the earth with a uniform standard time. Time zones allow us to convert local time to UTC(Coordinated Universal Time) or vice versa. Time with time zone is stored in PostgreSQL as a TIMESTAMPTZ(abbreviation of TIMESTAMP with TIMEZONE) data type, which includes time and time zone offset. Offsets show the difference between local and UTC.

This blog will explain what exactly **TIMEZONE** is and how it works in Postgres. For this purpose, the below-listed concepts will be covered in this write-up:

  * How to Get/Show Database Timezone in Postgres?
  * Postgres Supported Timezones.
  * How to Set Database Timezone in Postgres?
  * Postgres TIMEZONE() Function.
  * Date/Time Functions With Time Zone



 **How to Get/Show Database Timezone in Postgres?**

In Postgres, the “SHOW TIMEZONE” command retrieves the timezone of the current database:
    
    
    SHOW TIMEZONE;

The stated command retrieves the current timezone of the “postgres” database.

 **Postgres Supported Timezones**

In Postgres, the “ **pg_timezone_names** ” table retrieves the list of Postgres-supported timezones:
    
    
    SELECT *
    FROM pg_timezone_names;

The “ **pg_timezone_names** ” table contains all necessary details regarding Postgres-supported timezones.

 **How to Set/Change Database Timezone in Postgres?**

Use the ALTER DATABASE command with the SET TO clause to set/change the timezone of a Postgres database:
    
    
    ALTER DATABASE postgres SET TIMEZONE TO 'Africa/Abidjan';

Let’s verify the time zone alteration using the following command:
    
    
    SHOW TIMEZONE;

The time zone of the selected database has been modified to “Africa/Abidjan”.

 **Postgres TIMEZONE() Function**

Postgres offers a **timezone()** function that accepts a zone and a timestamp as arguments and converts the timestamp to some other timestamp based on the specified/given timezone:
    
    
    timezone(zone, timestamp);

Specify the “timezone” of your choice in place of the “zone” argument.

 **Example: How Does the TIMEZONE Function Work in Postgres?**

In the following code, we will pass a TIMESTAMP with a time zone to the TIMEZONE() function:
    
    
    SELECT TIMEZONE('Canada/Mountain', TIMESTAMPTZ '2020-11-11 08:30:15-08');

The input timestamp has been converted according to the specified time zone.

 **Date/Time Functions With Time Zone**

Postgres offers several date-time functions to deal with temporal data. The below-provided functions retrieve the DateTime values along with the timezone information:

\- **NOW():** Retrieves the current DateTime with timezone information.  
\- **CURRENT_TIMESTAMP:** Retrieves the timestamp value with timezone information.  
\- **TO_TIMESTAMP():** Converts a DateTime string to a timestamp. Its return type is TIMESTAMPTZ.  
\- **CURRENT_TIME** : Retrieves Current Time with Timezone information.  
\- **CLOCK_TIMESTAMP():** Retrieves the current DateTime with timezone information at which the recent transaction begins.  
\- **STATEMENT_TIMESTAMP():** Retrieves the current DateTime with timezone information at which the current statement executes.  
\- **TRANSACTION_TIMESTAMP():** It works the same way as the NOW() function.  
\- **DATE_TRUNC():** Truncates/trims unnecessary values from the DateTime and retrieves a result with specific precision. Its return type is TIMESTAMP with TIMEZONE.

Let’s comprehend how these functions work via the following examples.

 **Example 1: Get Today’s DateTime With Timezone**

In the below code, we will show how the NOW() function work in Postgres:
    
    
    SELECT NOW();

The output shows that the **NOW()** function retrieves the current DateTime with a timezone.

 **Example 2: Get Today’s Time With Timezone**

In the below code, we will show how the CURRENT_TIME function works in Postgres:
    
    
    SELECT CURRENT_TIME;

The output shows that the “ **CURRENT_TIME** ” function retrieves the time with the timezone.

 **Conclusion**

A time zone in PostgreSQL is a region that follows a specific set of rules for handling time. It allows us to store and display date and time values with a specific offset from UTC (Coordinated Universal Time). It allows us to accurately convert the date and time values to other time zones across different regions. This post presented a comprehensive guide on Postgres TIME ZONE with a practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/postgresql-timezone-explained-with-examples/)

---

# How to Get the Current Date and Time With Time Zone in PostgreSQL

> In Postgres, the NOW() and CURRENT_TIMESTAMP functions are used to fetch the current date and time with the time zone offset.

PostgreSQL provides built-in functions for getting the current DateTime with the time zone, such as NOW() and CURRENT_TIMESTAMP. The NOW() function doesn’t accept any argument; however, the CURRENT_TIMESTAMP function can accept an optional argument named “precision”. Both these functions retrieve today’s DateTime with a timezone offset.

This post demonstrates various examples to illustrate the usage of the NOW() function and CURRENT_TIMESTAMP function in Postgres.

 **How to Get Current DateTime(With Timezone) Using Postgres NOW() Function?**

It is a built-in DateTime function that retrieves today’s DateTime with a timezone offset. You must use the stated with a set of parenthesis, as shown below:
    
    
    NOW();

Its return type is TIMESTAMPTZ(TIMESTAMP with TIMEZONE).

 **Example 1: How to Get Today’s DateTime Via NOW()?**

To get the current date and time with timezone offset, you must use the NOW() function with the collaboration of the Postgres SELECT query:
    
    
    SELECT NOW();

 **Example 2: How to Insert Current DateTime With Timezone into a Specific Table?**

We have created a sample table named staff_info, whose structure is described in the following snippet:

Let’s learn how to insert the Current DateTime with timezone to a table using the NOW() function:
    
    
    INSERT INTO staff_info(staff_id, staff_name, joining_date, contract_duration)
    VALUES (15, 'Anna', NOW(), '2 Years');

Let’s check out the newly inserted record using the below-provided command:
    
    
    SELECT * FROM staff_info;

The current date-time and the timezone offset have been inserted into the “staff_info” table.

 **Example 3: How to Set NOW() Function as the Column’s Default Value?**

Use the ALTER TABLE command with ALTER COLUMN and SET DEFAULT clause followed by the NOW() function to set the current date, time, and time zone offset as the default value of a targeted column:
    
    
    ALTER TABLE staff_info
    ALTER COLUMN joining_date SET DEFAULT NOW();

Describe the “staff_info” table to see its structure:
    
    
    \d staff_info;

The output snippet clearly states that the “NOW()” function has been set as the default value for the “joining_date” column. Let’s insert a new record into the “staff_info” table:
    
    
    INSERT INTO staff_info(staff_id, staff_name, staff_designation, contract_duration)
    VALUES (12, 'Henry', 'Author', '2 Years');

The below snippet shows the newly inserted record:
    
    
    SELECT * FROM staff_info;

 **How to Get Current DateTime(With Timezone) via Postgres CURRENT_TIMESTAMP Function?**

The CURRENT_TIMESTAMP function may or may not accept a precision parameter, which determines the fractional points for the seconds' field.
    
    
    CURRENT_TIMESTAMP(precision);

Skipping the precision parameter will retrieve the seconds with full available precision. The return type of the stated function is “TIMESTAMPTZ(TIMESTAMP WITH TIME ZONE)”.

 **Example 1: How to Get Today’s DateTime Via CURRENT_TIMESTAMP?**

A SELECT command can be used to get the current date and time with the timezone using the CURRENT_TIMESTAMP function.
    
    
    SELECT CURRENT_TIMESTAMP;

 **Example 2: How to Find Current DateTime(with timezone) With Specific Precision?**

You can specify the precision value as an argument to the CURRENT_TIMESTAMP() function, as shown in the following snippet:
    
    
    SELECT CURRENT_TIMESTAMP(2);

The output signifies the results for the CURRENT_TIMESTAMP function with and without precision parameters.

 **Note:** You can use the CURRENT_TIMESTAMP function as a column’s default value.

 **Conclusion**

In Postgres, the **NOW()** and **CURRENT_TIMESTAMP** functions are used to fetch the current date and time with the time zone offset. The return type of these functions is “TIMESTAMP with TIMEZONE” or “TIMESTAMPTZ”. The NOW() function doesn’t accept any argument; however, the CURRENT_TIMESTAMP function can accept an optional argument named “precision”, which determines the fractional points for the seconds' field. This blog considered various examples to show the usage of Postgres’ NOW() and CURRENT_TIMESTAMP functions.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-current-date-and-time-with-time-zone-in-postgresql/)

---

# How to Get the Current Time Without Time Zone in PostgreSQL

> Postgres offers a DateTime function named LOCALTIME that retrieves the current time without a timezone. It may or may not accept an optional argument named “pr…

PostgreSQL provides several DateTime functions to get the current date or time. For instance, the **NOW()** function is used to get the current DateTime; the **CURRENT_DATE** function is used to get the current date only; the **CURRENT_TIME** function retrieves the current time with time zone offset, etc. Similarly, to get the current time without time zone offset, the **LOCALTIME** function is used in Postgres.

This blog will guide you on getting the current time in Postgres without the time zone.

 **Getting the Current Time Without Timezone in Postgres?**

The LOCALTIME function may take an optional precision parameter known as the “precision”, as shown in the following syntax:
    
    
    LOCALTIME(precision);

The “precision” parameter determines the fractional points for the seconds' field. Skipping the precision parameter will retrieve the time with full available precision. The return type of the stated function is “TIME(TIME WITHOUT TIME ZONE)”.

 **Example 1: How to Get Current Time in PostgreSQL Without Time Zone Via LOCALTIME?**

Use the LOCALTIME function with the help of a SELECT statement to fetch the current time without the time zone:
    
    
    SELECT LOCALTIME;

The output shows that the stated function retrieves the time(at which the transaction begins) without a timezone.

 **Example 2: How to Get Current Time With Specific Precision in PostgreSQL?**

Pass an integer as an argument to the LOCATIME function to get the time(seconds) up to specified precision:
    
    
    SELECT LOCALTIME, LOCALTIME(2);

The output shows the difference between the local time without precision parameter and with precision parameter.

 **Example 3: How to Set the Current Time Without Time Zone As the Column Default Value?**

We have created a sample table named “flight_details” with three columns, as shown in the below snippet:

Let’s add the current time without the time zone as the default value of the “arrival_time” column:
    
    
    ALTER TABLE flight_details
    ALTER COLUMN arrival_time SET DEFAULT LOCALTIME;

The selected table has been altered successfully. Let’s add a new record to the “flight_details” table:
    
    
    INSERT INTO flight_details(flight_num, departure_time)
    VALUES (1001, '07:35:40');

A new record has been inserted into the flight_details table. We didn’t specify any value for the “arrival_time” column. Let’s execute the SELECT query to see what the output says:
    
    
    SELECT * FROM flight_details;

The output demonstrates that postgres assigned the current time(without time zone) to the arrival_time column. This way, you can set the current time without the time zone as the default value of a specific column.

 **Conclusion**

Postgres offers a DateTime function named **LOCALTIME** that retrieves the current time without a timezone. The LOCALTIME function may or may not accept an optional argument named “precision”, which determines the decimal places for the seconds' field. Skipping the precision parameter will retrieve the time with full available precision. The return type of the stated function is TIME(TIME WITHOUT TIME ZONE). This Postgres blog presented a comprehensive guide on getting the current time without time zone information in PostgreSQL using the **LOCALTIME** function.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-current-time-without-time-zone-in-postgresql/)

---

# ILIKE Operator: Case-Insensitive Pattern Matching in PostgreSQL

> In Postgres, the ILIKE operator performs the case-insensitive pattern matching on a string. Two wildcards are used to specify a pattern in ILIKE operator: an u…

In Postgres, the LIKE operator performs the case-sensitive pattern matching on a specified string. So, if you want to perform the case-insensitive pattern matching on a string, then you can use the ILIKE operator instead of the LIKE operator.

In PostgreSQL, the ILIKE operator allows us to perform the case-insensitive pattern matching in SELECT, UPDATE, and DELETE statements. It can be used in the WHERE clause to filter the data based on case-insensitive pattern matching.

This blog explains how to perform case-insensitive pattern matching in postgres with suitable examples.

 **Case-Insensitive Pattern Matching in PostgreSQL Via ILIKE Condition/Operator**

The syntax for using the ILIKE operator is presented in the below snippet:
    
    
    targeted_string ILIKE pattern;

Two wildcards are used in Postgres to specify a particular pattern, i.e., an underscore “_” and a percent sign “%”. The underscore wildcard allows us to perform the pattern matching on a single character, while the percent sign is used to perform pattern matching on a sequence of characters.

Let’s learn this concept practically.

 **Example 1: How to Perform Case-insensitive Pattern Matching on a Single Column?**

A sample table named staff_info has already been created:

Suppose we have to fetch all those employees whose names start with the letter “j”:
    
    
    SELECT staff_name, staff_designation 
    FROM staff_info
    WHERE staff_name ILIKE 'j%';

The pattern “j%” represents that fetch all those strings that start with the letter “j” followed by anything:

We searched for the small “j”; however, the ILIKE operator retrieves the names irrespective of the lowercase. It proves that the ILIKE operator performs case-insensitive pattern matching.

 **Example 2: How to Perform Case-insensitive Pattern Matching on Multiple Columns?**

Find all those employees whose name starts with “j” and whose designation is “author”:
    
    
    SELECT staff_name, staff_designation 
    FROM staff_info
    WHERE staff_name ILIKE 'j%' AND staff_designation ILIKE 'author';

The above query retrieves all those authors whose name starts with “j”:

The output proved that the “ILIKE” operator performed the case-insensitive matching.

 **Example 3: How to Perform Case-insensitive Pattern Matching Using Underscore Wildcard?**

All employees whose names contain "I" as a second letter will be listed using the following statement:
    
    
    SELECT staff_name, staff_designation 
    FROM staff_info
    WHERE staff_name ILIKE '_I%';

The output shows that the ILIKE operator retrieves the records irrespective of the case.

 **Conclusion**

In PostgreSQL, the ILIKE operator performs the case-insensitive pattern matching on a string. The ILIKE operator is often used in the WHERE clause to filter the data based on case-insensitive pattern matching. In Postgres, Two wildcards are used to specify a particular pattern in ILIKE operator, i.e., an underscore “_” and a percent sign “%”. This blog demonstrated a comprehensive guide on performing case-insensitive pattern matching in Postgres.

---
[View this page online](https://www.commandprompt.com/education/ilike-operator-case-insensitive-pattern-matching-in-postgresql/)

---

# How to Get the Current Date in PostgreSQL

> PostgreSQL provides a Date function named CURRENT_DATE, which retrieves the current/today’s date. It retrieves the date in “YYYY-MM-DD” format.

PostgreSQL supports several DateTime functions to work with date and time. One such function is **CURRENT_DATE** which retrieves the current/today’s date. It retrieves the date based on the system on which PostgreSQL is running. It stores and retrieves the date in “ **YYYY-MM-DD** ” format.

This post presents a thorough guide to getting the current date in Postgres via the **CURRENT_DATE** function.

 **Getting Current Date Using Postgres CURRENT_DATE Function**

The CURRENT_DATE function doesn’t take any argument, as shown in the following syntax:
    
    
    CURRENT_DATE;

The return type of the stated function is “DATE”. The stated function retrieves the date in “YYYY-MM-DD” format where “YYYY” indicates the 4-digit year, “MM” shows a 2-digit month, and “DD” represents a 2-digit day.

 **Example 1: How to Get Today’s Date Via CURRENT_DATE?**

To get the current date, all you need to do is execute the CURRENT_DATE function with the aid of the Postgres SELECT command:
    
    
    SELECT CURRENT_DATE;

This way, you can get the current date in Postgres.

 **Example 2: How to Set Today’s Date as a Column Default Value?**

We have created a sample table named “staff_info”, whose content is depicted in the following snippet:

Suppose we want to set the CURRENT DATE as the DEFAULT type of the “joining_date” column. To do that, the ALTER TABLE statement will be executed with ALTER COLUMN and SET DEFAULT clause as follows:
    
    
    ALTER TABLE staff_info
    ALTER COLUMN joining_date SET DEFAULT CURRENT_DATE;

The selected table has been altered successfully. The below statement shows how the CURRENT_DATE function works when it is set as the default value for a column:
    
    
    INSERT INTO staff_info(staff_id, staff_name, staff_designation, contract_duration)
    VALUES (11, 'Shane', 'author', '1 Year');

A new record has been successfully inserted into the staff_info table. We didn’t specify any value for the “joining_date” column in the above query. However, Postgres will, by default, assign the current date to the “joining_date” column. The below provided “ **SELECT *** ” command demonstrates the data of the staff_info table:
    
    
    SELECT * FROM staff_info;

The output snippet shows that the current date has been assigned to the “joining_date” column. This way, you can set the current date as the default value of a specific column.

 **Conclusion**

PostgreSQL provides a Date function named **CURRENT_DATE,** which retrieves the current/today’s date. It retrieves the date in “YYYY-MM-DD” format where “YYYY” indicates the 4-digit year, “MM” shows the 2-digit month, and “DD” represents the 2-digit day. It returns the date according to the system/machine that Postgres is running on. This Postgres blog presented a practical guide on getting the current date in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-current-date-in-postgresql/)

---

# How to Get the Current Time With Timezone in PostgreSQL

> PostgreSQL provides a built-in DateTime function named CURRENT_TIME that retrieves the current time with time zone offset.

PostgreSQL provides various DateTime functions to work with date and time. One such function is **CURRENT_TIME** which retrieves the current time with time zone offset. It retrieves the time based on the system on which PostgreSQL is running.

This post presents a thorough guide to getting the current time in Postgres via the **CURRENT_TIME** function.

 **Getting Current TIME With Time Zone Using Postgres CURRENT_TIME Function**

The CURRENT_TIME function may accept an optional precision argument, as shown in the following syntax:
    
    
    CURRENT_TIME(precision);

The “precision” parameter determines the decimal places for the seconds' field. Skipping the precision parameter will retrieve the seconds with full available precision. The return type of the stated function is “TIMETZ(TIME WITH TIME ZONE)”.

 **Example 1: How to Get Current Time in PostgreSQL Via CURRENT_TIME?**

To get the current time, all you need to do is execute the CURRENT_TIME function with the help of the Postgres SELECT command:
    
    
    SELECT CURRENT_TIME;

This way, you can get the current time(with timezone) in Postgres.

 **Example 2: How to Get Current Time With Specific Precision in PostgreSQL?**

In the following code, we will execute the CURRENT_TIME function with and without a precision argument:
    
    
    SELECT CURRENT_TIME, CURRENT_TIME(3);

The output shows that specifying the precision parameter retrieves the seconds up to the specified precision value.

 **Example 3: How to Set the Current Time As the Column Default Value?**

Let’s create a table named and specify the CURRENT_TIME as the default value for the “arrival_time” column:
    
    
    CREATE TABLE flight_details(
    filghtNum INT, 
    departure_time TIME, 
    arrival_time TIME DEFAULT CURRENT_TIME
    );

The below statement shows how the CURRENT_TIME function works when it is set as the default value of a specific column:
    
    
    INSERT INTO flight_details (flight_num, departure_time)
    VALUES (0000, '10:45:00');

A new record has been successfully inserted into the flight_details table. We didn’t specify any value for the “arrival_time” column; however, Postgres will, by default, assign the current time to the “arrival_time” column. The below provided “ **SELECT *** ” command illustrates the data of the flight_details table:
    
    
    SELECT * FROM flight_details;

The output snippet shows that the current time has been assigned to the “arrival_time” column. This way, you can set the current time as the default value of a specific column.

 **Conclusion**

PostgreSQL provides a time function named **CURRENT_TIME** that retrieves the current time with time zone offset. The CURRENT_TIME function may accept an optional “precision” argument, which determines the decimal places for the seconds' field. Skipping the precision parameter will retrieve the seconds with full available precision. The return type of the stated function is TIMETZ(TIME WITH TIME ZONE). This Postgres blog presented a practical guide on getting the current time in PostgreSQL using the CURRENT_TIME function.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-current-time-with-timezone-in-postgresql/)

---

# How to Get the Current Date and Time Without Time Zone in PostgreSQL

> In Postgres, a built-in function named “LOCALTIMESTAMP” is used to get today’s Date and Time without timezone information.

In PostgresQL, the NOW() function is used to get the current DateTime along with the TIMEZONE offset. But the query is, what if we don't need the timezone? How do we get the current DateTime in such a case? Well! To deal with such scenarios, a built-in function named “ **LOCALTIMESTAMP** '' is used in Postgres. It retrieves today’s DateTime without a timezone offset.

This blog shows different examples of how to get the current DateTime without the Timezone information.

 **How to Use LOCALTIMESTAMP Function in Postgres?**

The LOCALTIMESTAMP function may or may not accept a precision parameter. The “precision” parameter determines the decimal places for the seconds' field:
    
    
    LOCALTIMESTAMP(precision);

Skipping the precision parameter will retrieve the seconds with full available precision. The return type of the stated function is “TIMESTAMP(TIMESTAMP WITHOUT TIME ZONE)”.

 **Example 1: How to Get Today’s DateTime Via LOCALTIMESTAMP?**

To get the current date and time, you must use the LOCALTIMESTAMP function with the collaboration of the Postgres SELECT command:
    
    
    SELECT LOCALTIMESTAMP;

The output retrieves the current DateTime without a time zone.

 **Example 2: How to Find Current DateTime(without timezone) With Specific Precision?**

You can pass the precision as an argument to the **LOCALTIMESTAMP** function. For instance, in the below snippet, “0” is passed as a precision:
    
    
    SELECT LOCALTIMESTAMP(0);

The output snippet shows that the stated function retrieves the current date and time without fractional seconds.

 **Example 3: How to Set Current DateTime as a Column Default Value Using LOCALTIMESTAMP Function?**

We have created a sample table named “flight_details”, whose details are listed in the following snippet:
    
    
    \d flight_details;

Suppose we want to add the current date and time without the timezone as the “next_arrival” column's default value. For this, use the ALTER TABLE command with ALTER COLUMN and SET DEFAULT clause followed by the LOCALTIMESTAMP:
    
    
    ALTER TABLE flight_details
    ALTER COLUMN next_arrival SET DEFAULT LOCALTIMESTAMP;

Let’s describe the table one more time to see whether the changes have been made to the respective column or not:
    
    
    \d flight_details;

The output snippet shows that the LOCALTIMESTAMP function is the default value of the “next_arrival” column. Let’s insert a new record to the flight_details column to see how the default value works in Postgres:
    
    
    INSERT INTO flight_details(flight_num, departure_time, arrival_time)
    VALUES (1001, '07:35:40', '09:35:45');

Let’s check out the newly inserted record via the “SELECT *” command:
    
    
    SELECT * FROM flight_details;

The current date and time are default inserted into the “next_arrival” column.

 **Note:** If you want the current date and time, with timezone offset, then use the CURRENT_TIMESTAMP or NOW() function instead of the LOCALTIMESTAMP function.

 **Conclusion**

In Postgres, a built-in function named “LOCALTIMESTAMP” is used to get today’s Date and Time without timezone information. The LOCALTIMESTAMP function may or may not accept a precision parameter, which determines the decimal places for the seconds' field. Skipping the precision parameter will retrieve the seconds with full available precision. The return type of the stated function is “TIMESTAMP(TIMESTAMP WITHOUT TIME ZONE)”. This post explained the usage of the LOCALTIMESTAMP function with suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-the-current-date-and-time-without-time-zone-in-postgresql/)

---

# PostgreSQL STRING_AGG() Function With Examples

> The STRING_AGG() function in Postgres is used to concatenate multiple strings into a single string, separated by a specific delimiter/separator.

PostgreSQL offers various built-in string manipulation functions. One such function is **STRING_AGG()** which comes up with the ease and efficiency of aggregating multiple strings into a single. It is one of the aggregate functions that Postgres supports and is widely used to concatenate the list of strings.

This blog will explain what exactly the **STRING_AGG()** is and how to use it in Postgres. For this purpose, the below-listed concepts will be covered in this post:

\- How to Use STRING_AGG() Function in Postgres?  
\- Generating a Comma-separated List of Values Using STRING_AGG() Function.  
\- Generating a Comma-Separated List of Values From Multiple Columns.

 **How to Use STRING_AGG() Function in Postgres?**

The STRING_AGG() function in Postgres is used to concatenate multiple strings into a single string, separated by a specific delimiter/separator. The syntax for using STRING_AGG() is:
    
    
    STRING_AGG(col_name/expression, delimiter[order_by_clause]);

Here, in the above syntax,

\- The “col_name/expression” represents the column whose values you want to concatenate.  
\- The delimiter represents the separator between each value, such as “ **,** ”, “ **-** ”, etc.  
\- The “order_by_clause” specifies the order in which the values should be aggregated.

 **Generating a Comma-separated List of Values Using STRING_AGG() Function**

To generate a comma-separated list of values, you need to pass an expression and a comma as arguments to the STRING_AGG() function.

 **Example: How to Use STRING_AGG() Function on a Single Column?**

We have created a sample table named “staff_info” that contains the following data:

Let’s use the **STRING_AGG()** function to generate a list of comma-separated values for the “ **staff_info** ” table:
    
    
    SELECT staff_designation, STRING_AGG(staff_name, ',')
    FROM staff_info 
    GROUP BY staff_designation;

The above example uses the **STRING_AGG()** function to get a comma-separated list of employee names. The GROUP BY clause is used to group the data with respect to designation:

The output proves that the STRING_AGG() function retrieves the comma-separated list of employees’ names.

 **Generating a Comma-Separated List of Values From Multiple Columns**

The **STRING_AGG()** function accepts only two arguments, an expression, and a separator. So if you want to aggregate multiple columns using STRING_AGG(), then you must concatenate the column names in the first argument and specify the separator in the second argument. Use the concatenation symbol “||” to concatenate various columns. Alternatively, multiple **STRING_AGG()** functions can be used in a single query to generate a comma-separated list of values from various columns.

 **Example 1: STRING_AGG() Function on Multiple Columns Using Concatenation Operator**

We have created two sample tables named “employee_info” and “department_info”, whose details are shown in the following snippets:

The department_info table contains the following data:

Now we will learn how to use the STRING_AGG() function to multiple columns:
    
    
    SELECT dpt_name,
    STRING_AGG (e_id ||' ' || e_name, ', ') AS emp_details
    FROM employee_info
    INNER JOIN department_info USING (e_id)
    GROUP BY dpt_name;

In the above code:

\- Multiple columns are passed as the first argument to the **STRING_AGG()** function.  
\- The concatenation symbol combines multiple columns, and the comma “,” is used as a separator/delimiter.  
\- The **INNER JOIN** joins the employee_info and department_info tables.  
\- The **GROUP BY** clause groups the table’s data with respect to the department name.

This is how you can use the STRING_AGG() function to generate a list of comma-separated values from different columns.

 **Example 2: Using Multiple STRING_AGG() Functions on Multiple Columns**

In the following example, we will show you how to use multiple STRING_AGG() functions on multiple tables to generate a list of comma-separated values from different columns:
    
    
    SELECT dpt_name,
    STRING_AGG (e_name, ', '), STRING_AGG (e_email, ', ')
    FROM employee_info
    INNER JOIN department_info USING (e_id)
    GROUP BY dpt_name;

The output authenticates the working of the STRING_AGG() function.

 **Conclusion**

PostgreSQL offers a **STRING_AGG()** function, which comes up with the ease and efficiency of aggregating multiple strings into one. It accepts two arguments: an expression(list of strings) and a separator; consequently, it concatenates the given set of strings into a single string, separated by a specified delimiter/separator. This post explained the usage of the STRING_AGG() function with suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-string_agg-function-with-examples/)

---

# How to Create a View in PostgreSQL

> In Postgres, the CREATE VIEW statement defines a new view based on the selected table(s). To create a view from several tables, use the CREATE VIEW statement w…

In Postgres, a view is not a real table(not physically materialized) but a pseudo-table. However, it can be accessed as an ordinary/real table using a SELECT statement. In PostgreSQL, a VIEW can be defined/created based on single or multiple tables or from other views. For this purpose, the **CREATE VIEW** statement is used in Postgres.

This post demonstrates how to create a view in Postgres using suitable examples.

 **How to Create a View in Postgres?**

Use the below-provided syntax to create a new view in Postgres:
    
    
    CREATE[OR REPLACE] VIEW viewName AS
    SELECT col_list
    FROM tab_name
    [WHERE condition];

Let’s comprehend the above syntax line-by-line:

\- OR REPLACE is an optional clause/parameter that replaces the already existing view.  
\- Skipping the OR REPLACE parameter may cause an error if the view already exists.  
\- Specify the column names in place of the “col_list” parameter to add the columns of your choice to the view.  
\- tab_name represents a table based on which the view will be created.  
\- WHERE is an optional clause that specifies a particular condition(s).

Let’s put these concepts into practice.

 **Example 1: Creating a View**

The below snippet shows the content of the base table:

Suppose we want to create a view from the “staff_info” table. For this purpose, we will use the following statement:
    
    
    CREATE VIEW staff_view AS
    SELECT staff_id, staff_name, staff_designation
    FROM staff_info
    WHERE staff_id <= 5;

The “ **CREATE VIEW** ” message in the output window demonstrates that the “staff_view” has been created. Let’s verify it via the “SELECT *” command:
    
    
    SELECT * FROM staff_view;

 **Example 2: Creating an Already Existing View**

Trying to create an already existing view will throw an error, as shown in the following snippet:

To avoid this error, you need to execute the “CREATE VIEW” statement with the “OR REPLACE” parameter:
    
    
    CREATE OR REPLACE VIEW staff_view AS
    SELECT staff_id, staff_name, staff_designation
    FROM staff_info
    WHERE staff_id <= 8;

The output shows that this time the CREATE VIEW command executed successfully. To verify the view’s creation/modification, you must execute the following command:
    
    
    SELECT * FROM staff_view;

The “staff_view” with desired records has been created successfully.

 **Example 3: Creating/Defining a View From Multiple Postgres Tables**

We have two sample tables named “employee_info” and “department_info”. The below snippet demonstrates the content of the “emp_info” table:

The content of the “department_info” table is shown in the following snippet:

Let’s learn how to create a view from multiple tables:
    
    
    CREATE VIEW emp_data_view AS
    SELECT employee_info.e_id, e_name, dpt_name
    FROM employee_info
    INNER JOIN department_info
    ON employee_info.e_id = department_info.e_id;

In the above snippet, the INNER JOIN is used with the CREATE VIEW statement to create a view from multiple tables:

The “ **CREATE VIEW** ” message in the output window signifies that the desired view has been created from multiple tables. Let’s execute the “SELECT *” command to fetch the data from the “emp_view_data”:

This way, you can use the CREATE VIEW statement to create/define a view from one or more tables.

 **Conclusion**

In PostgreSQL, the **CREATE VIEW** statement defines a new view based on the selected table(s). To create a view from several tables, use the CREATE VIEW statement with INNER JOIN. Creating an existing view will throw a “relation already exists” error. To avoid such an error, use the “OR REPLACE” parameter with the CREATE VIEW statement. This Postgre blog presented different examples to illustrate how to create a view in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-view-in-postgresql/)

---

# How to List Views in PostgreSQL

> In PostgreSQL, the “\d”, “\dv”, “\dv+” commands, “information_schema.views”, etc., are used to list all the views from a database.

Postgres offers several commands and queries to list all the views from a database, such as the “\d”, “\dv”, “\dv+” commands, “information_schema.views”, etc. Moreover, the pgAdmin can also be used to access and display all the views of any Postgres database.

This post illustrates how to list all views of a specific database using SQL Shell and pgAdmin. The content of this Postgres post is organized as follows:

  * Method 1: How to List Views Using “\d” Command?
  * Method 2: How to List Views Using “\dv” or “\dv+” Command?
  * Method 3: How to List Views Using “information_schema.views”?
  * Method 4: How to List Views Using pgAdmin?



 **Method 1: How to List Views Using “\d” Command?**

Launch the SQL Shell, specify the login details, and use the “\d” command to get the list of available tables, views, sequences, etc.:
    
    
    \d

The output shows that the “\d” command retrieves the list of relations, including views and tables.

 **Method 2: How to List Views Using “\dv” or “\dv+” Command?**

Alternatively, you can use the “\dv” command to get the list of Postgres views. It will retrieve the list of views only(excluding tables, sequences, etc.):
    
    
    \dv;

The output shows the list of available views. Execute the “\dv+” command to get the views’ list with more details like size, persistence, etc.:
    
    
    \dv+;

The targeted command returns the list of views along with persistence, size, and description.

 **Method 3: How to List Views Using “information_schema.views”?**

Use the “information_schema.views” with the “SELECT” statement to get the list of views in Postgres. You can execute this command from any interface, like psql or pgAdmin.
    
    
    SELECT table_schema AS schema_name, table_name AS view_name
    FROM information_schema.views
    WHERE table_schema != 'information_schema' AND table_schema != 'pg_catalog';

The “information_schema.views” command retrieves all the views from the user-defined schemas.

 **Method 4: How to List Views Using pgAdmin?**

You can also list all the views of a specific database using pgAdmin. For this purpose, open the pgAdmin, provide the login details, navigate to the “Databases” tab and click on the database of your choice to expand it:

Click on “Schemas” and select the schema of your choice; by default, views are stored in the “public” schema. So, click on the “public” schema and then click on the “Views” to see the available views:

Finally, you can see the list of views under the “Views” tab.

 **Conclusion**

In PostgreSQL, the “\d”, “\dv”, “\dv+” commands, “information_schema.views”, etc., are used to list all the views from a database. pgAdmin can also be used to display all the views of a Postgres database. To get the views list with more details like size, persistence, etc., use the “\dv+” command. This blog considered various examples to demonstrate how to list views in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-list-views-in-postgresql/)

---

# PostgreSQL ALTER VIEW Statement With Examples

> In Postgres, the ALTER VIEW command modifies the views’ definition, such as setting the column&#x27;s default value, changing the view’s owner, renaming a view, etc…

In Postgres, the **ALTER VIEW** statement is used to modify/alter the views’ definition. It allows us to modify the auxiliary properties of a view. Using the **ALTER VIEW** statement, you can set or drop the default value of a column, change the view’s owner, rename a view, etc. However, to execute the **ALTER VIEW** command, you must own the targeted view.

This blog illustrates several examples to showcase the usage of the Postgres ALTER VIEW statement. For this purpose, the below-mentioned topics will be covered in this blog:

  * How to Rename a VIEW?
  * How to Rename the VIEW’s Columns?
  * How to Change the VIEW’s Owner?
  * How to Set Default Value for a VIEW’s Column?
  * How to Remove Default Value From a VIEW’s Column?



 **How to Rename a VIEW?**

Let’s execute the “\dv” command to describe the list of views:
    
    
    \dv;

Suppose we want to rename the “staff_view” to “emp_view”. To do that, we use the “ALTER VIEW” statement as follows:
    
    
    ALTER VIEW staff_view
    RENAME TO emp_view;

Let’s execute the “\dv” command to get the list of available views:
    
    
    \dv;

The output signifies that the “staff_view” has been renamed “emp_view”.

 **How to Rename the VIEW’s Columns?**

Let’s execute the “\d” command followed by the view’s name to see the view’s columns:
    
    
    \d emp_view;

Suppose we need to rename the “staff_name” column to “emp_name”. For this, use the “ALTER VIEW” command with the “RENAME COLUMN” clause:
    
    
    ALTER VIEW emp_view
    RENAME COLUMN staff_name TO emp_name;

Let’s check the view’s columns using the “\d” command:
    
    
    \d emp_view;

The output snippet clarifies that the “staff_name” column has been renamed “emp_name”.

 **How to Change the VIEW’s Owner?**

Let’s execute the “\dv” command followed by the view’s name to describe the view’s details:
    
    
    \dv emp_view;

The above snippet shows that the owner of the “emp_view” is “postgres”. Let’s change it to “cp_user”:
    
    
    ALTER VIEW emp_view
    OWNER TO cp_user;

Specify the name of the user/role in place of “cp_user”:

Let’s execute the “\dv” command followed by the view’s name to check the view’s owner:
    
    
    \dv emp_view;

The output proves that the owner of the “emp_view” has been changed to “cp_user”.

 **How to Set Default Value for a VIEW’s Column?**

Firstly, let’s check the view’s columns using the “\d” command:
    
    
    \d emp_view;

Suppose we want to set the default value of the “staff_designation” column as “author”. For this, we will use the ALTER VIEW command as follows:
    
    
    ALTER VIEW emp_view
    ALTER COLUMN emp_designation SET DEFAULT;

Execute the “\d” command to see the columns’ definition:
    
    
    \d emp_view;

The output shows that a default value has been assigned to the “staff_designation” column.

 **How to Remove Default Value From a VIEW’s Column?**

Use the “ALTER VIEW” and “ALTER COLUMN” commands with the “DROP DEFAULT” clause to remove a default value from a view’s column:
    
    
    ALTER VIEW emp_view
    ALTER COLUMN staff_designation DROP DEFAULT;

Execute the “\d” command to see the columns’ definition:
    
    
    \d emp_view;

The default value has been successfully removed from the “staff_designation” column.

 **Conclusion**

In PostgreSQL, the **ALTER VIEW** command allows us to modify/alter the views’ definition. For instance, using the **ALTER VIEW** statement, you can set/drop the default value of a column, change the view’s owner, rename a view, etc. In this blog, we have demonstrated multiple examples to explain the usage of the Postgres ALTER VIEW statement.

---
[View this page online](https://www.commandprompt.com/education/postgresql-alter-view-statement-with-examples/)

---

# PostgreSQL CREATE OR REPLACE VIEW - How to Modify View’s Defining Query

> Postgres provides a “CREATE OR REPLACE VIEW” statement to create a new view or replace an existing view&#x27;s defining query. It allows us to modify the defining q…

Postgres provides a “CREATE OR REPLACE VIEW” statement to create a new view or replace an existing view's defining query. It allows us to modify the defining query of a view without dropping a view. It defines a new view if the desired view doesn’t exist already or modifies the view’s defining query if it already exists.

This blog explains how to replace the view’s definition using the “CREATE or REPLACE VIEW” statement in Postgres.

 **How to Modify Views Defining Query?**

Use the “OR REPLACE” parameter with the CREATE VIEW statement to alter the defining query of a view in Postgres:
    
    
    CREATE OR REPLACE VIEW viewName AS
    SELECT col_list
    FROM tab_name
    [WHERE condition];

Let’s comprehend the above syntax line-by-line:

\- The CREATE OR REPLACE statement will create a new view if it doesn’t exist already. While it will modify the defining query of a view if the selected view already exists.  
\- Specify the columns to be added to the view in place of “col_list”.  
\- tab_name represents a table based on which the view will be created.  
\- WHERE Clause is optional that specifies a particular condition to filter the data.

 **Example 1: Create a New View**

The following figure illustrates the sample table named “employees_details”:
    
    
    SELECT * FROM employees_details;

Now execute the following statement to create a view from the “employees_details” table:
    
    
    CREATE OR REPLACE VIEW employees_view AS
    SELECT * FROM employees_details;

Run the below-provided command to verify the view’s creation:
    
    
    SELECT * FROM employees_view;

The output shows that a view named “employees_view” has been successfully created.

 **Example 2: Modifying View’s Defining Query**

Suppose we want to replace the view’s defining query, i.e., add only those employees to the view whose experience is more than three years. For this, use the following piece of code:
    
    
    CREATE OR REPLACE VIEW employees_view AS
    SELECT * FROM employees_details
    WHERE emp_experience is > ‘3 Years’;

The above snippet uses the “OR REPLACE” parameter with the “CREATE VIEW” statement to modify the view’s defining query. The WHERE clause is used to filter the employees whose experience is more than three years:

The “CREATE VIEW” message in the output wind shows that the selected view has been replaced/modified. You can verify the view’s content via the “SELECT *” command:
    
    
    SELECT * FROM employees_view;

This way, you can modify the view’s defining query in Postgres using the “CREATE OR REPLACE VIEW” statement.

 **Conclusion**

Use the “OR REPLACE” parameter with the “CREATE VIEW” statement to alter/modify the defining query of a view in Postgres. Trying to modify the view’s defining query without using the “OR REPLACE” statement will throw a “relation already exists” error. This Postgre blog presented several examples to illustrate how to modify/replace the view’s definition using the “CREATE OR REPLACE” statement in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-modify-views-defining-query-using-postgres-create-or-replace-command/)

---

# PostgreSQL - List All Columns of a Specific Table

> In PostgreSQL, the “\d” command, “\d+” command, “information_schema”, and “pgAdmin” are used to list all columns of a table.

Postgres supports various commands and queries to list all columns of a table in your Postgres database, such as the “\d” or “\d+” commands, “information_schema”, etc. You can also use pgAdmin to access and display all columns of any Postgres table. This post demonstrates how to list all columns of a specific table using CLI (SQL Shell) and GUI (pgAdmin).

The content of this Postgres post is organized as follows:

  * Method 1: Using “\d” or “\d+” Command
  * Method 2: Using “information_schema”
  * Method 3: Using pg_Admin



 **Method 1: Using “\d” or “\d+” Command**

The “\d” command is used to describe the tables of a database. While the “\d+” command describes the Postgres tables in detail. You can use the “\d” or “\d+” command followed by the table name to get the list of all columns of the specific table. For instance, the below command will show the column names of a user-defined table named “staff_info”:
    
    
    \d staff_info;

The output shows that the “\d” command retrieves the column names of the “staff_info” table.

 **Method 2: Using information_schema**

Alternatively, you can use the “ **information_schema** ” with the help of the “ **SELECT** ” statement to get the column names of a specific table:
    
    
    SELECT column_name, data_type
    FROM information_schema.columns
    WHERE table_schema = 'public' AND table_name = 'staff_info';

The above snippet shows that the “information_schema” retrieves all the columns of the “staff_info” table.

 **Method 3: Using pg_Admin**

You can also list all columns of a specific table using GUI/pgAdmin. To do that, open the pgAdmin, provide the login information, navigate to the “Databases” tab and click on the database of your choice to expand it:

Now click on “Schemas” and select the schema of your choice; by default, your tables are stored in the “public” schema. So, click on the “public” schema and then click on the “Tables” to see the available tables:

Now, click on the targeted table, and then select the “columns” tab to expand it:

Finally, you can see all the column names of the selected table under the “Columns” tab.

 **Conclusion**

In PostgreSQL, the “\d” command, “\d+” command, “information_schema”, and “pgAdmin” are used to list all columns of a table. You can use the “\d” or “\d+” command followed by the table name to get the list of all columns of the specific table along with some other necessary details. While you can use the “information_schema” to get all the information of the selected table, such as column names, data types, constraints, etc. This post explained how to list all columns of a Postgres table using practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/postgresql-list-all-columns-of-a-specific-table/)

---

# PostgreSQL: Listing and Switching Databases in psql

> “\List”, “\l”, and “pg_database” is used in SQL Shell to get the database list. While to switch databases in SQL Shell, the “\c” and “\connect” commands are us…

Listing and switching databases are core concepts in any DBMS. For example, if you want to perform some tasks on the existing databases, you must know the names of the respective databases. However, remembering all databases' names is impossible for a human being. Therefore different databases adopt different approaches to reveal the list of available databases.

For instance, Postgres offers various built-in commands for listing databases, such as “\l”, “\list”, “pg_database”, etc. Once you get the list of databases, you can switch to any database of your choice using the “\c” or “\connect” command.

This blog post illustrates how to list and switch databases in SQL Shell (psql) via practical demonstration.

 **PostgreSQL: List Databases in SQL Shell(psql)**

The “ **pg_database** ” catalog, “ **\List** ”, and “ **\l** ” commands are used in Postgres to get the list of available databases. You can also use the “\ **list+** ” and “ **\l+** ” commands to get a more detailed database list, including size, tablespace, etc.

 **Example 1: List Databases in SQL Shell(psql) Using “\l” or “\list” Command**

Launch the SQL Shell, provide the login details, and execute the “\l” command to get the databases’ list:
    
    
    \l

The “\l” command retrieves seven databases, three of which(i.e., postgres, template0, and template1) are default databases, while the other four are user-defined databases. Alternatively, you can use the “\list” command to get the same functionality.

 **Example 2: Expand Output**

To get the psql output in a more readable format, you can execute the “\x” command:

The expanded display is on. Now, execute the “\l” or “\list” command to get the list of databases in the expanded display:
    
    
    \list

 **Example 3: List Databases in SQL Shell(psql) Using “pg_database” Catalog**

Alternatively, you can use the “pg_database” catalog along with the SELECT statement to show the list of available databases:
    
    
    SELECT datname FROM pg_database;

 **Example 3: List Databases in SQL Shell(psql) Using “\l+” or “\list+” Command**

To get more details regarding available databases, you need to execute the “\l+” or “\list+” command:
    
    
    \l+

 **PostgreSQL: Switch Databases in SQL Shell(psql)**

To switch databases in SQL Shell, the “\c” and “\connect” commands are used with the respective database name.

 **Example 1: Switching Database Using “\c” Command**

Specify the “\c” command followed by the database name to which you want to establish a connection:
    
    
    \c sample_db;

The output snippet shows that you are successfully switched to a database named “smaple_db”.

 **Example 2: Switching Database Using “\connect” Command**

Alternatively, you can use the “\connect” command followed by the database name to switch the databases in psql:
    
    
    \connect postgres;

The output signifies that the “\connect” command successfully switched you to the “postgres” database.

 **Conclusion**

Different built-in Postgres commands are used for listing and switching databases in SQL Shell. For instance, the “ **\List** ”, “ **\l** ” commands, and “ **pg_database** ” catalog are used in SQL Shell to get the list of available databases. The “\ **list+** ” and “ **\l+** ” commands are used to get a more detailed database list, including size, tablespace, etc. To switch databases in SQL Shell, the “\c” and “\connect” commands are used with the respective database name. This blog post presented a detailed guide on how to list and switch databases in SQL Shell (psql) via practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/postgresql-listing-and-switching-databases-in-psql/)

---

# How to Import or Export CSVs to PostgreSQL Using pgAdmin

> This post demonstrates stepwise instructions for importing CSV to Postgres or exporting Postgres tables to CSV files using pgAdmin.

The graphical interface provides a variety of user-friendly features like easy to use, attractive interface, provides shortcuts, etc. Therefore, most beginners or intermediate users prefer graphical interfaces as compared to command-line interfaces. pgAdmin is the most popular GUI-based management tool to interact with the Postgres database. It allows us to import CSV files to Postgres tables or export Postgres tables to CSV files easily and efficiently.

This post will demonstrate how to import or export CSV files to PostgreSQL via pgAdmin.

 **Importing CSV Using pgAdmin**

To import data from a CSV file to a Postgres table via pgAdmin, users need to follow the below-provided instructions.

 **Step 1: Sample CSV File**

The below snippet shows the sample CSV file that we want to import into a Postgres table:

 **Step 2: Show Table’s Structure**

Open the pgAdmin, provide the login privileges, and execute the following command to see the table’s structure:
    
    
    SELECT * FROM staff_info;

 **Step 3: Import CSV File**

To import a CSV file via pgAdmin, right-click on the table and click on the “Import/Export Data…” tab option:

In the “Import/Export Data Window”, select the “import” option, provide the “file name/path”, specify the file format, enable the “header” option, specify the delimiter, and hit the “OK” button to import the data from a CSV file to Postgres table:

Clicking on the “OK” button will show the following message:

 **Step 4: Verify the Exported Table’s Data**

Let’s verify whether the data from CSV has been imported to the selected table or not:
    
    
    SELECT * FROM staff_info;

The output shows that data from CSV has been imported to the “staff_info” table.

 **Exporting CSV Using pgAdmin**

Users need to follow the below-provided instructions to export data from a Postgres table to a CSV file via pgAdmin.

 **Step 1: Show Table’s Data**

Open the pgAdmin, provide the login privileges, and execute the following command to see the data from the selected table:
    
    
    SELECT * FROM department_info;

 **Step 3: Export to CSV File**

To export a CSV file via pgAdmin, right-click on the table and select the “Import/Export Data…” option:

In the “Import/Export Data Window”, select the “export” option, provide the “file name”, specify the file format, enable the “header” option, specify the delimiter, and hit the “OK” button to export the data from the Postgres table to CSV file:

Clicking on the “OK” button will show the following message window:

 **Step 4: Verify the Table’s Data**

Let’s verify whether the data from the selected table has been exported to a CSV file or not. For this purpose, navigate to the directory/location where you exported the selected table:

A CSV file named “dept_data” has been exported to the specified location. Now open it to see its content:

The above snippet clarifies that the content from the “department_info” table has been successfully exported to a CSV file named “dept_data”.

 **Conclusion**

PostgreSQL allows us to import CSV files to Postgres tables or export Postgres tables to CSV files using pgAdmin. To do that, right-click on a table of your choice > click on the “import/export data…” tab > select either the “import” or “export” option > provide the “file name” > specify the file format > enable the “header” option > specify the delimiter > hit the “OK” button to import or export CSVs to Postgres via pgAdmin. This post demonstrates stepwise instructions for importing CSV to Postgres or exporting Postgres tables to CSV files using pgAdmin.

---
[View this page online](https://www.commandprompt.com/education/how-to-import-or-export-csvs-to-postgresql-using-pgadmin/)

---

# How to Import or Export CSV Files to PostgreSQL Using psql

> PostgreSQL allows us to import CSV files to Postgres tables or export Postgres tables to CSV files using SQL Shell (psql). To do that, the “\COPY” command is u…

CSV(acronym of Comma Separated Values) is a format/standard supported by various apps, such as google sheets, MS Office, etc. The CSV format is used to save data in text files. The primary use case of CSV files is transferring data from one platform to another, such as exporting data to CSV files or importing data from CSV files. PostgreSQL allows us to import CSV files to Postgres tables or export Postgres tables to CSV files using SQL Shell (psql).

This post will demonstrate how to import or export CSV files to PostgreSQL via SQL Shell or psql.

 **Importing CSV Using SQL SHELL (psql)**

The “ **\COPY** ” command is used with the collaboration of the “ **FROM** ” clause to import a CSV file to a Postgres table. The COPY command will copy all the data from the targeted file to a Postgres table.

 **Step 1: Sample CSV File**

The below snippet shows the CSV file to be imported into a Postgres table:

 **Step 2: Sample Table**

The following snippet shows the table’s structure in which we will import the CSV file:

 **Step 3: Import CSV File**

Execute the “\COPY” command from SQL Shell to import a CSV file into a Postgres table:
    
    
    \COPY employee_details(e_id, e_name, e_experience)
    FROM 'C:\Users\DELL\Downloads\employee_data.csv'
    DELIMITER ','
    CSV HEADER;

The “COPY 14” message in the output demonstrates that 14 records have been imported to the “employees_details” table from the CSV file.

 **Step 4: Verify the Working of \COPY Command**

You can verify it via the following command:
    
    
    SELECT * FROM employees_details;

This way, you can import data from a CSV file to a PostgreSQL table via SQL SHELL.

 **Exporting CSV Using the SQL SHELL (psql)**

In Postgres, the “ **\COPY** ” command is used with the collaboration of the “ **TO** ” clause to export a Postgres table to a CSV file using psql.

 **Step 1: Show Sample Table**

The following snippet shows the table’s data that we want to export to the CSV file:

 **Step 2: Export the Table’s Data to CSV File**

Execute the “\COPY” command with the “TO” clause to export a Postgres table to a CSV file:
    
    
    \COPY employee_info(e_id, e_name, e_email)
    TO 'C:\Users\DELL\Downloads\employee_data.csv'
    DELIMITER ','
    CSV HEADER;

The “COPY 6” message in the output demonstrates that six records have been exported to a CSV file named “employee_data.csv”.

 **Step 4: Verify the Working of \COPY Command**

Let’s verify whether the data from the selected table has been exported to a CSV file. To do that, navigate to the directory/location where you exported the selected table:

A CSV file named “employee_data” has been exported to the specified location. Let’s open it to see its content:

The above snippet clarifies that the content from the “employee_info” table has been successfully exported to a CSV file named “employee_data”.

 **Conclusion**

PostgreSQL allows us to import CSV files to Postgres tables or export Postgres tables to CSV files using SQL Shell (psql). The “ **\COPY** ” command is used with the collaboration of the “ **FROM** ” clause to import a CSV file to a Postgres table. In Postgres, the “ **\COPY** ” command is used with the collaboration of the “ **TO** ” clause to export a Postgres table to a CSV file using psql. This post demonstrated stepwise instructions for importing CSV to Postgres or exporting Postgres tables to CSV files using SQL Shell(psql).

---
[View this page online](https://www.commandprompt.com/education/how-to-import-or-export-csv-files-to-postgresql-using-psql/)

---

# A Quick Guide to Installing Citus for PostgreSQL

> PostgreSQL is a powerful object-relational database management system that offers a growing range of extensions to provide features and functionality unmatched…

## Introduction

PostgreSQL is a powerful object-relational database management system that offers a growing range of extensions to provide features and functionality unmatched by others. One such extension that has recently become fully open-source is Citus. Citus Data originated in 2011, was open sourced as an extension to PostgreSQL in 2016, and was acquired by Microsoft in 2019. As of June 2022, all Enterprise features have been made available for free, and Citus is now 100% open source!

Citus has the ability to transform PostgreSQL into a distributed database with the additional features of sharding, a distributed SQL engine, reference tables, and distributed tables. The distributed database consists of multiple shards of data stored in different locations, which can lead to considerable improvements in performance and data storage. Citus uses parallelism (holding more data in memory) to offer higher I/O bandwidth and significant performance improvements for multi-tenant SaaS applications, customer-facing real-time analytics dashboards, and time series workloads.

Read on to learn when you should consider using Citus and how to install it.

### Scaling

Citus has the ability to scale up operations significantly by adding worker nodes. One Citus user reports up to 80 billion updates per day with a 20-node cluster on Google Cloud with 2.4 TB of memory, 1280 cores, and 80TB of data. Another Citus user reports 700+ billion events on a 100-node cluster with 1.4 PB of data. As you can tell, the ability of Citus to scale up PostgreSQL is quite substantial!

### Multi-Tenant

One Citus use case is the multi-tenant database model, where the database serves many tenants and each tenant's data kept separate from other tenants. This notable feature of tenant isolation provides performance guarantees for large tenants. Citus not only allows full SQL coverage for the workload, but also allows scaling to 100K+ tenants. Another notable feature is the concept of reference tables, which are small tables stored on each worker node that are often referenced (hence the name) by other tables. Referencing these tables locally on a worker node helps keep resources free that would otherwise be used to request data from another node. These features allow you to scale out your tenants’ data across multiple machines and easily add more CPU, memory, and disk resources. Additionally, sharing the same database schema across multiple tenants simplifies database management and makes more efficient use of hardware resources by distributing loading across multiple instances.

Advantages with Citus for multi-tenant applications are:

  * Fast queries for all tenants
  * Sharding logic occurs in the database, not the application
  * More data is able to be held than possible in single-node PostgreSQL; 32 TB limit per table
  * Performance is maintained under high concurrency
  * Fast metrics analysis across customer base
  * Easy scaling for new customers
  * Isolation of resource usage of large and small customers



### Real-Time Analytics

Citus supports real-time queries for large datasets. These queries are common occurrences in rapidly growing event systems or systems with time series data. Examples include:

  * Analytic dashboards with sub-second response times
  * Exploratory queries on unfolding events
  * Large dataset archival and reports
  * Analyzing sessions with funnel, segmentation, and cohort queries



Citus provides these benefits due to its ability to parallelize query execution and scale linearly with the number of worker databases in a cluster. Advantages of Citus for real-time applications include:

  * Maintain sub-second responses with a growing dataset
  * Analyze new events and data as they become available in real-time
  * Parallelize SQL queries
  * Maintain performance under high concurrency
  * Fast responses to dashboard queries
  * Use one database, not a patchwork
  * Rich PostgreSQL data types and extensions



### When is Citus Not Beneficial?

Citus offers distributed functionality to PostgreSQL, but does not scale out all workloads. Citus’ design mainly benefits the use cases described above. Most environments will not be appropriate for Citus, or Citus may not offer performance improvements. Citus is not likely to benefit a single-node PostgreSQL that supports your application and you are not expecting to outgrow the limits of a single-node. If your analytics applications do not need to support a large number of concurrent users or your focus is offline analytics without real-time queries or ingestion, Citus will not likely be beneficial. Queries which return data-heavy ETL results instead of summaries also will not benefit from Citus.

#### Citus Structure

Now that we understand what Citus is used for and when it will be beneficial to use, let’s review the structure of Citus. Citus refers to machines/instances as nodes. Citus is structured to have one coordinator node and multiple worker nodes. The coordinator node contains only sparse amounts of data (mainly metadata), while the worker nodes contain the production data broken into shards that are distributed to different nodes. The amount of worker nodes needed will depend on how much production data you have (or plan on having) and/or how you want the data distributed.

#### Multi-Node Installation

Let’s install a multi-node Citus cluster. The following commands are executed on Ubuntu 22.04 LTS instances. If you do not have curl currently installed, you can do so by issuing the following command:

> sudo apt -y install curl

Next, we will add a repository to install the necessary components for the Citus extension. **The following steps should be repeated on the coordinator node and each worker node.** First, we need to add the repository with:

> curl https://install.citusdata.com/community/deb.sh | sudo bash

Now that the Citus repository is set up, we can install PostgreSQL 14 along with the latest Citus extension with one command:

> sudo apt -y install postgresql-14-citus-11.1

 **NOTE** : This will only work properly on an instance that does not already have PostgreSQL installed.

We will be able to confirm installation after we load Citus into our demo database in our next Citus blog. Stay tuned!

## Summary

We have covered many important aspects of Citus. We briefly introduced Citus, reviewed use cases, reviewed Citus structure, and installation of Citus along with PostgreSQL 14. Citus is a great fit for multi-tenant applications and real-time analytics. We also covered when Citus is not beneficial. Next in this series of blog posts is Citus Configuration.

## Video

### Related articles

  * Citus Configuration
  * Executing across Citus Nodes

---
[View this page online](https://www.commandprompt.com/education/a-quick-guide-to-installing-citus/)

---

# How to Combine Two Tables Using INNER JOIN in PostgreSQL

> Postgres provides an INNER JOIN clause to combine the records of multiple tables based on a specific condition/criteria.

PostgreSQL offers a concept of JOINS to get the data from multiple tables. In Postgres, there are several types of joins, such as **inner** join, **outer** join, **left outer** join, **right outer** join, **full outer** join, **cross** join, and **natural** join. Among them, the most frequently used is **INNER** join.

This blog will demonstrate the usage of the **INNER** joins through practical examples. So, let’s start.

 **What is the Need for JOINS in Postgres?**

Use joins if there are some common attributes between multiple tables. If we have only one table, then we can fetch its records via a select statement. However, if two or more tables depend on each other and we have to fetch the common data from such tables, then we have to use the JOINS.

For example, we have two tables: **employee_info** with three columns employee_id, employee_name, employee_email and **department_info** with three columns department_id, department_name, employee_id. Now, if we have to fetch the employee_name and his department, then in such a case, we will use a Join.

 **How to Use INNER JOIN Clause in Postgres?**

Postgres provides an **INNER JOIN** clause to combine the records of multiple tables based on a specific condition/criteria. It retrieves all records with common/matching values in both tables.

 **Syntax**

The “ **INNER JOIN** ” Clause is used with the “ **ON** ” clause to combine two tables via the inner JOIN in Postgres:
    
    
    SELECT col_list
    FROM tab_1 
    INNER JOIN tab_2
    ON tab_1.column = tab_2.column;

In the above snippet:

\- col_list represents the columns to be selected.  
\- tab_1 and tab_2 represent the tables to be joined.  
\- “tab_1.column = tab_2.column” represents the matching/common columns.

PostgreSQL's **INNER** JOIN retrieves the records where table1 intersects table2. In simple terms, the **INNER** join returns the matching/common values from the targeted tables.

The best way to comprehend a concept is to implement it practically. So, let’s do it.

 **Example: How to Combine Two Tables Via INNER Join in Postgres?**

A step-by-step guide on joining different tables via the INNER JOIN clause is presented in this section:

 **Step 1: Create Sample Tables**

Firstly, we will create a couple of sample tables named “ **employee_info** ” and “ **department_info** ”. After that, we will insert some records into the newly created tables:
    
    
    CREATE TABLE employee_info( 
    e_id INT PRIMARY KEY, 
    e_name VARCHAR NOT NULL, 
    e_email VARCHAR(50) NOT NULL
    );

The “CREATE TABLE” message in the output proves that the “employee_info” table has been created successfully. Let’s create one more sample table:
    
    
    CREATE TABLE department_info(
    dpt_id INT NOT NULL, 
    dpt_name VARCHAR NOT NULL,
    e_id INT,
    CONSTRAINT fk_employee
    FOREIGN KEY(e_id) 
    REFERENCES employee_info(e_id)
    );

The “department_info” table has been created successfully.

 **Step 2: Insert Data**

Let’s insert employees' information and departments' information into the respective tables:
    
    
    INSERT INTO employee_info(e_id, e_name, e_email)
    VALUES (1, 'Mike', 'mike@abc.com'),
    (2, 'John', 'johm@abc.com'),
    (3, 'Ambrose', 'ambrose@abc.com'),
    (4, 'Seth', 'seth@abc.com'),
    (5, 'Joe', 'joe@abc.com'),
    (6, 'Kane', 'kane@abc.com');

Six records have been inserted into the employee_info table successfully. Let’s insert the department information into the department_info table:
    
    
    INSERT INTO department_info(dpt_id, dpt_name, e_id)
    VALUES (1, 'Writing Department', 1),
    (2, 'Video Editing Department', 2),
    (3, 'HR Department', 3),
    (2, 'Video Editing Department', 4),
    (1, 'Writing Department', 5),
    (1, 'Writing Department', 6);

All the records have been inserted into the department_info table.

 **Step 3: Verify/Check Table’s Data**

To check the **“employee_info”** data, we will execute the select command as follows:
    
    
    SELECT * FROM employee_info;

Now we will check the **“department_info”** records via the **SELECT** statement:
    
    
    SELECT * FROM department_info;

The SELECT statement retrieves all the data of the “department_info” table.

 **Step 4: Join Tables**

Suppose we want to fetch the employees' data along with their respective departments. For this purpose, we will use the INNER Join as follows:
    
    
    SELECT employee_info.e_id, 
    e_name, e_email, dpt_name
    FROM employee_info 
    INNER JOIN department_info
    ON employee_info.e_id = department_info.e_id;

The output proves that the INNER Join retrieves the data from the targeted tables.

 **Conclusion**

Postgres provides an **INNER JOIN** clause to combine the records of multiple tables based on a specific condition/criteria. The “INNER JOIN” Clause is used with the “ON” clause to combine two tables via the inner JOIN in Postgres. Postgres' **INNER** JOIN retrieves the records where table1 intersects table2. In simple terms, the **INNER** join returns the matching/common values from the targeted tables. This post demonstrated the usage of INNER JOIN using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-combine-two-tables-using-inner-join-in-postgresql/)

---

# How to Drop All Tables in PostgreSQL?

> Postgres provides a couple of ways to drop all the tables of a Postgres database, such as dropping the complete schema or removing the schema’s tables individu…

Postgres provides a couple of ways to drop all the tables of a Postgres database, such as dropping the complete schema or removing the schema’s tables individually. The DROP SCHEMA command is used to drop the entire schema, while the DROP TABLE command with a for loop can drop each table individually.

This post will show you how to drop/delete tables in Postgres using suitable examples.

 **Method 1: Drop the Complete Schema**

Dropping a complete schema will drop all the objects present within it. However, the selected schema, along with its privileges, must be re-defined/re-created. The schema may have some tables with dependent objects; therefore, the CASCADE option with the DROP SCHEMA statement must be used to remove the dependent objects:
    
    
    DROP SCHEMA schema_name CASCADE;
    CREATE SCHEMA schema_name; 
    GRANT ALL ON SCHEMA schema_name TO postgres;
    GRANT ALL ON SCHEMA schema_name TO public;

The command mentioned above will drop all the tables of the selected schema along with its dependent objects like views and foreign keys. After that, it will re-create a schema and assign all privileges to the “postgres” and “public” users.

 **Listing Available Schemas**

Execute the “\dn” command from the SQL Shell to list all the schemas:

The above snippet shows that there are seven schemas available in the “postgres” database.

 **Example: How Do I Drop All the Tables From a Single Schema?**

The “example_schema” contains various tables, as shown in the following snippet:
    
    
    \dt example_schema.*;

Suppose we need to drop all the tables from the “ **example_schema** ”. For this purpose, we must use the “ **DROP SCHEMA** ” statement followed by the “ **schema_name** ” and then the “ **CASCADE** ” option:
    
    
    DROP SCHEMA example_schema CASCADE;
    CREATE SCHEMA example_schema;

The output shows that the first, the “example_schema,” has been dropped along with its objects. After that, the CREATE command re-created the selected schema. Now, grant the privileges to the “postgres” and “public” users via the following commands:
    
    
    GRANT ALL ON SCHEMA example_schema TO postgres;
    GRANT ALL ON SCHEMA example_schema TO public;

Let’s verify whether all the tables of the “example_schema” have been dropped or not via the following command:
    
    
    \dt example_schema.*;

The output signifies that all the tables of the selected schema have been dropped.

 **Note:** Similarly, you can drop all the tables from multiple schemas using the comma-separated syntax. To do that, you must use the DROP SCHEMA command as follows:
    
    
    DROP SCHEMA schema_1, schema_2, schema_3 CASCADE;
    CREATE SCHEMA schema_1, schema_2, schema_3;
    GRANT ALL ON SCHEMA schema_1, schema_2, schema_3 TO postgres;
    GRANT ALL ON SCHEMA schema_1, schema_2, schema_3 TO public;

Replace "schema_1, schema_2, schema_3" with the name of the schemas that you want to drop.

 **Method 2: Drop Each Table of a Schema Individually**

Alternatively, we can use a script to generate the DROP TABLE commands for each table in the database and execute them individually. This process is efficient and highly recommended because it drops only the tables of a schema rather than the whole schema.

 **Example: How Do I Drop All the Tables Individually?**

Let’s execute the below command to see all the available tables from the “public” schema:
    
    
    \dt;

Suppose we want to remove/drop all the relations of the “public” schema. For this purpose, the following script will be used:
    
    
    DO $$ DECLARE
    rec RECORD;
    BEGIN
    FOR rec IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public') LOOP
    EXECUTE 'DROP TABLE IF EXISTS ' || rec.tablename || ' CASCADE';
    END LOOP;
    END $$;

We utilized the for loop in the above code block to iterate over all the tables of the “public” schema. The DROP TABLE statement is used along with the “IF EXISTS” and “CASCADE” options to first check the table’s existence and then drop all the tables along with their dependent objects:

The “DO” message in the output demonstrates that the above block of code executed successfully. Let’s verify whether all the tables of the “public” schema have been dropped or not via the following command:
    
    
    \dt;

The output proves that all the tables from the “public” schema have dropped successfully.

This way, you can drop all the tables in Postgres.

 **Conclusion**

Postgres provides a couple of ways to drop all the tables of a Postgres database, such as dropping the complete schema or removing the schema’s tables individually. Dropping a complete schema will drop all the objects present within it. Alternatively, we can use a DROP TABLE command with the for loop to drop all the tables of the selected schema. This post demonstrates several methods to drop/remove all the tables in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-all-tables-in-postgresql/)

---

# How to Replace Null Values With Default Values in PostgreSQL

> In PostgreSQL, the COALESCE() function and the IS NULL operator are used to find and replace the null values with some default values.

In Postgres, “NULL” refers to an entry with no value or missing entry. PostgreSQL offers various built-in functions and operators to work with null values, such as **COALESCE()** function, **IS NULL** operator, etc. We can use these functions/operators to find and replace the null entries with some default/non-null entries in a Postgres table.

This blog will explain how to find and replace the null entries of a table with some non-null values using the following methods:

  *  **Method 1:** Using IS NULL Operator.
  *  **Method 2:** Using COALESCE() Function.



So, let’s begin with the COALESCE() function.

 **Method 1: Using IS NULL Operator**

In Postgres, the IS NULL operator allows us to filter out the NULL values, ensuring that our results contain only the relevant data. To replace the null values with some default values, you must use the IS NULL operator with the UPDATE query as follows:
    
    
    UPDATE table_name
    SET column_name = default_value
    WHERE column_name IS NULL;

The above-specified query will update the null values of the targeted column with the default value.

 **Example: How to Replace Null Values With Non-Null Values Using IS NULL Condition?**

We have already created a sample table named “ **staff_info** ”, whose content is shown in the following snippet:
    
    
    SELECT * FROM staff_info
    ORDER BY employee_id;

The output snippet shows that the “ **staff_info** ” table contains null and non-null entries. Suppose we want to update the null values of the employee_salary column with some new values. For this purpose, we will use the IS NULL operator with the UPDATE query as follows:
    
    
    UPDATE staff_info
    SET employee_salary = 15000
    WHERE employee_salary IS NULL;

Let’s verify the updated records using the SELECT command:

The null records have been updated/replaced with the default value.

 **Method 2: Using COALESCE() Function**

In Postgres, the COALESCE() function is one of the easiest ways of replacing null values with non-null values of your choice. To replace a null entry with some default value, you need to pass an expression or a column name as the first argument and the default value as the second argument to the COALESCE() function:
    
    
    COALESCE(expression|col_name, default_val);

Specify a non-null value of your choice in place of the “default_val” argument.

 **Example: How to Replace Null Values With Default Values Using COALESCE() Function?**

The sample table contains the following data:
    
    
    SELECT * FROM staff_info
    ORDER BY employee_id;

Suppose we want to replace the null entries of the “ **employee_salary** ” column with a default value of “10000”. For this purpose, we will use the **COALESCE()** function as follows:
    
    
    SELECT employee_name, COALESCE(employee_salary, 10000)
    FROM staff_info;

The null values have been successfully replaced with “10000”.

That’s all from this Postgres blog!

 **Conclusion**

In PostgreSQL, the **COALESCE()** function and the **IS NULL** operator are used to find and replace the null values with some default values. For instance, the IS NULL operator is used with the UPDATE query to find and replace the null entries with some default values. To replace a null entry with some default value using the COALESCE() function, pass an expression and the default value as arguments to the COALESCE() function. This post explained several methods to find and replace the null entries with the default values in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-replace-null-values-with-default-values-in-postgresql/)

---

# PostgreSQL INTERVAL Data Type With Examples

> The INTERVAL keyword is used to define an interval in Postgres. This blog explained the usage of the INTERVAL data type in Postgres via suitable examples.

A PostgreSQL **INTERVAL** data type represents a duration of time, such as the time between two events, an event's duration, etc. It takes 16 bytes of storage and ranges between -178000000 to +178000000 years. It stores a period of time as a single value(e.g., years, months, days, hours, minutes, etc.).

Users can also specify the precision of the **INTERVAL** data type while defining a table’s column. For instance, a column defined as an interval(4) will store the intervals with up to 4 digits of precision. The precision value is applied to the seconds' field only.

This blog post will give you an in-depth overview of how to use the INTERVAL data type in Postgres. So, let’s start!

 **How to Use INTERVAL Data Type in PostgreSQL?**

The below snippet demonstrates the interval data type:
    
    
    INTERVAL [field] [(p)]

In the above snippet, the “field” represents a time period, such as a year, month, day, hour, etc. While “p” represents a precision value.

Let’s put it into practice for a profound understanding!

 **Example 1: Creating a Column With INTERVAL Data Type**

This example states how to create a column with INTERVAL data type in Postgres:
    
    
    CREATE TABLE sample_tbl(
    article_title TEXT,
    article_published INTERVAL
    );

Now execute the “\d” command to describe the table details:
    
    
    \d sample_tbl;

The output snippet verifies that a table named “sample_tbl” has been created with an INTERVAL data type column.

 **Example 2: Inserting Interval into a Column**

Let’s learn how to insert intervals into Postgres tables via the INSERT command:
    
    
    INSERT INTO sample_tbl(article_title, article_published)
    VALUES(‘Count Unique Records’, ‘2 Years 3 Months 17 Days’);

You can see the inserted entries via the “SELECT” command:
    
    
    SELECT * FROM sample_tbl;

The desired record has been inserted into the “sample_tbl” successfully.

 **Example 3: Adding a Specific INTERVAL to Current Date**

In the following code snippet, we will show you how to add an **INTERVAL** to the current date:
    
    
    SELECT CURRENT_DATE, 
    CURRENT_DATE + INTERVAL '2 Years 3 Months 17 Days' AS "Current Date After 2 Years 3 Months 17 Days";

The above snippet shows the current date and the current date after “2 years 3 months, and 17 days”.

 **Example 4: Subtracting a Specific INTERVAL From Current DateTime**

Similarly, we can subtract a specific **INTERVAL** from the current date:
    
    
    SELECT CURRENT_DATE, 
    CURRENT_DATE - INTERVAL '2 Years 3 Months 17 Days' AS "Current Date After 2 Years 3 Months 17 Days";

The output shows the current date and the current date before “2 years, 3 months, and 17 days”.

 **Example 5: How to Format an INTERVAL in Postgres?**

To format a specific interval, the TO_CHAR() function is used in Postgres. The return type for the formatted interval will be TEXT:
    
    
    SELECT TO_CHAR(INTERVAL '2Y 3M 15D 18H 25M 32S', 'YY-MM-DD HH12:MI:SS');

The output snippet verifies that the given interval has been converted into the 12-hours format.

 **Example 6: How to Extract a Specific Field From the Given INTERVAL in Postgres?**

Use the Postgres’ **EXTRACT()** function to extract a specific field from an INTERVAL in Postgres:
    
    
    SELECT EXTRACT(HOURS FROM INTERVAL '06H 25M 32S');

The “hours” field has been extracted from the input INTERVAL successfully.

 **Conclusion**

PostgreSQL offers an **INTERVAL** data type that represents a time duration, such as the time between two events, an event's duration, etc. The “ **INTERVAL** ” keyword is used to define an INTERVAL in Postgres. Users can also specify the precision of the **INTERVAL** data type while defining a table’s column. For instance, a column defined as an interval(4) will store the intervals with up to 4 digits of precision. The precision value is applied to the seconds' field only. This blog explained the usage of the INTERVAL data type in Postgres via suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-interval-data-type-with-examples/)

---

# PostgreSQL - ALTER TABLE Command With Examples

> The ALTER TABLE command in PostgreSQL is used to alter the tables&#x27; structure, such as adding columns, renaming columns/tables, dropping columns, modifying cons…

In Postgres, the **ALTER TABLE** statement is used to alter/update the table’s structure. Using this command, you can easily modify the structure of any Postgres table, including adding columns, renaming columns/table, dropping columns, modifying constraints, and so on.

This blog post will discuss various use cases of Postgres’ ALTER TABLE statement via practical demonstration. So, let’s start with the basic syntax.

 **How to Alter/Modify a Table in PostgreSQL?**

Use the ADD, DROP, or RENAME keywords to perform the respective operation. For instance, the below-provided syntax is used to add, drop, or rename a column via the ALTER TABLE command:
    
    
    ALTER TABLE tab_name
    [ADD|DROP|RENAME] COLUMN col_name col_definition;

To change the column’s data type, use the ALTER TABLE command as follows:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_name TYPE new_data_type;

Use the following syntax to add or drop a constraint using the ALTER TABLE command:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_name SET|DROP constraint_name;

Use the ALTER TABLE command with the OWNER TO clause to change the owner of a table:
    
    
    ALTER TABLE tab_name
    OWNER TO new_owner_name;

Let’s put these concepts into practice!

 **Sample Table**

A sample table named “ **emp_data** ” has already been created. The below snippet demonstrates the content of the “ **emp_data** ” table:

Let’s modify the table’s structure via the ALTER TABLE command.

 **Example 1: Adding a New Column**

In the following **ALTER TABLE** statement, the **ADD COLUMN** clause will be used to insert a new column in the “ **emp_data** ” table:
    
    
    ALTER TABLE emp_data
    ADD COLUMN emp_age SMALLINT;

To verify the table alteration, use the “ **\d** ” command followed by the table name, i.e., “emp_data”:
    
    
    \d emp_data;

A new column named “ **emp_age** ” has been successfully inserted into the “ **emp_data** ” table.

 **Example 2: Dropping an Existing Column**

You must use the " **ALTER TABLE** " command with the " **DROP COLUMN** " clause to drop an existing column from the selected table:
    
    
    ALTER TABLE emp_data
    DROP COLUMN emp_age;

The above statement will drop the “ **emp_age** ” column from the “ **emp_data** ” table:

Let’s verify the table alteration using the “\d” command:
    
    
    \d emp_data;

The “ **emp_age** ” column from the “ **emp_data** ” table has been dropped/removed.

 **Example 3: Renaming a Column**

Use the “ **RENAME COLUMN** ” clause along with the “ **ALTER TABLE** ” command to rename a specific column of a table:
    
    
    ALTER TABLE emp_data
    RENAME COLUMN emp_joining_date TO "joining_date";

The below snippet will verify the table alteration:
    
    
    \d emp_data;

The output snippet proves that the “emp_joining_date” column has been renamed to “joining_date”.

 **Example 4: Changing Column Type**

Use the “ **ALTER TABLE** ” command with the “ **ALTER COLUMN TYPE** ” clause to change the data type of a column:
    
    
    ALTER TABLE emp_data
    ALTER COLUMN emp_id TYPE SMALLINT;

The above-provided statement will change the type of the “emp_id” column from “ **INTEGER** ” to “ **SMALLINT** ”:

Use the “ **\d** ” command to verify the column’s data type:
    
    
    \d emp_data;

The data type of the “ **emp_id** ” column has been successfully changed from “ **INT** ” to “ **SMALLINT** ”.

 **Example 5: Adding a Constraint**

To add a constraint in a specific column, you need to use the ALTER TABLE and ALTER COLUMN commands with the SET clause:
    
    
    ALTER TABLE emp_data
    ALTER COLUMN emp_id SET NOT NULL;

The above command will add a “ **NOT NULL** ” constraint in the “ **emp_id** ” column:

Let’s verify the table’s alteration using the following command:
    
    
    \d emp_data;

The “NOT NULL” constraint has been added to the emp_id column.

 **Example 6:** **Dropping a Constraint**

Suppose you want to drop a constraint from a particular column; for this purpose, you can utilize the ALTER TABLE and ALTER COLUMN commands with the DROP keyword as follows:

Let’s describe the “emp_data” table to verify the table alteration:
    
    
    \d emp_data;

The **NOT NULL** constraint has been dropped successfully from the selected column, i.e., “ **emp_id** ”.

 **Example 7: Changing Table’s Owner**

Run the “\dt” command followed by the table name to check the owner of a specific table”:
    
    
    \dt emp_data;

The above snippet shows that the owner of the “emp_data” table is “postgres”. Suppose we want to change the owner of the “ **emp_data** ” table from “ **postgres** ” to “ **cp_user** ”; for this purpose, we will use the “ **ALTER TABLE** ” command as follows:
    
    
    ALTER TABLE emp_data
    OWNER TO cp_user;

Use the “ **\dt** ” command to check the new owner of the “ **emp_data** ” table:
    
    
    \dt emp_data;

The output shows that the owner of the “emp_data” table has been changed from “ **postgres** ” to “ **cp_user** ”.

 **Example 8: Renaming a Table**

To rename a specific table in Postgres, users need to use the “ALTER TABLE” command with the “RENAME TO” clause:
    
    
    ALTER TABLE emp_data
    RENAME TO emp_info;

The above-specified statement will rename the “ **emp_data** ” table to “ **emp_info** ”:

Let’s verify the table’s name via the following command:
    
    
    \dt;

The output snippet signifies that the “ **emp_data** ” table has been successfully renamed to “ **emp_info** ”.

That’s all from this Postgres blog!

 **Conclusion**

The **ALTER TABLE** command in PostgreSQL is used to alter/update the existing tables. Users can easily modify the table’s structure using this command, such as adding columns, renaming columns/table, dropping columns, modifying constraints, etc. This blog post demonstrated the usage of the ALTER TABLE statement using relevant examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-alter-table-command-with-examples/)

---

# How to List Schemas in PostgreSQL

> In Postgres, the standard “information_schema”, a system catalog table named “pg_namespace”, and the “\dn” command is used to get the list of available schemas…

PostgreSQL offers several ways to list schemas, such as using standard “ **information_schema** ”, system catalog table “ **pg_namespace** ”, the “ **\dn** ” command, etc. These built-in schemas and commands empower us to efficiently access all schemas within a database, ultimately ensuring optimal performance and smooth operation.

This blog will demonstrate various methods along with suitable examples to list the schemas in Postgres. So, let’s start with the “\dn” command.

 **How to List Schemas Via the “\dn” in Postgres?**

The "\dn" command is the most convenient/user-friendly way to get the schemas list in PostgreSQL. It retrieves the list of schemas with their respective owners:
    
    
    \dn;

The output snippet shows that the “\dn” command retrieves all the available schemas and their owners. You can use the “\dn+” command to get the schema’s list with more details like access privileges and description:
    
    
    \dn+;

The output snippet shows that the “\dn+” command shows more detailed information for every available schema. To get the information of a specific schema, you need to use the “\dn” or “\dn+” command followed by the schema name, as shown in the following snippet:
    
    
    \dn exp_schema;

This way, we can get the details for a particular schema with the “\d” command.

 **How to List Schemas Via the “information_schema” in Postgres?**

The **INFORMATION_SCHEMA** shows the list of all the available schemas. To list all the schemas in a Postgres database, you can query the information_schema as follows:
    
    
    SELECT schema_name, schema_owner
    FROM information_schema.schemata;

The output shows the list of all the available schemas along with their owners.

 **How to List Schemas Via the “pg_namespace” in Postgres?**

To get the list of all the available schemas in a Postgres database, you can use the system catalog table "pg_namespace":
    
    
    SELECT nspname AS schema_name
    FROM pg_catalog.pg_namespace;

The output shows that the “pg_namespace” retrieves the list of available schemas.

That’s all from this blog!

 **Conclusion**

In PostgreSQL, the standard “information_schema”, a system catalog table named “pg_namespace”, and the “\dn” command is used to get the list of available schemas. You can use the “\dn+” command to get the schema’s list with more details like access privileges and description. You can also use the “\dn” or “\dn+” command, followed by the schema name to get the information of a specific schema. This blog post explained different approaches to getting the list of available schemas in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-list-schemas-in-postgresql/)

---

# PostgreSQL IS NULL Operator/Condition

> In Postgres, the IS NULL operator tests whether an expression/column contains a null value. It can be used with different statements, such as SELECT, UPDATE, e…

In PostgreSQL, NULL is a special marker that represents missing information or a non-existent value rather than an empty string or zero. A table in Postgres may or may not have some null entries. Postgres' **IS NULL** operator lets you filter and manipulate data based on whether a given column contains a NULL value or not. The IS NULL operator is especially useful when working with large datasets, where finding missing information can be essential for making data-driven decisions.

This blog will show you the usage of the **IS NULL** operator via practical examples.

 **IS NULL Operator/Condition in PostgreSQL**

In Postgres, the **IS NULL** operator tests whether an expression or a column contains a null value or not. It can be used in a SELECT statement to identify and return the rows with missing values in a specific column.

It can also be used in INSERT, UPDATE, and DELETE statements to manipulate the data accordingly. For instance, you can use the IS NULL operator in an UPDATE statement's SET clause to update only the rows where a column is null.

The IS NULL operator can be used with other comparison operators such as =, >=, >, etc. In such cases, it provides even more control over your data. For instance, you can use it to find records where a certain column does not have a NULL value and meet certain criteria.

 **How to Use the IS NULL Operator in Postgres?**

The basic syntax to use the IS NULL Operator in Postgres is as follows:
    
    
    col_name | expression IS NULL

Specify the column name or expression of your choice in which you want to check the existence of the NULL values. The IS NULL operator retrieves TRUE if the null value is found in a column/expression else, it retrieves FALSE.

 **Example 1: How to Find the NULL Values in a Postgres Table?**

We have created a sample table and inserted some records into it. The table’s data contains some null values as well:
    
    
    SELECT * FROM emp_data
    ORDER BY emp_id;

Let’s use the IS NULL operator and see how it works:
    
    
    SELECT *
    FROM emp_data
    WHERE emp_salary IS NULL;

The above statement will check the existence of NULL values within the “emp_salary” column:

The **IS NULL** operator retrieves the filtered data based on the NULL values.

 **Example 2: How to Use IS NULL Operator With INSERT Statement?**

We have created a couple of tables named “ **emp_data** ” and “ **emp_information** ”, whose data is shown in the following snippets:

Now execute the “ **SELECT *** ” command to get the details of the “ **emp_data** ” table:

Let's say we want to insert the records with null values from the emp_data table into the emp_information table. For this purpose, we will execute the following statements:
    
    
    INSERT INTO emp_information(emp_name)
    SELECT emp_name
    FROM emp_data 
    WHERE emp_salary IS NULL;

Three records with “null” values have been inserted from the “emp_data” table to the “emp_information” table. To verify the newly inserted null entries, use the “SELECT *” command:
    
    
    SELECT * FROM emp_information;

This is how the IS NULL operator works with Postgres’ INSERT statement.

 **Example 3: How to Find and Update the NULL Values From a Postgres Table?**

Suppose we want to update the null values with some new values. For this purpose, we will use the ISNULL operator with the UPDATE query as follows:
    
    
    UPDATE emp_information
    SET emp_salary = 0
    WHERE emp_salary IS NULL;

The above-given code will replace the null values with “0” in the emp_salary column:

Now, execute the “SELECT *” command one more time to see the updated table’s records:
    
    
    SELECT * FROM emp_information;

This is how the IS NULL operator works with the UPDATE query.

 **Example 4: How to Find and Delete the NULL Values From a Postgres Table?**

Use the IS NULL Operator with the DELETE query to delete the null entries from a table in Postgres:
    
    
    DELETE FROM emp_data
    WHERE emp_salary IS NULL;

In the above snippet, the IS NULL operator is used in the WHERE clause to filter the table’s data based on the NULL values. The DELETE query will delete the filtered NULL values from the emp_salary column:

The “DELETE 3” message in the output shows that three records have been deleted from the “emp_data” table. Let’s verify the deletion of the null entries via the following command:
    
    
    SELECT * FROM emp_data;

The output shows that the “emp_data” table contains only non-null values. It proves that the null entries have been deleted successfully.

 **Conclusion**

In Postgres, the **IS NULL** operator tests whether an expression or a column contains a null value or not. It can be used in a SELECT statement to identify and return only rows with missing values in a specific column. Moreover, it can be used in INSERT, UPDATE, and DELETE statements to manipulate the data accordingly. This Postgres blog explains what the “IS NULL” operator is and how it works in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-is-null-operatorcondition/)

---

# PostgreSQL TIMESTAMP: Timestamp Without Time Zone Data Type

> The PostgreSQL “TIMESTAMP” or “TIMESTAMP WITHOUT TIME ZONE” data type stores a timestamp value without the time zone information.

PostgreSQL provides several data types for the DateTime values, such as TIME, DATE, INTERVAL, TIMESTAMP, and TIMESTAMPTZ. These data types allow us to store the DateTime values in a database. The time data type stores time values in the database, the date data type stores the date values, and the interval type stores the intervals. While the TIMESTAMP and TIMESTAMPTZ data types are similar, the only difference is that one includes the time zone information while the other doesn’t.

This blog will show you the working of the Postgres **TIMESTAMP** data type with suitable examples.

 **PostgreSQL TIMESTAMP: Timestamp Without Timezone Data Type**

The PostgreSQL “ **TIMESTAMP** ” or “ **TIMESTAMP WITHOUT TIME ZONE** ” data type stores a timestamp value without a timezone. It is mostly used in scenarios where all the users work in the same zones. Use the following syntax to define a column with TIMESTAMP data type:
    
    
    CREATE TABLE tab_name (
    col_name TIMESTAMP
    );

To create a table’s column that accepts DateTime values, you need to replace the “col_name” with the column name of your choice and then specify the “TIMESTAMP” data type.

 **Example 1: Creating a Column With TIMESTAMP Data Type**

In the below program, we will create a table named “ **emp_data** ” with three columns: “ **emp_id** ”, “ **emp_name** ”, and “ **emp_joining_date** ”:
    
    
    CREATE TABLE emp_data(
    emp_id SMALLINT,
    emp_name TEXT,
    emp_joining_date TIMESTAMP
    );

The above snippet shows that the “ **emp_joining_date** ” column is created with the **TIMESTAMP** data type. So it will store the date time values without timezone information:

Let’s execute the “\d” command to describe the table’s structure:
    
    
    \d emp_data;

A column named “emp_joining_date” has been successfully created with the “TIMESTAMP WITHOUT TIME ZONE” data type. Let’s learn how to insert DateTime values to a “TIMESTAMP” column in Postgres:
    
    
    INSERT INTO emp_data(emp_id, emp_name, emp_joining_date)
    VALUES(1, 'John', '2021-12-12 09:10:15'),
    (2, 'Kane', '2022-01-01 09:00:35'),
    (3, 'Williams', '2022-01-15 09:30:00');

Let’s verify the newly inserted records via the “ **SELECT *** ” command:
    
    
    SELECT * FROM emp_data;

The output shows that the DateTime values have been successfully inserted into the TIMESTAMP column.

 **Example 2: Inserting a DateTime Value Via the LOCALTIMESTAMP Function**

The LOCALTIMESTAMP is a built-in function in Postgres that retrieves a DateTime value(without time zone) at which the current transaction begins:
    
    
    INSERT INTO emp_data(emp_id, emp_name, emp_joining_date)
    VALUES(4, 'Mike', LOCALTIMESTAMP);

To verify the newly inserted record, we will execute the SELECT query as follows:
    
    
    SELECT * FROM emp_data;

A new record without a time zone information has been inserted into the “ **emp_joining_date** ” column.

 **Example 3: Inserting DateTime Values Via Different Built-in Functions**

In Postgres, the functions like **NOW()** , **CURRENT_TIMESTAMP** , **TRANSACTION_TIMESTAMP()** , etc., retrieve the current date and time with time zone information. However, if we use them for the TIMESTAMP column, then the timezone information will be skipped, and the date time values will be inserted into the respective column:
    
    
    INSERT INTO emp_data(emp_id, emp_name, emp_joining_date)
    VALUES (5, 'Stephen', NOW()),
    (6, 'Ambrose', CURRENT_TIMESTAMP),
    (7, 'Shane', TRANSACTION_TIMESTAMP());

Let’s execute the “SELECT *” command one more time to fetch the newly inserted records:
    
    
    SELECT * FROM emp_data;

The output shows that the current DateTime values have been inserted into the “emp_joining_date” column, and the timezone information has been skipped successfully.

 **Conclusion**

The PostgreSQL “ **TIMESTAMP** ” or “ **TIMESTAMP WITHOUT TIME ZONE** ” data type stores a timestamp value without the time zone information. In Postgres, the TIMESTAMP and TIMESTAMPTZ data types are similar; the only difference is that one includes the time zone information while the other doesn’t. Inserting a DateTime value with time zone information into the TIMESTAMP column will insert the date and time into the respective column, and the time zone information will be skipped. This blog post explained the working of Postgres’ TIMESTAMP data type with suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-timestamp-timestamp-without-time-zone-data-type/)

---

# PostgreSQL TIMESTAMPTZ: Timestamp With Time Zone Data Type

> The PostgreSQL “TIMESTAMPTZ” or “TIMESTAMP With TIME ZONE” data type is used to store a timestamp value that includes the time zone information.

PostgreSQL facilitates us with various temporal data types, such as TIME, DATE, INTERVAL, TIMESTAMP, and TIMESTAMPTZ. These data types enable us to store the dates and times in a database. The TIMESTAMP and **TIMESTAMPTZ** data types are similar; the only difference is that one includes the time zone information while the other doesn’t.

This blog post will explain the working of the Postgres **TIMESTAMPTZ** data type with practical examples.

 **PostgreSQL Timestamp With Timezone(TIMESTAMPTZ) Data Type**

The PostgreSQL “ **TIMESTAMPTZ** ” or “ **TIMESTAMP With TIME ZONE** ” data type is used to store a timestamp value that includes the time zone information. This data type is useful in global applications where the users' time zones may differ. Postgres’ default time zone is UTC; therefore, inserting any value in the “TIMESTAMP With TIME ZONE” data type column will be converted into UTC.

 **Syntax**

To define a column with the “ **TIMESTAMPTZ** ” data type, you need to specify the column name followed by the TIMESTAMPTZ data type:
    
    
    CREATE TABLE tab_name (
    col_name TIMESTAMPTZ
     );

Let’s comprehend the **TIMESTAMPTZ** data type via the following examples.

 **Example: Creating a Column With TIMESTAMPTZ Data Type**

In the following example program, we will create a table named “ **employee_data** ” with three columns: “ **emp_id** ”, “ **emp_name** ”, and “ **emp_joining_date** ”:
    
    
    CREATE TABLE employee_data(
    emp_id SMALLINT,
    emp_name TEXT,
    emp_joining_date TIMESTAMPTZ
    );

Here in the above snippet, the “ **emp_joining_date** ” column is created with the “ **TIMESTAMPTZ** ” data type:

Execute the “ **\d** ” command along with the table’s name to find the details of the newly created table:
    
    
    \d employee_data;

A column named “ **emp_joining_date** ” with “timestamp with time zone” data type has been created successfully. Now, let’s learn how to insert data into the “ **TIMESTAMPTZ** ” column:
    
    
    INSERT INTO   employee_data(emp_id, emp_name, emp_joining_date)
    VALUES (1, 'Joe', '2021-01-09   05:13:15.162085-08');

Let’s verify the newly inserted record via the “ **SELECT *** ” command:
    
    
    SELECT * FROM employee_data;

The output signifies that a timestamp with the time zone information has been inserted into the TIMESTAMPTZ column.

 **TIMESTAMPTZ Functions**

Postgres offers several date-time functions to deal with temporal data. Some functions with the return type “TIMESTAMPTZ” have been listed below:

\- **NOW():** Retrieves the current DateTime with timezone information.  
\- **CURRENT_TIMESTAMP:** Retrieves the timestamp value with timezone information.  
\- **TO_TIMESTAMP():** Converts a DateTime string to a timestamp. Its return type is TIMESTAMPTZ.  
\- **CLOCK_TIMESTAMP():** Retrieves the current DateTime with timezone information at which the recent transaction begins.  
\- **STATEMENT_TIMESTAMP():** Retrieves the current DateTime with timezone information at which the current statement executes.  
\- **TRANSACTION_TIMESTAMP():** It works the same way as the NOW() function.

Let’s comprehend how these functions work via the following example.

 **Example: How Do the TIMESTAMPTZ Functions Work in Postgres?**

Let’s practice the functions mentioned above via the INSERT statement:
    
    
    INSERT INTO employee_data()
    VALUES(2, 'Joseph', NOW()),
    (3, 'Henry', CURRENT_TIMESTAMP),
    (4, 'Mike', CLOCK_TIMESTAMP()),
    (5, 'Joseph', STATEMENT_TIMESTAMP())
    (6, 'Joseph', TRANSACTION_TIMESTAMP());

Execute the “SELECT *” command to see the newly inserted data:
    
    
    SELECT * FROM employee_data;

The TIMESTAMPTZ values have been inserted into the “employee_joining_date” via the built-in DateTime functions.

 **Conclusion**

The PostgreSQL “ **TIMESTAMPTZ** ” or “ **TIMESTAMP With TIME ZONE** ” data type is used to store a timestamp value that includes the time zone information. Postgres offers several date-time functions to deal with temporal data. Some functions with the return type “ **TIMESTAMPTZ** ” include the “ **NOW()** ” function, **STATEMENT_TIMESTAMP()** function, **CURRENT_TIMESTAMP** function, etc. This blog post explained the working of TIMESTAMP with timezone data type using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-timestamptz-timestamp-with-time-zone-data-type/)

---

# TO_TIMESTAMP: How to Convert a String to TIMESTAMP in PostgreSQL

> The TO_TIMESTAMP() in Postgres is a built-in function for converting a string to a timestamp data type. Users can easily manipulate and analyze DateTime inform…

PostgreSQL offers various built-in functions that help us easily manipulate and analyze date and time information in our database. For instance the TO_CHAR() function, TO_TIMESTAMP() function, DATE_PART() function, etc. The **TO_TIMESTAMP()** is a must-have function for anyone working with PostgreSQL. It is a built-in formatting function that allows us to easily convert a string representation of a date-time into a timestamp data type.

This blog will teach you how to use the **TO_TIMESTAMP()** function in Postgres via practical examples. So, let’s start!

 **How to Use TO_TIMESTAMP() Function in Postgres?**

For using to_timestamp in Postgres, simply pass in the string you want to convert, along with a format mask that specifies how the date and time are represented. Utilize the following syntax to avail the functionality of the **TO_TIMESTAMP()** function:
    
    
    TO_TIMESTAMP(str_timestamp, formatMask);

The “ **str_timestamp** ” is a string representing a timestamp value that will be converted to a **TIMESTAMP** according to the specified “ **formatMask** ”. For example, if the given string is in the "YYYY-MM-DD HH:MI:SS" format, then you can use the following format mask: 'YYYY-MM-DD HH:MI:SS'. As a result, the TO_TIMESTAMP will convert the given string into a timestamp according to the provided format mask. The format must be [valid](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE>), as described in Postgres’ official documentation.

 **Note:** Aside from its basic features, simplicity, and flexibility, the TO_TIMESTAMP also has some advanced features that allow us to customize the conversion process. For instance, you can specify the number of decimal places in the mask to handle timestamps with fractional seconds, etc.

Let’s learn it practically!

 **Example 1: How to Convert the String Data to TIMESTAMP in Postgres?**

Execute the following line of code to convert the given string data into a TIMESTAMP data type:
    
    
    SELECT TO_TIMESTAMP('2023-01-04 11:13:20', 'YYYY-MM-DD HH:MI:SS');

Here, the second argument represents a format where “YYYY” is used to specify a four-digit year, “MM” for a two-digit month, “DD” for a two-digit month, “HH” for two-digit hours, “MI” for two-digit minutes, “SS” for two-digits seconds:

The output shows that the input string has been converted into a “TIMESTAMPTZ” data type.

 **Example 2: Adjusting Less Than Four-digits Year**

If you specify a year in less than four digits, then the **TO_TIMESTAMP()** will revise it to the nearest year. For instance, if you specify 95, it will be revised to 1995,14 will be modified to 2014, and so on:
    
    
    SELECT TO_TIMESTAMP('11 04 23', 'DD MM YY');

The output shows that the “ **TO_TIMESTAMP** ” function converted the given “2-digit year” to the nearest four-digits year.

 **Example 3: How Does the TO_TIMESTAMP Function Treat the Milliseconds/Microseconds?**

The TO_TIMESTAMP() addresses the milliseconds/microseconds as seconds while converting a text/string to a timestamp. The TO_TIMESTAMP function specifies the “ **milliseconds** ” in the “ **seconds** ” field after the decimal point:
    
    
    SELECT TO_TIMESTAMP('2023-01-04 31:55', 'YYYY-MM-DD SS:MS');

The output shows that the TO_TIMESTAMP function specified the milliseconds in the seconds' field after the decimal part.

 **Example 4: ERROR: Invalid Value**

Passing an invalid format to a TO_TIMESTAMP() function will result in an “Invalid Value” error:
    
    
    SELECT TO_TIMESTAMP('2023-01-04', 'ABCDYYYY-MM-DD');

The output shows that Postgres threw an “invalid value” error when we specified an inappropriate format.

 **Example 5: ERROR: Out of Range**

In Postgres, you may encounter an “out-of-range value” error while working with the TO_TIMESTAMP() function:
    
    
    SELECT TO_TIMESTAMP('2023-19-04 11:13:20', 'YYYY-MM-DD HH12:MI:SS');

The TO_TIMESTAMP() function throws a “value out-of-range” error because the “month” field accepts an invalid value(i.e., 19 > 12).

Overall, we can say that the TO_TIMESTAMP() is an essential tool/function for any Postgres developer working with date and time data.

 **Conclusion**

The **TO_TIMESTAMP()** in Postgres is a built-in function for converting string data into the timestamp data type. Users can easily manipulate and analyze date and time information using this function. It accepts a string representation of a DateTime and converts it into a timestamp data type. This post presents a detailed guide on converting the string data into a timestamp using the Postgres

TO_TIMESTAMP function.

---
[View this page online](https://www.commandprompt.com/education/to_timestamp-how-to-convert-a-string-to-timestamp-in-postgresql/)

---

# IS NOT NULL Operator/Condition in PostgreSQL

> In Postgres, the IS NOT NULL operator tests whether an expression or a column contains a non-null value. It is used in a SELECT statement to return only non-nu…

In Postgres, the **IS NULL** operator allows us to filter out the NULL values, ensuring that our results contain only the relevant data. While the **IS NOT NULL** operator opposes the working of the IS NULL operator. This means the IS NOT NULL operator checks the NON NULL values in INSERT, SELECT, DELETE, and UPDATE queries. With these operators, we can filter out NULL and NON-NULL values and get relevant, accurate, and truly representative data results.

This blog post will demonstrate the usage of the **IS NOT NULL** operator using suitable examples.

 **How to Use the IS NOT NULL Operator in Postgres?**

The basic syntax to use the IS NOT NULL Operator in Postgres is shown in the following snippet:
    
    
    col_name | expression IS NOT NULL

Specify the column name or expression in which you want to check for NON NULL values. The IS NOT NULL operator retrieves FALSE if the null value is found in a column/expression, else it retrieves TRUE.

 **Example 1: How to Find the NON NULL Values in a Postgres Table?**

We have created a sample table and inserted some null and non-null records into it:
    
    
    SELECT * FROM emp_data
    ORDER BY emp_id;

Now we will use the **IS NOT NULL** operator to get the non-null values only:
    
    
    SELECT *
    FROM emp_data
    WHERE emp_salary IS NOT NULL;

In this example, the IS NOT NULL operator is used to check the existence of NON NULL values within the “emp_salary” column:

The **IS NOT NULL** operator excludes the NULL values and retrieves the filtered data.

 **Example 2: How Insert NON-NULL Values From One Table to Another?**

We have a couple of sample tables named “ **emp_data** ” and “ **emp_information** ”, whose data is shown in the following snippets:

Now execute the “ **SELECT *** ” query one more time to get the details regarding the “ **emp_data** ” table:

Now, to insert the NON NULL records from the emp_data table to the emp_information table, we will use the IS NOT NULL operator as follows:
    
    
    INSERT INTO emp_information(emp_name, emp_salary)
    SELECT emp_name, emp_salary
    FROM emp_data 
    WHERE emp_salary IS NOT NULL;

To verify the newly inserted non-null entries, use the “SELECT *” command as follows:
    
    
    SELECT * FROM emp_information;

This is how the IS NOT NULL operator works with the Postgres’ INSERT statement.

 **Example 3: How to Update the NON NULL Values in a Postgres Table?**

To update the non-null values with some new values, we will use the IS NOT NULL operator with the UPDATE query as follows:
    
    
    UPDATE emp_data
    SET emp_salary = 0
    WHERE emp_salary IS NOT NULL;

The above-given code will set a value zero for all the non-null entries in the emp_salary column:

Let’s execute the “SELECT *” command one more time to see the updated table’s records:
    
    
    SELECT * FROM emp_data;

The output shows that the non-null values have been replaced with a numeric value “0.00”.

 **Example 4: How to Find and Delete the NON-NULL Values From a Postgres Table?**

Use the IS NOT NULL Operator with the DELETE query to delete the non-null values from a Postgres table:
    
    
    DELETE FROM emp_data
    WHERE emp_salary IS NOT NULL;

In the above snippet, the IS NOT NULL operator is used within the WHERE clause to filter the table’s data based on the NON-NULL values. The DELETE query will delete all the NON-NULL entries from the emp_salary column:

The “DELETE 4” message in the output window demonstrates that four records have been deleted from the “emp_data” table. You can verify the deletion of the non-null values using the “SELECT *” command:
    
    
    SELECT * FROM emp_data;

The output shows that the “emp_data” table contains only null values. It proves that the non-null entries have been deleted successfully.

That’s all from this Postgres blog.

 **Conclusion**

In Postgres, the **IS NOT NULL** operator tests whether an expression or a column contains a non-null value. It can be used in a SELECT statement to identify and return only non-null records from a specific column. Moreover, it can be used with INSERT, UPDATE, and DELETE statements to manipulate the data accordingly. This Postgres blog explained the usage of the “IS NOT NULL” operator with suitable examples.

---
[View this page online](https://www.commandprompt.com/education/is-not-null-operatorcondition-in-postgresql/)

---

# PostgreSQL - How to Insert Data Into a Table Using Python

> Use the “connect()” method of “psycopg” module to establish a connection with the Postgres database using python. Next, create a cursor object and execute the …

PostgreSQL is an advanced, open-source, highly stable DBMS that extends the standard SQL language. It supports all major programming languages, such as Python, Java, C++, etc. Due to its extensive features, Postgres has become most programmers/developers' first choice.

In this blog, we will present a step-wise guide on inserting data into a Postgres table using Python. So, let’s begin!

 **How to Insert Data Into a Postgres Using Python Programming?**

Follow the below instructions to insert the data into a table using python:

● Import psycopg  
● Establish a Connection With Postgres  
● Create a Cursor Object  
● Execute the INSERT Query  
● Save Changes  
● Close the Connection With the Database

 **Import psycopg**

Firstly, you need to import the “ **psycopg** ” module in your python program via the import keyword:
    
    
    import psycopg2

 **Establish a Connection With Postgres**

Use the “ **connect()** ” method of “ **psycopg** ” module to establish a [connection](<https://www.commandprompt.com/education/how-to-connect-to-postgresql-database-server-using-python/>) with the Postgres database using python:
    
    
    con = psycopg2.connect(
       database="postgres",
       user="postgres",
       password="*******",
       host="localhost",
       port= '5432'
       )

In the above snippet, the “ **postgres** ” represents a targeted database, the “ **postgres** ” represents a user name, and the “ **password** ” field shows a valid password for the selected database. Finally, specify the host/IP address and the port number in the respective fields.

 **Create a Cursor Object**

Creating the cursor object enables us to execute the Postgres queries from python. To create a cursor object in Postgres, you need to use the **cursor()** method as follows:
    
    
    curs_obj = con.cursor()

 **Execute the INSERT Query**

Now, execute the **INSERT** query with the help of the cursor object:
    
    
    curs_obj.execute("INSERT INTO emp_data(emp_name, emp_age) VALUES('Joseph', 26), ('Joe', 29);")
    print("Data Inserted")

 **Save Changes**

Use the “ **commit()** ” method to commit all the desired changes to the Postgres database permanently:
    
    
    con.commit()

 **Close the Connection With the Database**

Use the “ **close()** ” method to terminate the cursor and the connection to the selected database:
    
    
    curs_obj.close()
    con.close()

 **Complete Code**

 **Output**

 **Verification**

Let’s verify the inserted data using the **execute()** method and **fetchall()** method:
    
    
    curs_obj.execute("SELECT * FROM emp_data")
    result = curs_obj.fetchall()
    print("Table's Data:", "\n", result)

In the above code block, we utilize the execute() method to execute the SELECT query. Using the fetchall() method, we fetch the data from the “ **emp_data** ” table.

 **Code**

 **Output**

This is how you can insert and fetch data to or from a table in Postgres.

 **Conclusion**

Use the “ **connect()** ” method of “ **psycopg** ” module to establish a connection with the Postgres database using python. Next, create a cursor object and execute the **INSERT** query via the cursor object. After that, use the “commit()” method to permanently commit all the desired changes to the Postgres database. Finally, execute the “close()” method to terminate the cursor and the connection to the selected database. This blog presented a detailed guide on inserting data into a Postgres table via Python programming.

---
[View this page online](https://www.commandprompt.com/education/postgresql-how-to-insert-data-into-a-table-using-python/)

---

# Setting Up an SSH Connection

> The Secure Shell Protocol (SSH) provides IT professionals with a secure method to remotely connect to client environments. SSH typically uses a password or pub…

## Introduction

The Secure Shell Protocol (SSH) provides IT professionals with a secure method to remotely connect to client environments. SSH typically uses a password or public-key method to encrypt connections and authenticate network devices. This tutorial will focus on establishing an SSH connection for data transfer between the _postgres_ users on two Ubuntu 22.04 LTS instances.

### Step 1: Install OpenSSH

Before we can communicate between servers, we need to install OpenSSH, a suite of tools designed to use SSH to provide an encrypted, secure connection between servers:

> sudo apt -y install openssh-server

### Step 2: Generate SSH Keys

With OpenSSH installed, we now have tools in place that will allow an SSH connection, but we still need to give each server permission to connect with the other. To establish our connection, we generate a pair of ssh keys on each server. The pair of keys will consist of one private key and one public key. The private key contents should always be kept private (hence the name), while the public key can be shared in instances such as this to establish a connection. After creation, we will then transfer the public key contents of one server to an _authorized_keys_ file on the other.

Since we are connecting between the postgres user on each server, we will need to set the postgres user’s password on each server to connect. We can do so with:

> sudo passwd postgres

You will be prompted to enter and repeat a new password. Now, let’s become the postgres user on both servers to bypass some extra steps:

> sudo -iu postgres

The _ssh-keygen_ command will create our pair of ssh keys. As the postgres user, let’s begin by creating keys on each server:

> ssh-keygen -t rsa -b 4096 -N "" -f /var/lib/postgresql/.ssh/id_rsa

Let’s discuss the options we have included in our command:

  * -t indicates the type of key we will be generating (rsa).
  * -b specifies the key size in bits (4096).
  * -N specifies the passphrase, which we are excluding. If you wish to include a passphrase (recommended for security purposes), you may do so by excluding this option in the command and entering one when prompted after executing the command. This prevents your password from being recorded in any terminal logs.
  * -f indicates the output key file, which creates the .ssh directory with a private key labeled id_rsa and a public key named id_rsa.pub. This is the default path for the key placement, but we have included it explicitly for clarity of operations, or so you know how to change the path if desired.



This will produce output similar to:

> Generating public/private rsa key pair.  
> Created directory '/var/lib/postgresql/.ssh'.  
> Your identification has been saved in /var/lib/postgresql/.ssh/id_rsa  
> Your public key has been saved in /var/lib/postgresql/.ssh/id_rsa.pub  
> The key fingerprint is:  
> SHA256:pzXyCMcv4LOXdjtlgAsnkggYiG4OLfDywbd9M4pNhD0 postgres@bi-primary  
> The key's randomart image is:  
> +---[RSA 4096]----+  
> |=. |  
> |* |  
> |o= . + . |  
> |+o* = E.o . |  
> |++ o =o=S.+. |  
> | .. ..o+=O .o |  
> | +oo++oo |  
> | . oo+.o |  
> | .o ..o |  
> +----[SHA256]-----+

### Step 3: Transfer Public Keys

Now, we transfer the public key from one server to the other. There are a few methods to do this, but the simplest is to copy/paste them from one to the other.

Let’s begin by creating the _authorized_keys_ file where we placed the public key from the other server. We then change permissions on the file to keep it secure. The _authorized_keys_ file should be readable and writable only to our postgres user, which is what the _600_ setting means below:

> touch ~/.ssh/authorized_keys  
> chmod 600 ~/.ssh/authorized_keys

The contents of the public key file will be a single, long line with no line breaks. However, less will wrap the display across multiple lines of the screen. We copy the contents of the primary server public key ( _id_rsa.pub_ ) into the _authorized_keys_ file of the secondary server, and vice versa. View the contents of the file on the primary server with:

 _less ~/.ssh/id_rsa.pub_

Now, copy the string in the file, which should begin with _ssh-rsa_ and end with _postgres@primary_name_. Next, open the _authorized_keys_ file on the secondary and paste the contents from the primary server’s _id_rsa.pub_ :

> vi ~/.ssh/authorized_keys

 **Repeat this procedure using the secondary server public key and the primary server authorized_keys file.**

### Step 4: Test Connection

Next, let’s test the connection. During this process, you will be prompted to confirm the fingerprint from the server you are trying to connect to. The fingerprint is a shortened version of the host’s public key, which is easier to visually confirm than the entire key. This fingerprint is stored on the client server, usually in the _~/.ssh/known_hosts_ file, to validate the connection from the client to the host and prevent man-in-the-middle attacks. The fingerprints on a server are usually stored in the /etc/ssh/ directory, so we can list the fingerprints on the primary server with this command:

 _for k in $(ls -1 /etc/ssh/ssh_host_*_key.pub) ; do ssh-keygen -l -f "$k" ; done_

It should return something like this:

 _256 SHA256:orldbEz5z8lTOkjARQACvv3NUlUbTatvi11Wz5UuypE root@primary (ECDSA)  
256 SHA256:46ndduXK7ftOBFjL1ER6dvDzvHjKDCNYd0Tar3x/8FE root@primary (ED25519)  
3072 SHA256:qLUOsQ3o63tZ+eM/9ZumZsEgWzJCfidK4St+ZyFX7eE root@primary (RSA)_

This list includes the fingerprints for the ECDSA, ED25519, and RSA encryptions, but the server you are on may have more. Now that we know what fingerprints the primary server has, we can confirm them when we try to connect. To connect from the secondary, we enter:

 _ssh postgres@192.168.0.1_

You should now be asked to confirm the fingerprint on the host server with something like:

 _The authenticity of host '192.168.0.1 (192.168.0.1)' can't be established.  
ED25519 key fingerprint is SHA256:46ndduXK7ftOBFjL1ER6dvDzvHjKDCNYd0Tar3x/8FE.  
This key is not known by any other names  
Are you sure you want to continue connecting (yes/no/[fingerprint])?_

This output is telling us that the host _192.168.0.1_ is not in the _known_hosts_ file, which actually does not exist yet since we have not yet connected to any hosts. We are asked to confirm the fingerprint from the host, and we can visually compare this to the ED25519 fingerprint from the list we just printed. Since they match, we can safely type _yes_ to continue connecting.

You will receive an output that looks something like this:

> Warning: Permanently added '192.168.0.1' (ED25519) to the list of known hosts.  
> ssh_dispatch_run_fatal: Connection to 192.168.0.1 port 22: Broken pipe

The _known_hosts_ file has been created, and the fingerprint has been added. Let’s attempt to connect again:

> ssh postgres@192.168.0.1

You should now be prompted to enter the postgres password for the primary server:

> postgres@192.168.0.1's password:

Enter the password you set earlier, and you should receive some welcoming information indicating you are on the primary server. We can confirm this by issuing the hostname command:

> hostname

And it should display the primary server’s name:

> primary

Assuming there are no hangups, we are ready to transfer data!

### Summary

We have covered how to establish an SSH connection between two servers. We installed OpenSSH, generated key-pairs, transferred public key information, and then tested our connection. This will allow us to securely transfer data across systems with our postgres user. Thanks for tuning in!

---
[View this page online](https://www.commandprompt.com/education/setting-up-an-ssh-connection/)

---

# How to Convert the Case of a String in PostgreSQL

> In PostgreSQL, the UPPER(), LOWER(), and INITCAP() functions are used for letter case conversion.

In PostgreSQL, converting the case of a string is a useful technique that is used to format the strings into a specific case. For this purpose, Postgres provides various built-in functions. These built-in functions can easily transform the case of your strings according to your requirements. The process of letter case functions is simple and straightforward.

This blog demonstrates how to convert the string’s letter case in Postgres via practical examples. So, let’s start!

 **How Do I Convert the Case of a String in Postgres?**

To convert the case of a string in Postgres, you must use one of the following functions:

 **UPPER():** This function converts all string characters to uppercase.
    
    
    SELECT UPPER(col_name) FROM table_name;

 **LOWER():** It converts all characters/letters in a string to lowercase.
    
    
    SELECT LOWER(col_name) FROM table_name;

 **INITCAP()** : this function transforms each word's first character/alphabet in a string to uppercase and the rest of the characters to lowercase.:
    
    
    SELECT INITCAP(col_name) FROM table_name;

 **Example 1: Converting String letters to Uppercase**

In the following code, a string is passed to the UPPER(); let's see how it works:
    
    
    SELECT UPPER('Hello, welcome, how are you');

All letters have been converted to UPPER CASE successfully.

 **Example 2: Converting String letters to Lowercase**

In the following code, a string is passed to the UPPER(); let's see how it works:
    
    
    SELECT LOWER('Hello, WELCOME, how are you');

All letters have been converted to lowercase successfully.

 **Example 3: Converting String letters to Title Case**

Let’s learn how the INITCAP() function works in PostgreSQL
    
    
    SELECT INITCAP('Hello, welcome, how are you');

The output proves the working of the INITCAP() function.

 **Example 4: How to Use Letter case Functions on Table’s Data**

We have already created a table named articles_info, whose data is shown in the following snippet:

Let’s use the letter case functions in the article_title column:
    
    
    SELECT LOWER(article_title), UPPER(article_title),
    INITCAP(article_title)
    FROM articles_info;

The output certifies the working of the letter case functions.

 **Conclusion**

In PostgreSQL, the UPPER(), LOWER(), and INITCAP() functions are used for letter case conversion. The UPPER() function converts all the string characters/letters to uppercase, while the LOWER() converts all characters in a string to lowercase. The INITCAP() transforms each word's first character/alphabet in a string to uppercase and the remaining letters/characters to lowercase. This blog presented detailed knowledge on how to convert the case of a string in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-convert-the-case-of-a-string-in-postgresql/)

---

# PostgreSQL SPLIT_PART Function: Extracting Data From a String

> The SPLIT_PART() function accepts three arguments: a string, a delimiter/separator, and a position. Consequently, it retrieves the extracted data from the give…

The SPLIT_PART() in Postgres is an incredibly useful built-in function for manipulating and extracting data from strings. The SPLIT_PART() function allows us to determine a delimiter/separator based on which the string will be divided. It can accept any character or sequence of characters, such as a comma, a space, or even a regular expression.

This post will guide you on extracting the data from a string using the SPLIT_PART() function in Postgres. So, let’s start.

 **PostgreSQL SPLIT_PART Function: Extracting Data From a String**

The SPLIT_PART() function assists us in extracting the data from strings such as employee name, address, or any other data that contains multiple pieces of information separated by a delimiter/separator:
    
    
    SPLIT_PART(str, del, position);

Here in this syntax:

The “str” represents a string to be separated/split. The “del” argument represents a delimiter/separator based on which the given string will split. While “position” specifies the substring's position, it must be a positive number.

 **Example 1: Split the Given String From a Comma**

In the following code, we utilize the “ **,** ” as a delimiter:
    
    
    SELECT SPLIT_PART('Hello, welcome, how are you', ',', 3);

The SPLIT_PART() extracts the data from the string based on the specified position.

 **Example 2: Splitting Dates From Hyphen “-”**

We have already created a table named articles_info, whose data is shown in the following snippet:

Let’s split the publish_date and retrieve the year, month, and day, separately:
    
    
    SELECT article_title,SPLIT_PART(publish_date::TEXT,'-', 1) AS Year,
    SPLIT_PART(publish_date::TEXT,'-', 2) AS Month,
    SPLIT_PART(publish_date::TEXT,'-', 3) As Day
    FROM articles_info;

The output demonstrates that the SPLIT_PART() function extracted the published date successfully.

 **Example 3: Splitting Article Titles From a Space**

The below statement will split the article titles from a from and retrieve the data based on position “2”:
    
    
    SELECT article_title,SPLIT_PART(article_title,' ', 2) 
    FROM articles_info;

The output verifies the working of the SPLIT_PART() function.

 **Conclusion**

The SPLIT_PART() in Postgres is a built-in function used for manipulating and extracting data from strings. The SPLIT_PART() function allows us to determine a delimiter/separator based on which the string will be extracted. It accepts three arguments: a string, a delimiter/separator, and a position. Consequently, it retrieves the extracted data from the given string. This post demonstrated the practical usage of the SPLIT_PART() function using examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-split_part-function-extracting-data-from-a-string/)

---

# How to Group by Date/Time in PostgreSQL

> PostgreSQL offers various built-in functions to group data by time, such as the DATE_TRUNC(), EXTRACT(), and DATE_PART() functions.

Grouping data by date and time is a common task while working with databases. Grouping the table’s data by date/time intervals (such as months, weeks, days, hours, etc.) assists us in gaining valuable insights and trends in our data. PostgreSQL offers various built-in functions to group data by time, such as the **DATE_TRUNC()** , **EXTRACT()** , and **DATE_PART()** functions.

This blog post will explain several methods to group the table’s data by time in Postgres. So, let’s get started.

 **How to Group by Time in Postgres Via DATE_TRUNC() Function?**

The most convenient method to group table data is by using the **DATE_TRUNC()** function, which allows us to truncate a timestamp to a specific level of precision, such as the month, day, hour, etc. The following snippet shows the content of a sample table named "article_info":

Let’s group the table’s data by “Year” via the DATE_TRUNC() function:
    
    
    SELECT DATE_TRUNC('YEAR', publish_date) published_year,
    COUNT(article_id) AS count
    FROM articles_info
    GROUP BY DATE_TRUNC('YEAR', publish_date);

The output proves that the DATE_TRUNC() function groups the table’s data by year.

 **Note:** Similarly, you can group data by month, day, hours, etc., using the DATE_TRUNC() function.

 **How to Group by Time in Postgres Via DATE_PART() Function?**

The DATE_PART() function can also be used to group the data by date/time. This function allows us to extract a date part and group the records by date/time using the GROUP BY clause. Let’s group the table’s data by “DAY” via the DATE_TRUNC() function:
    
    
    SELECT DATE_PART('DAY', publish_date) day_of_month,
    COUNT(article_id) AS count
    FROM articles_info
    GROUP BY DATE_PART('DAY', publish_date);

The output verifies that the DATE_PART() function groups the table’s data by day.

 **How to Group by Time in Postgres Via EXTRACT() Function?**

Another option to group table data by time is to use the built-in EXTRACT() function, which allows you to extract a specific part of a timestamp, such as a year, a week, an hour, etc. The following snippet shows the content of a sample table named "emp_attendence":

Let’s group the table’s data by “minutes” via the EXTRACT() function:
    
    
    SELECT EXTRACT('MINUTES' FROM emp_check_in) AS minutes,
    COUNT(emp_id)
    FROM emp_attendence
    GROUP BY EXTRACT('MINUTES' FROM emp_check_in);

This way, you can use the EXTRACT() function to group the table’s data by “minutes”.

That’s it from this post.

 **Conclusion**

PostgreSQL offers various built-in functions to group data by time, such as the **DATE_TRUNC()** , **EXTRACT()** , and **DATE_PART()** functions. The most convenient method to group table data is the **DATE_TRUNC()** function, which allows us to truncate a timestamp to a specific level of precision, such as the month, day, hour, etc. This blog post explained how to group the data by date/time in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-group-by-datetime-in-postgresql/)

---

# PostgreSQL Logical Operators: AND, OR, NOT

> PostgreSQL has three main logical operators: OR, AND, and NOT. All these operators retrieve a boolean value and are hence also referred to as Boolean operators…

Postgres offers three main logical operators **OR** , **AND,** and **NOT**. The AND and OR operators combine several conditions to create more sophisticated queries that can extract the exact data you need. While the NOT operator negates the result of a boolean expression. For any database developer working with PostgreSQL, these operators are essential, as they allow you to make decisions based on the data stored in your database.

This blog post will explain the working of the following Postgres Logical operators with suitable examples.

  * PostgreSQL Logical Operators
  * What Does AND Operator Do in Postgres?
  * What Does OR Operator Do in Postgres?
  * What Does NOT Operator Do in Postgres?



So, let’s begin!

 **PostgreSQL Logical Operators**

PostgreSQL has three main logical operators: AND, OR, and NOT. All these operators retrieve a boolean value and are hence also referred to as Boolean operators. Postgres also offers advanced logical operators such as BETWEEN, IN, LIKE, etc. These advanced logical operators allow you to perform more complex operations such as comparing values, checking whether a value falls within a range, finding patterns among your data, etc. In PostgreSQL, you can create highly customized and targeted queries using these operators.

 **What Does AND Operator Do in Postgres?**

The logical AND joins two or more conditions and retrieves a boolean value as follows:

\- Retrieves TRUE only if both boolean expressions are true.  
\- Retrieves FALSE if any of the given boolean expressions is false.  
\- Retrieves NULL if one value is TRUE and the second one is NULL.  
\- Retrieves FALSE if one value is FALSE and the second one is NULL.  
\- Retrieves NULL if both boolean expressions are NULL.

 **Syntax**

Follow the below syntax to join different conditions using **AND** Operator:
    
    
    SELECT col_list
    FROM table_name
    WHERE [cond_1] AND [cond_2]...

 **Example 1: How Do I Use the AND Operator in PostgreSQL?**

We have already created a sample table named “example_tab” that contains the following boolean data:

Let’s utilize the AND operator to combine two columns, “val_1” and “val_2”:
    
    
    SELECT val_1, val_2, val_1 AND val_2 AS result
    FROM example_tab;

The output shows the truth table for the AND operator.

 **Example 2: Practical Implementation of the AND Operator in Postgres**

Let’s learn the usage of the AND operator in a real-world scenario. We have a sample table named “article_details”, whose content is shown in the following snippet:

Suppose we want to fetch published articles between the interval '2021-08-10' and '2022-08-10'. For this purpose, we will execute the “SELECT *” as follows:
    
    
    SELECT * FROM article_details
    WHERE published_date > '2021-08-10' AND published_date < '2022-08-10';

The output snippet shows that the AND operator retrieves only those records that satisfy both conditions.

 **What Does OR Operator Do in Postgres?**

The OR operator combines two or more conditions and retrieves a boolean value as follows:

\- Retrieves TRUE if both boolean expressions/conditions are TRUE.  
\- Retrieves TRUE if any of the given boolean expressions are TRUE.  
\- Retrieves TRUE if one expression/condition is TRUE and the second one is NULL.  
\- Retrieves NULL if one expression/condition is FALSE and the second one is NULL.  
\- Retrieves NULL if both boolean expressions are NULL.

 **Syntax**

Follow the below syntax to join different conditions using **OR** Operator:
    
    
    SELECT col_list
    FROM table_name
    WHERE [cond_1] OR [cond_2]...

 **Example 1: How do I Use the OR Operator in PostgreSQL?**

Let’s utilize the OR operator to combine two columns, “val_1” and “val_2”:
    
    
    SELECT val_1, val_2, val_1 OR val_2 AS result
    FROM example_tab;

The output snippet shows the truth table for the OR operator.

 **Example 2: Practical Implementation of the OR Operator in Postgres**

Suppose we want to fetch the articles published after '2021-08-10' or article_id is less than 5. To do that, we will execute the “SELECT *” statement as follows:
    
    
    SELECT * FROM article_details
    WHERE published_date > '2021-10-10' OR article_id < 5;

The output snippet shows that the AND operator retrieves all those records that satisfy at least one condition.

 **What Does NOT Operator Do in Postgres?**

The NOT operator negates a condition and retrieves the result as follows:

\- Retrieves TRUE if the original result is FALSE.  
\- Retrieves FALSE if the original result is TRUE.  
\- Retrieves NULL if the original result is NULL.

 **Syntax**

To use the NOT operator in Postgres, users must follow the below-provided syntax:
    
    
    SELECT col_list
    FROM table_name
    WHERE NOT [condition]

Let’s implement it practically.

 **Example: Practical Implementation of the NOT Operator in Postgres**

Suppose we want to fetch the articles whose id is greater than 5. For this purpose, we can use the NOT operator as follows:
    
    
    SELECT * FROM article_details
    WHERE NOT article_id < 5;

Here the original condition is “article_id < 5”; however, we will get opposing results because of the NOT operator, as shown in the following snippet:

The output shows that the NOT operator negates the results of the original condition.

 **Conclusion**

PostgreSQL has three main logical operators: OR, AND, and NOT. All these operators retrieve a boolean value and are hence also referred to as Boolean operators. The AND and OR operators combine several conditions to create more sophisticated queries. While the NOT operator negates the result of a boolean expression. This write-up explained the usage of the logical operators in Postgres using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-logical-operators-and-or-not/)

---

# How to Drop a Default Value From a Column in PostgreSQL

> To drop/remove the default value from a column, you need to use the “DROP DEFAULT” keyword with the assistance of the “ALTER TABLE” command.

PostgreSQL allows us to add the default values to the table’s column. To do that, the DEFAULT keyword is used in Postgres during table creation or alteration. Setting the columns’ default values provides an ease to the users; however, they can sometimes be annoying. For example, while customizing your data or if they're no longer needed. Thankfully, dropping a default value from a column is a straightforward process that can be accomplished using the “ALTER TABLE DROP DEFAULT” command.

This blog will present a detailed overview of adding or dropping a default value from a column using the ALTER TABLE command in Postgres. So, let’s get started.

 **Setting/Adding a Column’s Default Value in Postgres**

We have already created a “product_info” table, whose structure is shown in the following snippet:

The output snippet shows that the default value is not added to any column. Let’s set today’s date as the default value of the purchase_date column:
    
    
    ALTER TABLE product_info
    ALTER COLUMN purchase_date SET DEFAULT NOW();

Let’s describe the “product_info” table to check the default value:

The output shows that the default value has been added to the “purchase_date” column.

 **Dropping a Default Value From a Column in Postgres**

To drop/remove the default value from a column, you need to use the “DROP DEFAULT” keyword with the assistance of the “ALTER TABLE” command:
    
    
    ALTER TABLE product_info
    ALTER COLUMN purchase_date DROP DEFAULT;

The output snippet shows that the “ALTER TABLE DROP DEFAULT” command was executed successfully. Let’s describe the “product_info” table one more time to check the default value of the purchase date column:

The above image shows that the default value has been dropped successfully.

This way, you can add/drop the column’s default value using the ALTER TABLE command in Postgres.

 **Conclusion**

PostgreSQL allows us to add or drop the default values to the table’s column using the ALTER TABLE command. To drop/remove the default value from a column, you need to use the “DROP DEFAULT” keyword with the assistance of the “ALTER TABLE” command. This blog considered multiple examples of adding or dropping the column’s default value using the ALTER TABLE command in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-default-value-from-a-column-in-postgresql/)

---

# INTEGER Data Types in PostgreSQL

> PostgreSQL provides several integer data types, such as INTEGER, SMALLINT, and BIGINT. These data types assist us in storing and manipulating whole numbers.

PostgreSQL provides several integer data types that help us fulfill our needs, such as **INTEGER** , **SMALLINT** , and **BIGINT**. These data types assist us in storing and manipulating whole numbers. Each data type stores a different range of values and has different storage requirements. You can store integer data types in PostgreSQL no matter what your requirements are.

This blog post will explain various integer data types via practical examples. So, let’s start.

 **How to Use INTEGER Types in Postgres?**

This section will explain the three primary data types to store the integer data in Postgres.

 **SMALLINT Data Type**

The below-listed points demonstrate the working of the Postgres SMALLINT data type:

\- The storage size of the SMALLINT is **two** bytes.  
\- The minimum range of the SMALLINT type is **-32,768**.  
\- Its maximum range is **+32,767**.  
\- Trying to store an out-of-the-specified range will throw an error.

 **INT Data Type**

The below-listed points present the working of the Postgres INTEGER data type:

\- The storage size of the INTEGER is **four** bytes.  
\- The minimum range of the INT type is -2,147,483,648.  
\- Its maximum range is +2,147,483,647.  
\- Trying to store an out-of-the-specified range will throw an error.

 **BIGINT Data Type**

The following points will explain the working of the Postgres BIGINT data type:

\- The storage size of the BIGINT is **eight** bytes.  
\- The minimum range of the BIGINT type is -9,223,372,036,854,775,808.  
\- The maximum range of the BIGINT type is 9,223,372,036,854,775,807.  
\- Trying to store an out-of-the-specified range will throw an error.

 **Note:** **T** he BIGINT data type consumes too much storage, which decreases the database efficiency. So, use the BIGINT data type when you have a proper reason to use it.

 **Example: How to Create/Define a Table With INTEGER Data Types in PostgreSQL?**

Let’s learn how we can use integer data types in Postgres:
    
    
    CREATE TABLE example_tab (
    exp_small SMALLINT PRIMARY KEY,
    exp_int INT,
    exp_big BIGINT,
    );

The output snippet indicates that a table has been created with the integer data types. Execute the below query to insert integer data into the “example_tab” table:
    
    
    INSERT INTO example_tab(exp_small, exp_int, exp_big)
    VALUES (1, 500000, 9223172036154175807),
    (2, 1200000, 8123172036154175807),
    (3, 1500000, 6723172036154175807);

The output shows that three records have been inserted into the “example_tab” tab. To fetch the “example_tab” data, you must execute the “SELECT *” command:

Output authenticates the working of the integer data types.

 **Example 2: Out-of-Range Error**

If we insert an out-of-range value, then we will encounter the following error:
    
    
    INSERT INTO example_tab(exp_small, exp_int, exp_big)
    VALUES (500000, 1233211, 9223172036154175807);

The maximum range of the SMALLINT type is **+32,767** ; however, we tried to store “500000”, which causes the “smallint out of range” error.

That’s it from this blog.

 **Conclusion**

PostgreSQL provides several integer data types that help us fulfill our needs, such as **INTEGER** , **SMALLINT** , and **BIGINT**. These data types assist us in storing and manipulating whole numbers. Each data type stores a different range of values and has different storage requirements. This post presented a detailed guide on how to use integer data types in Postgres via examples.

---
[View this page online](https://www.commandprompt.com/education/integer-data-types-in-postgresql/)

---

# How to Drop a View in PostgreSQL

> In Postgres, the DROP VIEW statement allows us to delete one or more views from a database. To do that, use the DROP VIEW statement followed by the view’s name…

In PostgreSQL, a view is nothing but a virtual table that is defined based on a SELECT statement. It enables us to store a SELECT query and use it as a table in our database. Postgres views are useful for organizing and accessing data, but if you have too many, they can take up space and slow down your database. It is therefore recommended that review the Postgres views regularly and delete the unnecessary views.

This write-up will guide you on how to drop a view in Postgres using practical examples. So, let’s start.

 **How to Drop a View in PostgreSQL?**

In Postgres, the **DROP VIEW** statement allows us to delete one or more views from the database. To do that, use the DROP VIEW statement followed by the view’s name to be deleted:
    
    
    DROP VIEW view_name;

In place of “view_name”, specify the view to be dropped.

 **Example: Dropping a Postgres View**

The below snippet shows the list of available views:

Suppose we want to drop “emp_view”; for that, we will execute the DROP VIEW statement as follows:
    
    
    DROP VIEW emp_view;

To verify the view’s deletion, use the “\dv” command:

The selected view, i.e., “emp_view”, has been dropped successfully. Let’s execute the DROP VIEW command one more time to see how it works when the selected view doesn’t exist in the database:
    
    
    DROP VIEW emp_view;

The output shows that Postgres throws an error “view doesn’t exist”. To avoid this error, you need to use the “IF EXISTS” clause with the DROP VIEW statement:
    
    
    DROP VIEW IF EXISTS emp_view;

The output snippet proves that this time a notice appeared instead of throwing an error. Let’s use the following code to drop the “sample_view” from the database if it exists:
    
    
    DROP VIEW IF EXISTS sample_view;

The sample_view has been dropped successfully. From the above examples, we can conclude that the “if exists” option drops the selected view if it exists in the database, and it shows a notice if the targeted view doesn’t exist.

 **Conclusion**

In Postgres, the **DROP VIEW** statement allows us to delete one or more views from the database. To do that, use the DROP VIEW statement followed by the view’s name to be deleted. Postgres throws an error if the view to be dropped/deleted doesn’t exist in the database. To avoid this error, you need to use the “IF EXISTS” clause with the DROP VIEW statement. This post explained the basic syntax, usage, and working of the DROP VIEW statement using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-view-in-postgresql/)

---

# How the timezone() Function Works in PostgreSQL

> In PostgreSQL, the timezone() function converts a timestamp to a different time zone. It retrieves a new timestamp with the same value but in a different time …

PostgreSQL provides a built-in function named **timezone()** that converts a timestamp to a different time zone. The **timezone()** function does not change the value of the input timestamp; instead, it simply retrieves a new timestamp with the same value but in a different time zone.

This blog post will explain the working of the timezone() function with practical examples.

 **How Does the TIMEZONE() Function Work in Postgres?**

In Postgres, the **timezone()** function accepts two values as arguments: a zone and a timestamp. As a result, it converts a timestamp to some other timestamp based on the zone specified within the **timezone()** function:
    
    
    timezone(tz, timestamp);

Here, tz represents a timezone based on which the given timestamp will be converted.

Let’s put it into practice for a profound understanding!

 **How to Check the Current TIMEZONE in Postgres?**

To find the current timezone in PostgreSQL, you need to execute the following command:
    
    
    SHOW TIMEZONE;

The output indicates that the current timezone is “America/Los_angeles”.

 **How to Find All TIMEZONE in Postgres?**

Execute the “ **SELECT *”** command for the “ **pg_timezone_names** ” table to see the list of all timezones supported by Postgres:
    
    
    SELECT * FROM pg_timezone_names;

The “ **pg_timezone_names** ” table contains all necessary details regarding Postgres-supported timezones.

 **Example 1: How to Convert a TIMESTAMP(with timezone) to Another TIMESTAMP in Postgres?**

Let’s pass a TIMESTAMP with timezone to the **TIMEZONE()** function and see how it works:
    
    
    SELECT TIMEZONE('Australia/Melbourne', TIMESTAMP with TIME ZONE '2022-12-12 10:00:00-01');

The output shows that if the given timestamp contains a timezone, then the timezone() function shifts the original timestamp value to the specified time zone and retrieves the value without a time zone.

For a profound understanding, let’s change the timezone value in the specified timestamp:
    
    
    SELECT TIMEZONE('Australia/Melbourne', TIMESTAMP with TIME ZONE '2022-12-12 10:00:00+01');

In the above query, we changed the timezone value from “-01” to “+01”; consequently, you will get the following output:

The output snippet proves that the original timestamp value has been modified according to the specified timezone.

Suppose a user specifies a “TIMESTAMP with TIME ZONE” in the TIMEZONE() function. However, he didn’t specify the time zone in the original timestamp; then, the original timestamp value will be shifted to the local time zone:
    
    
    SELECT TIMEZONE('Australia/Melbourne', TIMESTAMP with TIME ZONE '2022-12-12 10:00:00');

The output shows that the original timestamp value has been shifted to the local timezone.

 **Example 2: How to Convert a TIMESTAMP(without timezone) to Another TIMESTAMP in Postgres?**

Suppose you want to convert a timestamp that doesn't contain a timezone. In that case, the result will be retrieved based on the timezone settings, and the timezone will be shifted/added with the original timestamp:
    
    
    SELECT TIMEZONE('Australia/Melbourne', TIMESTAMP without TIME ZONE '2022-12-12 10:00:00');

This is how you can convert a TIMESTAMP(without a timezone) to another zone via the TIMEZONE() function in Postgres.

 **Example 3: How to Convert a CURRENT_TIMESTAMP to Another TIMESTAMP in Postgres?**

This example explains converting the current timestamp via the **TIMEZONE()** function. In this example, we will convert the current TIMESTAMP(with time zone) to "Australia/Melbourne" timezone using the TIMEZONE() function:
    
    
    SELECT CURRENT_TIMESTAMP, TIMEZONE('Australia/Melbourne', CURRENT_TIMESTAMP);

Since the CURRENT_TIMESTAMP function contains a timezone, so the TIMEZONE() function will retrieve a timestamp without a time zone:

The output shows that the TIMEZONE() function shifts the original timestamp to the specified timezone.

 **Conclusion**

In PostgreSQL, the **timezone()** function converts a timestamp to a different time zone. The **timezone()** function does not change the value of the input timestamp; instead, it simply retrieves a new timestamp with the same value but in a different time zone. It accepts a Postgres-supported timezone and converts the given timestamp based on the specified timezone. This post explained the basic syntax, usage, and practical examples of the Postgres’ timezone() function.

---
[View this page online](https://www.commandprompt.com/education/how-the-timezone-function-works-in-postgresql/)

---

# How to Extract DATE From a TIMESTAMP in PostgreSQL?

> In PostgreSQL, the built-in DATE() function, CAST operator, and scope resolution operator “::” are used to extract a date from a TIMESTAMP.

In Postgres, timestamps can be handy for storing and tracking events, but sometimes you only need the date portion. For instance, you might want to group records by date, perform some analysis on just the date, etc. No matter what the case is, extracting the date from a timestamp in PostgreSQL is a straightforward process.

This post will cover the following methods for extracting the date from a timestamp in Postgres:

  * How to Extract DATE From a TIMESTAMP Using DATE() Function?
  * How to Extract DATE From a TIMESTAMP Using CAST Operator?
  * How to Extract DATE From a TIMESTAMP Using Scope Resolution “ **::** ” Operator?



The approaches mentioned above will extract the date from the timestamp regardless of whether the timestamp contains or doesn’t contain timezone information.

Let’s begin with the DATE() function!

 **How to Extract DATE From a TIMESTAMP Using DATE() Function?**

The DATE() function in Postgres is used to extract/get a date from a TIMESTAMP. The **DATE()** function takes a **TIMESTAMP** and extracts the date part from it. The following snippet shows the basic syntax of the DATE() function:
    
    
    DATE(‘time_stamp’);

Specify the timestamp to be converted in place of the “time_stamp” argument.

 **Example 1: Extract the Date From a TIMESTAMP via the DATE() Function**

Let’s pass a timestamp to the DATE() function and see how it works:
    
    
    SELECT DATE('2022-11-15 02:46:28.158712-08');

The output proves that the DATE() function extracts the date part from the given timestamp successfully.

 **Example 2: Extract the Date From a TIMESTAMP Column Via the DATE() Function**

We have defined a sample table in our database whose details are shown in the following snippet:

Let’s extract the date from the “joining_date” column via the DATE() function:
    
    
    SELECT emp_id, emp_name, DATE(joining_date)
    FROM employee_bio;

The output shows that the DATE() function extracts the date part from the targeted column successfully.

 **How to Extract DATE From a TIMESTAMP Using CAST Operator?**

Using the CAST operator, you can also extract a date from a TIMESTAMP. Here is the syntax for extracting a date from a timestamp via the CAST operator:
    
    
    CAST ('time_stamp' AS DATE);

Specify the timestamp to be converted in place of the “time_stamp” argument.

 **Example 1: Extract the Date From a TIMESTAMP Via the CAST Operator**

Let’s learn how to extract a date part from the current timestamp via the CAST operator:
    
    
    SELECT CAST(CURRENT_TIMESTAMP AS DATE);

The CURRENT_TIMESTAMP function will retrieve the current date and time with the timezone. The ‘CAST AS DATE’ operator will convert the current timestamp into a date:

The output snippet clarifies that the CAST operator successfully extracts the date from the timestamp.

 **Example 2: Extract the Date From a TIMESTAMP Column Via the CAST Operator**

In this example, we will extract the date from the “joining_date” column of the “employee_bio” table via the CAST operator:
    
    
    SELECT emp_id, emp_name, CAST(joining_date AS DATE)
    FROM employee_bio;

The output snippet proves that the CAST operator extracts the date from the timestamp successfully.

 **How to Extract DATE From a TIMESTAMP Using Scope Resolution “::” Operator?**

The scope resolution operator “ **::** ” works the same way as the **CAST** operator(i.e., converts the given timestamp to a date). The syntax for the scope resolution operator will go like this:
    
    
    ‘time_stamp':: DATE;

Specify the timestamp to be converted in place of “time_stamp”.

 **Example 1: Extracting a Date From a Timestamp Via the Scope Resolution Operator**

In the following example, we will convert a timestamp into a date using the scope resolution operator:
    
    
    SELECT '2022-11-15 02:46:28.158712-08':: DATE;

The output indicates that the date has been successfully extracted from the timestamp using the “ **::** ” operator.

 **Example 2: Extract the Date From a TIMESTAMP Column Via the Scope Resolution Operator**

In this example, we will extract the date from the “joining_date” column of the “employee_bio” table via the scope resolution operator:
    
    
    SELECT emp_id, emp_name, joining_date :: DATE
    FROM employee_bio;

The output snippet clarifies that the date part has been successfully extracted from the timestamp.

 **Conclusion**

In PostgreSQL, the built-in **DATE()** function, **CAST** operator, and **scope resolution** operator “ **::** ” are used to extract a date from a TIMESTAMP. All these methods take a timestamp/date-time value and convert it into a date. This blog presented various practical examples to explain how to extract a date from a timestamp in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-extract-date-from-a-timestamp-in-postgresql/)

---

# How to Change the Timezone of a Postgres Database

> PostgreSQL provides an “ALTER DATABASE” command that is used with the “SET TIMEZONE” clause to change the timezone of a Postgres database.

In PostgreSQL, changing the time zone of a database is a straightforward yet essential task. Incorrect time stamps can cause various ambiguities/issues, from misconceptions and miscommunications to inappropriate data analysis and reporting. However, by updating the database's time zone, you can ensure that all clients/team members are on the same page, regardless of their location.

This blog will show you how to change the timezone of a Postgres database via practical demonstration. So, let’s get started.

 **How to Find All TIMEZONE in Postgres?**

Execute the “ **SELECT *”** command for the “ **pg_timezone_names** ” table to see the list of all timezones supported by Postgres:
    
    
    SELECT * FROM pg_timezone_names;

The “ **pg_timezone_names** ” table contains all necessary details regarding Postgres-supported timezones.

 **How to Change/Alter the Timezone of a Database in PostgreSQL?**

PostgreSQL provides an “ **ALTER DATABASE** ” command that can be used with the “ **SET TIMEZONE** ” clause to change the timezone of a Postgres database. To do that, the ALTER DATABASE command must be executed as follows:
    
    
    ALTER DATABASE db_name
    SET TIMEZONE TO 'new_timezone';

Specify the database name in place of “db_name”.

 **Example: Changing the Timezone of a Specific Database**

To find the current timezone in PostgreSQL, you need to execute the following command:
    
    
    SHOW TIMEZONE;

The output indicates that the current timezone is “America/Los_angeles”. Let’s find the current timestamp by executing the below-provided command:
    
    
    SELECT CURRENT_TIMESTAMP;

Suppose we want to change the current time zone to "Australia/Brisbane". For this purpose, we will use the ALTER DATABASE command as follows:
    
    
    ALTER DATABASE example
    SET TIMEZONE TO 'Australia/Brisbane';

Let’s check the modified timezone of the “example” database via the below-mentioned command:
    
    
    SHOW TIMEZONE;

The output snippet shows that the TIMEZONE has been changed/modified successfully. Now to find the current timestamp, you need to use the following statement:
    
    
    SELECT CURRENT_TIMESTAMP;

This is how you can alter the timezone of a database in Postgres.

 **Note:** When you run a database on a server, the server's time zone might not match your team members' time zone. This can cause confusion and errors, especially while working with timestamped data. By changing the time zone of your database, you can remove such kind of issues/ambiguities.

 **Conclusion**

PostgreSQL provides an “ **ALTER DATABASE** ” command that can be used with the “ **SET TIMEZONE** ” clause to change the timezone of a Postgres database. The timezone must be valid/Postgres supported. Execute the “ **SELECT *”** command for the “ **pg_timezone_names** ” table to see the list of all time zones supported by Postgres. This blog explained how to change the timezone of a Postgres database via practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-change-the-timezone-of-a-postgres-database/)

---

# GREATEST() and LEAST() Functions in PostgreSQL

> In PostgreSQL, the GREATEST() and LEAST() are built-in functions used to get the biggest and smallest value from the given data, respectively.

In PostgreSQL, the **GREATEST()** and **LEAST()** are built-in functions used to get the biggest and smallest value from the given data, respectively. The **GREATEST()** and **LEAST()** functions are very handy for any data analyst or developer working with PostgreSQL. No matter what the case is, these functions are equally effective in analyzing and manipulating numerical and textual data.

This blog post will teach you how to use the **GREATEST(),** and **LEAST()** functions in Postgres via practical examples. So, let’s start!

 **GREATEST() and LEAST() Functions in PostgreSQL**

 **GREATEST()** and **LEAST()** functions in Postgres offer more than just finding the greatest or least value. These functions can compare multiple values at once, making it easy to find the maximum or minimum value among a **group** of values. These functions provide equally effective results for large sets of data.

 **Syntax of GREATEST() Function**

The following syntax is used to work with the GREATEST() function in Postgres:
    
    
    GREATEST(val_1, val_2, val_3, …., val_n);

The above snippet shows that the GREATEST() function accepts “n” arguments, retrieving the largest value among them.

 **Syntax of LEAST() Function**

Use the following syntax to implement the LEAST() function in Postgres:
    
    
    LEAST(val_1, val_2, val_3, …., val_n);

The LEAST() function accepts “n” arguments and retrieves the smallest value among them.

Let’s implement these functions practically!

 **Example 1: How to Use the GREATEST() Function With Numeric Data?**

Let’s learn how the GREATEST() function works on numeric data:
    
    
    SELECT GREATEST(-612, 127, 481, 620, -767);

The GREATEST() function retrieves the largest integer.

 **Example 2: How to Use the GREATEST() Function With TEXT Data?**

Execute the below code to comprehend the working of the GREATEST() function on alphabetic data:
    
    
    SELECT GREATEST('ALEX', 'Bob', 'John', 'Seth', 'Joseph');

The GREATEST() function retrieves the greatest value concerning alphabetic order/sequence.

 **Example 3: How to Use the LEAST() Function With Numeric Data?**

The following code snippet shows how the LEAST() function works on numeric data in Postgres:
    
    
    SELECT LEAST(0, 127, 481, 620, -67);

The LEAST() function retrieves the smallest integer.

 **Example 4: How to Use the LEAST() Function With TEXT Data?**

Let’s learn how the LEAST() function works on TEXT data:
    
    
    SELECT LEAST('ALEX', 'Bob', 'John', 'Seth', 'Joseph');

The output snippet proves that the LEAST() function retrieves the smallest value concerning alphabetic order/sequence.

 **Example 5: How to Use the GREATEST() Function With DATES?**

Run the following line of code to find the greatest date among the given dates:
    
    
    SELECT GREATEST('2022-01-01', '2025-12-14', CURRENT_DATE);

The GREATEST() function retrieves the maximum date value from the given set of dates.

 **Example 6: How to Use the LEAST() Function With DATES?**

Let’s learn how to find the least date from the given set of dates using the LEAST() function:
    
    
    SELECT LEAST('2022-01-01', '2025-12-14', CURRENT_DATE);

The output proves the working of the LEAST() function, as it retrieves the smallest date among the given dates.

That’s it from this post!  
 **Conclusion**

In PostgreSQL, the **GREATEST()** and **LEAST()** are built-in functions used to get the biggest and smallest value from the given data, respectively. These functions are equally effective for analyzing/manipulating numeric and alphabetic data. In the case of textual data, these functions retrieve the data based on the alphabetic sequence/order. This blog post demonstrated the basic syntax, usage, and practical implementation of the GREATEST() and LEAST() functions in Postgres.

---
[View this page online](https://www.commandprompt.com/education/greatest-and-least-functions-in-postgresql/)

---

# PostgreSQL Data Type Formatting Functions

> Postgres provides various built-in formatting functions such as TO_CHAR(), TO_TIMESTAMP(), etc. that allows us to convert data from one type to another based o…

One of the standout features of PostgreSQL is its diverse collection of data type formatting functions, such as **TO_CHAR()** , **TO_TIMESTAMP()** , etc. These formatting functions allow us to convert data from one type to another, format it in a specific way, or even extract specific parts of a date or time value. These functions assist us in manipulating the data and presenting it in a clear and concise manner.

This Postgres blog will explain the below-listed formatting functions with syntax and examples:

  * Postgres TO_CHAR() Function
  * Postgres TO_NUMBER() Function
  * Postgres TO_DATE() Function
  * Postgres TO_TIMESTAMP() Function



Let’s begin with the TO_CHAR() function!

 **Postgres TO_CHAR() Function**

TO_CHAR() is one of the most widely used formatting functions that convert a timestamp to string, interval to string, or number to string based on the specified format.

 **Syntax**

The **TO_CHAR()** function accepts an expression and a format as arguments:
    
    
    TO_CHAR(expression, format);

The expression can be an interval, a timestamp, or a numeric value that will be converted to a string based on the given format. The format must be valid as described in Postgres’ [official documentation](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE>).

 **Example: How to Format a Timestamp in Postgres?**

Let’s learn how to format a timestamp in Postgres via the **TO_CHAR()** function:
    
    
    SELECT TO_CHAR(TIMESTAMP '2022-11-18 22:11:16', 'YYYY/MM/DD HH12:MI:SS');

In the above snippet,

\- A TIMESTAMP '2022-11-18 22:11:16' is passed as an argument to the **TO_CHAR()** function.  
\- A valid format “YYYY/MM/DD HH12:MI:SS” is passed as an argument to the TO_CHAR() function.  
\- The **TO_CHAR()** function will convert the given timestamp according to the given format and retrieves a string as an output:

The input timestamp has been converted into a string based on the specified format. Visit the following [blog post](<https://commandprompt.com/education/postgresql-to_char-function-with-practical-examples/>) to learn more about the TO_CHAR() function.

 **Postgres TO_NUMBER() Function**

TO_NUMBER() is a formatting function that converts a string into a number based on the given format.

 **Syntax**

The below snippet shows the basic syntax of the TO_NUMBER() function:
    
    
    TO_NUMBER(numeric_val, format);

The “ **numeric_val** ” argument represents a numeric string to be converted based on the specified format. The format must be a valid numeric pattern, as stated in Postgres’ [official documentation](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-NUMERIC-TABLE>).

 **Example: How to Convert a Number to a String in Postgres Via the TO_NUMBER() Function?**

In the following example, we will show you how to convert a numeric string to a number using the TO_NUMBER() function:
    
    
    SELECT TO_NUMBER(-572.14, 'S999D99');

Here, in the above example, we specified “S” that represents a sign, each “9” represents a single digit, and “D” represents a decimal point. On successful execution, the given numeric string will be converted into a number, as shown in the following snippet:

The output authenticates the working of the TO_NUMBER() function. Read the following article for a profound understanding of Postgres’ [TO_NUMBER()](<https://commandprompt.com/education/how-to-use-to_number-function-in-postgresql/>) function.

 **Postgres TO_DATE() Function**

The TO_DATE() is a built-in formatting function that converts a date string to date based on the specified format.

 **Syntax**

The below snippet shows the basic syntax for the TO_DATE() function:
    
    
    TO_DATE(string, Format);

The format must be a valid date pattern as described in [Postgres’ official documentation](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE>).

 **Example: How to Convert a String to a Date Via the TO_DATE() Function in Postgres?**

Let’s pass a string and a valid date format to the TO_DATE() function:
    
    
    SELECT TO_DATE('2022/12/14', 'YYYY/MM/DD');

The output snippet proves that the given string has been successfully converted into a date. To learn more about the TO_DATE() function, you must visit the following [link](<https://commandprompt.com/education/postgresql-to_date-function-convert-string-to-date/>).

 **Postgres TO_TIMESTAMP() Function**

The TO_TIMESTAMP() function takes a string and a valid date format as arguments and converts the string into a timestamp.

 **Syntax**

Here is the basic syntax of the Postgres’ TO_TIMESTAMP() function:
    
    
    TO_TIMESTAMP(string, ‘date_format’);

The format must be a valid date pattern as described in [Postgres’ official documentation](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE>).

 **Example: How to Convert a String Into a Timestamp Via the TO_TIMESTAMP() Function?**

Let’s learn how the TO_TIMESTAMP() function works in Postgres via the following example:
    
    
    SELECT TO_TIMESTAMP('2022-07-12', 'YYYY-MM-DD');

The output snippet proves that the given string has been successfully converted into a TIMESTAMP. Visit the following blog for a profound understanding of Postgres’ [TO_TIMESTAMP()](<https://commandprompt.com/education/postgresql-to_timestamp-function-with-examples/>) function.

That’s it from this blog!

 **Conclusion**

PostgreSQL provides various built-in formatting functions such as **TO_CHAR()** , **TO_TIMESTAMP()** , etc. These formatting functions allow us to convert data from one type to another based on some valid format. The data formatting functions assist us in manipulating the data and presenting it in a clear and concise manner. This blog post explained the working of various built-in data type formatting functions via practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-data-type-formatting-functions/)

---

# How to Update an Existing Table in PostgreSQL

> In PostgreSQL, the ALTER TABLE command updates the table’s structure, such as adding a new column, renaming a column, changing data type, etc.

PostgreSQL offers various built-in commands to perform table operations, such as INSERT, DELETE, UPDATE, ALTER TABLE, etc. Updating tables in Postgres is one of the most frequently used operations that assist us in maintaining and organizing table data. Whether you need to modify an existing column, add a new one, or delete an old one, it's important to know how to do so efficiently and effectively.

With this tutorial, you'll learn how to update an existing table in Postgres and be well on your way to managing and organizing your data efficiently. In this regard, the following topics will be covered in this write-up:

  * How to Update an Existing Table in Postgres?
  * What Does ALTER TABLE Statement Do in Postgres?
  * What Does UPDATE Statement Do in Postgres?



So, let’s start!

 **How to Update/Modify an Existing Table in PostgreSQL?**

Postgres allows us to update the structure of an already existing table and the data/records of an existing table using different commands. For instance, commands like ALTER TABLE, ADD COLUMN, RENAME TABLE, etc., are used to modify the table's structure in Postgres. On the other hand, to modify the table’s records, the UPDATE statement with the SET clause is used in Postgres.

 **What Does ALTER TABLE Statement Do in Postgres?**

In Postgres, the ALTER TABLE command modifies the existing table's structure. For instance, using ALTER TABLE statement, you can perform the following functionalities:

\- [Add a New Column](<https://commandprompt.com/education/how-to-add-columns-to-a-table-in-postgresql/>).  
\- [Drop Column.](<https://www.commandprompt.com/education/how-to-drop-columns-from-a-table-in-postgresql/>)  
\- [Alter Column Type.](<https://www.commandprompt.com/education/how-to-alter-column-type-in-postgresql/>)  
\- [Rename Column.](<https://www.commandprompt.com/education/how-to-rename-the-columns-of-a-table-in-postgresql/>)  
\- [Rename Table.](<https://commandprompt.com/education/alter-table-rename-to-in-postgresql/>)  
\- [Add/Drop Constraints.](<https://commandprompt.com/education/postgresql-drop-constraint-with-practical-examples/>)  
\- [Set Column’s Default Value.](<https://commandprompt.com/education/how-to-addset-a-default-value-to-a-column-in-postgresql/>)

Let’s learn how to update the table’s structure via the following examples.

 **Example 1: Renaming a Postgres Table**

We have already created a table named “shortlisted_students”, whose details are shown in the following snippet:

The below-provided command will rename the “shortlisted_student” table to “shorlisted_candidates” via the **ALTER TABLE** statement:
    
    
    ALTER TABLE shortlisted_students
    RENAME TO shortlisted_candidates;

Execute the SELECT * command followed by the new table name, i.e., “shortlisted_candidates”, to verify the working of the ALTER TABLE statement:

Output proves the working of the ALTER TABLE command. Now fetching the table’s data with the old name, i.e., “shorlisted_students”, will throw an error:

The above snippet shows an error because the “shortlisted_students” table has been renamed to “shortlisted_candidates”, and there is no such table with the name “shortlisted_students”.

 **Example 2: Set Default Value for a Column**

We have already created a table named “product_details”, whose details are described in the following snippet:

The output snippet shows that the DEFAULT value is not set for any column. Let’s learn how to set a default value for an existing column using the ALTER TABLE statement:
    
    
    ALTER TABLE product_details 
    ALTER COLUMN purchase_date SET DEFAULT CURRENT_DATE;

The “CURRENT_DATE” has been set as the default value for the “purchase_date” column. Now insert a new record into the product_details table to comprehend the working of the DEFAULT keyword:
    
    
    INSERT INTO product_details(product_id, product_price)
    VALUES (1, 5000);

Let’s verify the table’s data via the “SELECT *” command:

The output snippet clarifies that the current date has been inserted into the purchase_date column by default, which proves the DEFAULT keyword's working.

 **Note:** Similarly, you can use the ALTER TABLE command to update the column name, column data type, add/drop a specific column, and so on.

 **What Does UPDATE Statement Do in Postgres?**

In Postgres, you must execute the UPDATE statement to update the table's record. For this purpose, use the following syntax for the UPDATE statement:
    
    
    UPDATE table_name
    SET column_1 = val_1, column_2 = val_2, …, column_N = val_N
    WHERE condition;

\- Specify the table’s name in place of table_name.  
\- Use the SET clause to specify the columns you want to update and the new values.  
\- Comma-separated syntax in Postgres allows us to update multiple columns at once.  
\- WHERE is an optional clause that specifies the condition to determine which rows should be updated.  
\- Skipping the WHERE clause will modify all the rows in the table.

 **Example: How to Update Table’s Data in Postgres?**

We have already created a table named “ **article_details** ”, whose data is shown in the following snippet:

Suppose we want to update the “ **article_title** ” from “ **PostgreSQL UPDATE Query** ” to “ **PostgreSQL UPDATE STATEMENT** ”. For this purpose, we will execute the Update statement as follows:
    
    
    UPDATE article_details
    SET article_title = 'PostgreSQL UPDATE Statement'
    WHERE article_id = 10;

The output snippet shows that the UPDATE statement was executed successfully. You can verify the updated record using the “SELECT *” query:
    
    
    SELECT * FROM article_details;

This is how you can update the data of an existing table in Postgres.

 **Conclusion**

In PostgreSQL, the ALTER TABLE command updates the table’s structure, such as adding a new column, renaming a column, changing data type, etc. While modifying the table’s records can be accomplished in Postgres via the UPDATE query and the SET clause. This blog post presented a detailed guide for updating an existing Postgres table via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-update-an-existing-table-in-postgresql/)

---

# How to Alter/Modify a VIEW in PostgreSQL

> Postgres, the “CREATE OR REPLACE VIEW” command is used to modify the view’s definition. The ALTER VIEW command allows us to alter the view’s auxiliary properti…

In PostgreSQL, a view is a virtual table that is based on a SELECT query. A VIEW in Postgres enables us to define a SELECT statement as a named object, which can be used to query data just like a regular table. Postgres offers various commands to work with views, such as CREATE VIEW, DROP VIEW, etc. In Postgres, the “ **ALTER VIEW** ” and “ **CREATE OR REPLACE VIEW** ” statements are used to modify a view.

In this tutorial, we will show you how to alter a view in Postgres to modify the definition of a view. So, let’s start.

 **How to Use CREATE OR REPLACE VIEW Command in Postgres?**

In Postgres, the “ **CREATE OR REPLACE VIEW** ” command is used to modify the view’s definition. Use the following syntax to use the “ **CREATE OR REPLACE VIEW** ” statement in Postgres:
    
    
    CREATE OR REPLACE name_of_view
    AS query;

The create or replace command will create a new view if it doesn’t exist already. And it will modify the view’s definition according to the specified query if it already exists.

 **Example: Modifying a VIEW**

We have created a sample view named “emp_view,” whose data is shown in the following snippet:

We have also created a sample table whose structure is shown in the below snippet:

Suppose we want to modify the “emp_view” according to the “emp_bio” table. To do that, we will execute the CREATE OR REPLACE view statement as follows:
    
    
    CREATE OR REPLACE VIEW emp_view AS
    SELECT emp_id, emp_name, emp_salary, emp_age
    FROM emp_bio;

To verify the modified view, execute the “SELECT *” command:

The output snippet proves that the targeted view has been modified successfully.

 **How to Use ALTER VIEW Command in Postgres?**

The **ALTER VIEW** command allows us to alter/modify the view’s auxiliary properties. Using the ALTER VIEW statement assists us in setting a default column, renaming a view, etc.

 **Example: Renaming a View**

We have already created a view named “example_view”, whose content is shown in the following snippet:

Suppose we want to rename a view from “ **example_view** ” to “ **sample_view** ”. For this purpose, we will use the ALTER VIEW statement as follows:
    
    
    ALTER VIEW example_view
    RENAME TO sample_view;

The output snippet shows that the **“example_view”** has been modified successfully.

That’s it from this post!

 **Conclusion**

In Postgres, the “ **ALTER VIEW** ” and “ **CREATE OR REPLACE VIEW** ” statements are used to modify a view. In Postgres, the “ **CREATE OR REPLACE VIEW** ” command is used to modify the view’s definition. It creates a new view if it doesn’t exist already and modifies the view’s definition according to the specified query if it already exists. The ALTER VIEW command allows us to alter/modify the view’s auxiliary properties. This blog post explained different methods to modify a view in Postgres through practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-altermodify-a-view-in-postgresql/)

---

# PostgreSQL Create User With Password

> In PostgreSQL, the “CREATE USER” command is used to create a new user. To create a user with the password, execute this command with the “PASSWORD” attribute.

While working with databases, creating a separate user for each person who needs database access is a good practice. It assists us to control and monitor who can access which resources. Maintaining Postgres security is essential for database administrators therefore creating a user with a strong and unique password can reduce security risks.

This post will present a detailed guide on creating a user with a password in PostgreSQL through practical examples. So, let’s start!

 **How to Create a User With Password in PostgreSQL?**

In PostgreSQL, the “CREATE USER” and “CREATE ROLE” commands are used to create a new user. To create a user with a password, you must execute any of these commands with the “PASSWORD” attribute as follows:
    
    
    CREATE USER user_name WITH PASSWORD ‘user_password’;

Here in the above syntax:

CREATE USER is a statement, user_name represents a user to be created, WITH is a clause used to specify the “PASSWORD” privileges, and “user_password” represents the user's password.

 **Example 1: Creating a User/Role With a Password Attribute**

Suppose we want to create a user named “joseph” with password privileges. For this purpose, we will use the CREATE USER statement with the PASSWORD attribute as follows:
    
    
    CREATE USER joseph WITH PASSWORD ‘user_password’;

Let’s execute the “\du” command to show the newly created user:

The output snippet shows that a user named “joseph” has been created successfully.

 **Example 2: Creating a User With a Password Valid Until**

Postgres allows us to create a user with a password along with validity/expiry date. The password will expire after a specified time period:
    
    
    CREATE USER joseph WITH PASSWORD ‘user_password’
    VALID UNTIL 2025-12-01;

Let’s execute the “\du” command to show the newly created user:

A user named “ambrose” has been created with the password attributes. The password will expire on “2025-12-01”.

 **Example 3: Creating a Superuser**

To create a superuser, users need to issue the below-provided command:
    
    
    CREATE USER mike SUPERUSER LOGIN PASSWORD '12345';

Let’s execute the “\du” command to show the newly created user:

The output shows that a user named “mike” is created with superuser attributes.

This is how you can create an ordinary or a superuser with a password in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “CREATE USER” and “CREATE ROLE” commands are used to create a new user. To create a user with a password, you must execute any of these commands with the “PASSWORD” attribute. You can create a user whose password will expire after the specified date using the VALID UNTIL clause and the CREATE USER or CREATE ROLE command. This blog explained how to create an ordinary or a superuser with the password attribute in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-create-user-with-password/)

---

# PostgreSQL Create Table From CSV File

> In PostgreSQL, creating a table from a CSV file means importing a CSV file into the Postgres table. For this, execute the COPY command to create a Postgres tab…

In PostgreSQL, creating a table from a CSV file means importing/loading a CSV file into the Postgres table. In PostgreSQL, creating a table from a CSV file can quickly and easily get your data into a new database. CSV files are commonly used when exchanging data between applications or systems. To achieve this task, PostgreSQL provides a convenient command named “COPY” that allows us to efficiently import/load a huge amount of data from a CSV file into a Postgres table.

This post will use practical examples to explain various methods to create a table from a CSV file. So, let’s start.

 **Creating a CSV File**

Firstly, create a CSV file and specify some data in that file:

The above snippet shows a CSV file named "articles" that is saved at the following location:

“C:\Users\DELL\Desktop”.

 **Creating a Sample Table**

Let’s create a sample table via the below-provided command:
    
    
    CREATE TABLE articles_tab(
    a_id INT PRIMARY KEY,
    a_title TEXT,
    p_date DATE
    );

Execute the “ **SELECT *** ” command to verify the table’s creation:

The sample table has been created.

 **How to Create a Postgres Table From CSV Via COPY Command?**

The “COPY” statement reads data from a file or standard input and inserts it into a Postgres table. The COPY command has options to specify the data format, the column names, and the delimiter used in the file.

Once a sample table is created, the next step is to load the data from a CSV file to the sample table. For this purpose, a “ **COPY** ” command is used in Postgres. For instance, the below-given command will import the selected CSV file into the “articles_tab” table:
    
    
    COPY articles_tab(a_id, a_title, p_date)
    FROM 'C:\Users\DELL\Desktop\articles.txt'
    DELIMITER ','
    CSV HEADER;

In the above snippet:

\- We utilized the COPY command to load/import the CSV into the PostgreSQL table. For this purpose, we specify the COPY command, Postgres’ table name, and the columns.  
\- To specify the CSV file’s path, use the FROM clause.  
\- The delimiter identifies how the values are separated in the targeted CSV file.  
\- The Header keyword specifies that the selected CSV file contains a header.

The output snippet shows that the “ **COPY** ” command was executed successfully. Execute the “ **SELECT *** ” command to verify the data insertion of the CSV file into the “ **articles_tab** ” table.

The output shows that a Postgres table has been created based on the selected CSV file.

 **Note:** To execute the “COPY” command, you must be a superuser. Moreover, the targeted file must be accessible/readable directly by the Postgres Server.

 **Conclusion**

In PostgreSQL, creating a table from a CSV file means importing/loading a CSV file into the Postgres table. You must execute the COPY command to create a Postgres table via the CSV file. The “COPY” statement reads data from a file or standard input and inserts it into a Postgres table. The COPY command has options to specify the data format, the column names, and the delimiter used in the file. This blog explained how to create a Postgres table from a CSV file via practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-create-table-from-csv-file/)

---

# How to Concatenate Multiple Arrays in PostgreSQL

> PostgreSQL provides a built-in function named ARRAY_CAT() and a concatenation operator “||” that assists us in concatenating multiple arrays into a single arra…

As a database developer or data analyst, you may face a situation where you have to combine/merge multiple arrays into a single array. This can be challenging, especially when handling large data sets or working with arrays with different data types. So, how to tackle such scenarios?

Thankfully, PostgreSQL provides a built-in function named **ARRAY_CAT()** and a concatenation operator “ **||** ” that assists us in concatenating/combining multiple arrays into a single array.

This blog post will show you how to concatenate multiple arrays into one array using the concatenation operator and the **ARRAY_CAT()** function. So, let’s get started!

 **How to Concatenate Multiple Arrays in Postgres Via ARRAY_CAT()?**

The **ARRAY_CAT()** function accepts different arrays as arguments and retrieves a concatenated array. Whether you are working with alphabetic, numeric, or a combination of both, the **ARRAY_CAT()** function can assist you in each case. Use the following syntax to avail the functionality of the **ARRAY_CAT()** function:
    
    
    ARRAY_CAT(arr_1, arr_2, arr_3, … arr_N);

The **ARRAY_CAT()** function accepts an “n” number of arrays and combines them into one array.

 **Example: How to Concat Multiple Arrays Via ARRAY_CAT() in Postgres?**

We have already created a sample table named “staff_information”, whose data is shown in the following snippet:

Let’s concatenate the “ **st_name** ” and “ **st_email** ” arrays via the **ARRAY_CAT()** function:
    
    
    SELECT ARRAY_CAT(st_name, st_email) 
    FROM staff_information;

The output snippet shows that the targeted arrays have been combined successfully.

 **How to Concatenate Multiple Arrays in Postgres Via Concatenation Operator?**

You can also use the concatenation operator between different arrays to combine them into a single array. The below snippet shows the usage of the concatenation operator:
    
    
    SELECT array_3 || array_2 || … || array_n;

The above syntax shows that the “ **n** ” number of arrays can be combined using the concatenation operator.

 **Example: How to Concat Multiple Arrays Via Concatenation Operator in Postgres?**

In the following example, we will show you how to merge multiple arrays using the concatenation operator in Postgres:
    
    
    SELECT st_name || st_email AS merged_array
    FROM staff_information;

The above piece of code will combine the “ **st_name** ” and “ **st_email** ” arrays of the “ **staff_inforamation** ” table:

The output snippet shows that both columns have been concatenated successfully.

This way, you can concatenate two or more arrays in Postgres.

 **Conclusion**

PostgreSQL provides a built-in function named ARRAY_CAT() and a concatenation operator “||” that assists us in concatenating/combining multiple arrays into a single array efficiently. The ARRAY_CAT() function and the concatenation operator accept the “n” number of arrays and combine them into a single array. Through practical examples, this blog post explained how to concatenate multiple arrays into one array using the concatenation operator and the **ARRAY_CAT()** function.

---
[View this page online](https://www.commandprompt.com/education/how-to-concatenate-multiple-arrays-in-postgresql/)

---

# How to Set the Default User Password in PostgreSQL

> Execute the “ALTER USER” or “ALTER ROLE” command, followed by the default user name and the PASSWORD attribute to set the default user password in PostgreSQL.

Maintaining PostgreSQL's security is essential for database administrators. One way to accomplish this task is by setting a strong and unique password for the default user. This will protect your data and prevent unauthorized access to your database. In PostgreSQL, “postgres” is the default user, so you must log in as “postgres” to set the default user password.

This post will present a detailed guide on how to set/change the password for the default user in PostgreSQL. So, let’s start!

 **How Do I Change/Set the Default User Password in Postgres?**

PostgreSQL offers a couple of built-in commands, such as “ALTER USER” and “ALTER ROLE”, that are used to modify the user’s password. To set the default user password in Postgres, you can follow these steps:

 **Step 1: Login as Default User**

Launch the SQL Shell, and provide the current password, as shown in the following snippet:

Hit the enter button to log in as the default user:

The above snippet shows that you have successfully logged in as the default user.

 **Step 2: Change/Set the Default User Password**

Now, execute the “ALTER ROLE” or “ALTER USER” statement to modify the default user password:
    
    
    ALTER USER postgres PASSWORD 'new_password';

The above snippet shows that the default use has been altered successfully.

Alternatively, you can execute the “ALTER ROLE” statement as follows:
    
    
    ALTER ROLE postgres PASSWORD 'my_new_password';

The “ALTER ROLE” message in the output indicates that the default user password has been set/changed successfully.

This is how you can set the default user password in Postgres using “ALTER ROLE” or “ALTER USER” statements.

 **Conclusion**

PostgreSQL provides a couple of built-in statements, such as “ **ALTER USER** ” and “ **ALTER ROLE** ” that are used to modify the user’s password. In PostgreSQL, “postgres” is the default user, so you must log in as “postgres” to set the default user password. After that, execute either the “ALTER USER” or “ALTER ROLE” command with the PASSWORD attribute to set the default user password. This blog post presented step-by-step instructions to set the default user password in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-set-the-default-user-password-in-postgresql/)

---

# How to Round Timestamps in PostgreSQL

> In PostgreSQL, the DATE_TRUNC() function is a convenient way for truncating/rounding the timestamps to the desired level of precision.

Timestamps are crucial in databases, and Postgres is no exception, but sometimes you may want to truncate them to a certain level of precision. Especially while grouping data by date or time. For this purpose, you must use the **DATE_TRUNC()** function to truncate timestamps to the desired level of precision.

This blog presents a detailed guide on rounding a timestamp in Postgres. So, let’s start!

 **How to Round Timestamps in PostgreSQL?**

In PostgreSQL, the **DATE_TRUNC()** function is a convenient way for truncating timestamps. The **DATE_TRUNC()** function enables you to specify the timestamp field as well as the unit of time to which you want to truncate. For instance, by specifying the 'year' as an argument, you can truncate a timestamp to the nearest year.

 **Syntax**

The snippet provided below shows how to use the DATE_TRUNC() function in Postgres:
    
    
    DATE_TRUNC(dateField, timestamp);

Specify the date field, such as year, month, day, etc., and a timestamp. Consequently, the timestamp will be rounded/truncated based on the specified date field.

 **Note:** All the date field parts other than the targeted “date field” will be rounded to their initials. For instance, year, month, day, etc., will be rounded to “1”, and hours, minutes, seconds, etc., will be rounded to 0.

 **Example 1: How to Round/Truncate a Timestamp by Year in Postgres?**

In the following snippet, we will specify a “year” as the first argument to truncate a timestamp by year in Postgres:
    
    
    SELECT DATE_TRUNC('YEAR', DATE '2012-12-12');

The output snippet shows that the DATE_TRUNC() function rounded the given timestamp by nearest year.

 **Example 2: How to Round/Truncate a Current Timestamp by Day in Postgres?**

Let’s learn how to round a timestamp by day in Postgres:
    
    
    SELECT DATE_TRUNC('DAY', CURRENT_TIMESTAMP);

The output snippet shows that the DATE_TRUNC() function rounded/truncated the given timestamp by day.

 **Note:** Similarly, you can group data by month, hours, minutes, etc., using the DATE_TRUNC() function.

 **Example 3: How to Group by YEAR in Postgres Via DATE_TRUNC() Function?**

The following snippet shows the content of a sample table named "article_details":

Let’s group the table’s data by “Year” via the DATE_TRUNC() function:
    
    
    SELECT DATE_TRUNC('YEAR', published_date) AS published_year,
    COUNT(article_id) AS count
    FROM article_details
    GROUP BY DATE_TRUNC('YEAR', published_date);

The output snippet shows that the DATE_TRUNC() function groups the table’s data by year.

This is how you round a timestamp in Postgres via the DATE_TRUNC() function.

 **Conclusion**

In PostgreSQL, the **DATE_TRUNC()** function is a convenient way for truncating timestamps. The **DATE_TRUNC()** function enables you to specify the timestamp field as well as the unit of time to which you want to truncate. For instance, by specifying the 'year' as an argument, you can truncate a timestamp to the nearest year. This blog post explained the basic syntax, usage, and practical implementation of the DATE_TRUNC() function to round the timestamps in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-round-timestamps-in-postgresql/)

---

# How to Fix “Permission Denied” Error While Importing a CSV File in PostgreSQL

> Sometimes a “Permission Denied” error occurs while importing a CSV file into a Postgres table. To fix this error, you need to change the file reading permissio…

In PostgreSQL, the “ **COPY** ” command allows us to import or export data to and from a database. CSV files are commonly used when exchanging data between applications or systems. It is a fast and efficient way of loading gigantic amounts of data into the Postgres table. The “COPY” statement reads data from a CSV file or standard input and inserts it into a Postgres table. However, sometimes user’s encounter a “Permission Denied” error while importing a CSV file into a Postgres table.

This blog post will show you the possible causes and solutions for the “permission denied” error. So, let’s start!

 **How to Fix the “Permission Denied” Error While Importing a CSV File?**

This section will show you a step-by-step procedure to fix the “permission denied” error.

 **Step 1: Creating a CSV File**

Firstly, create a CSV file and specify some data in that file:

The above snippet shows a CSV file named "articles" that is saved at the following location: “ **C:\Users\DELL\Desktop** ”.

 **Step 2: Creating a Sample Table**

Let’s create a sample table via the below-provided command:
    
    
    CREATE TABLE articles_tab(
    a_id INT PRIMARY KEY,
    a_title TEXT,
    p_date DATE
    );

Execute the “ **SELECT *** ” command to verify the table’s creation:

The sample table has been created.

 **Step 3: How Does the “Permission Denied” Error Occur in Postgres?**

Let’s learn how to import the CSV file into the Postgres table:
    
    
    COPY articles_tab
    FROM 'C:\Users\DELL\Desktop\articles_data.txt'
    DELIMITER ','
    CSV HEADER;

While executing the above command, you may encounter the following error:

The output shows that an error occurred while importing a CSV file.

 **Step 4: How to Fix the “Permission Denied” Error?**

First, right-click on the targeted file and select “ **Properties** ”:

Once the “ **Properties** ” window is open, select the “ **Security** ” tab:

Now, hit the “ **Edit** ” button, and a new pop-up window will appear:

In the "Permissions" window, hit the “ **Add..** ” button:

Write “Everyone” in the "Object Names” text field and hit the OK button. Now select “everyone” from the “Permission” window, and tick the read permissions:

Finally, hit the “OK” button to save the settings.

 **Step 5: Import CSV File**

Now, let’s try one more time to import the CSV file via the following command:
    
    
    COPY articles_tab
    FROM 'C:\Users\DELL\Desktop\articles_data.txt'
    DELIMITER ','
    CSV HEADER;

The output shows that the “Permission Denied” error has been resolved. You can verify the inserted data via the “SELECT *” command:

The output verifies that the COPY command executed successfully, and hence the data from the CSV file has been imported into the Postgres table successfully.

 **Note:** the other possible reason can be executing the “COPY” command as an ordinary user. To fix this error, you must execute the COPY command as a superuser.

 **Conclusion**

PostgreSQL provides a "COPY" command to import and export data. The “COPY” statement reads data from a CSV file or standard input and inserts it into a Postgres table. However, sometimes user’s encounter a “Permission Denied” error while importing a CSV file into a Postgres table. To fix this error, you need to change the file reading permissions, as demonstrated in this guide. This blog explained how to fix the “Permission Denied” error while importing a CSV file in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-permission-denied-error-while-importing-a-csv-file-in-postgresql/)

---

# How to Add/Set a Default Value to a Column in PostgreSQL

> In Postgres, the DEFAULT keyword is used with the help of CREATE TABLE or ALTER TABLE statement to set a default value to a column.

Setting default values for columns helps ensure data integrity in your tables. If a default value is set, new rows in the table will be inserted with the default value for that column, regardless of whether it was explicitly specified or not. This can be especially useful when working with null values, as it helps prevent inserting NULL values in your data.

This write will teach you how to add or drop a default value from a table in Postgres using practical examples. In this regard, the following topics will be covered in this blog post:

  * Key Points
  * How to Add/Set a Default Value to a Column Via CREATE TABLE Statement?
  * How to Add/Set a Default Value to a Column Via ALTER TABLE Statement?
  * How to Drop the Column’s Default Value Using ALTER TABLE Statement?



So, let’s start!

 **Key Points**

The below-listed points must be kept in mind when setting default values for columns in Postgres:

  * In Postgres, the DEFAULT keyword is used with the help of CREATE TABLE or ALTER TABLE statement to set a default value to a column.
  * DEFAULT must be a constant expression; it cannot refer to any other column or variable.
  * The default value's data type must match the column's data type.
  * Default values should be chosen based on your data and use case.



 **How to Add/Set a Default Value to a Column Via CREATE TABLE Statement?**

You can set a default value for a column when you create a Postgres table using the CREATE TABLE statement. Here's the syntax of how you might do this:
    
    
    CREATE TABLE table_name (
    column_name DATA TYPE DEFAULT 'default_value'
    );

The above snippet shows that adding a default value to a column can be accomplished via the DEFAULT keyword.

 **Example: Setting a Default Column Value Via CREATE TABLE Statement**

Let’s learn how to add a default value to a column at the time of table creation:
    
    
    CREATE TABLE product_details(
    product_id INT PRIMARY KEY,
    product_price INT,
    purchase_date DATE DEFAULT CURRENT_DATE
    )

The above output shows that the “purchase_date” column has been created with a default value, i.e., “CURRENT_DATE”. Let’s insert a record into the “product_details” table to learn how the DEFAULT keyword works in Postgres:
    
    
    INSERT INTO product_details(product_id, product_price)
    VALUES (1, 2500);

We didn’t specify the value for the “purchase_date” column. However, a default value will be assigned to the “purchase_date” column because of the “DEFAULT” keyword. Let’s run the “SELECT *” command to see the table’s data:

The output authenticates the working of the DEFAULT keyword, as it successfully added a default value to the purchase date column.

 **How to Add/Set a Default Value to a Column Via ALTER TABLE Statement?**

The most common way to add a default value to a column is using the ALTER TABLE statement, which allows you to modify the structure of an existing table. Here's the syntax of how you might use ALTER TABLE statement to set a default value for a column:
    
    
    ALTER TABLE table_name 
    ALTER COLUMN column_name SET DEFAULT 'default_value';

 **Example: Setting a Default Column Value Via ALTER TABLE Statement**

Let’s learn how to set a default value for an existing column using the ALTER TABLE statement:
    
    
    ALTER TABLE product_details 
    ALTER COLUMN product_price SET DEFAULT 0;

A default value has been set for the “product_price” column. Now insert a new record into the product_details table to comprehend the working of the DEFAULT keyword:
    
    
    INSERT INTO product_details(product_id)
    VALUES (2);

Let’s verify the table’s data via the “SELECT *” command:

The output snippet clarifies that a default value has been inserted into the product_price column, proving the DEFAULT keyword's working.

 **How to Drop the Column’s Default Value Using ALTER TABLE Statement?**

If you no longer want to set a default value for a column, then you can use the ALTER TABLE statement to drop the default value:
    
    
    ALTER TABLE table_name 
    ALTER COLUMN column_name DROP DEFAULT;

 **Example: Dropping a Default Column Value Via ALTER TABLE Statement**

If the column’s default value is no longer needed, you can drop it using the ALTER TABLE command as follows:
    
    
    ALTER TABLE product_details
    ALTER COLUMN product_price DROP DEFAULT;

The output snippet shows that the DEFAULT value has been removed from the “product_price” column. Let’s run the INSERT INTO command to insert a new record into the “product_details” table:
    
    
    INSERT INTO product_details(product_id)
    VALUES (3);

Now execute the SELECT * command to see the newly inserted record:

A null value has been inserted for the “product_price” column, it proves that the DEFAULT VALUE feature has been removed from the “product_price” column.

 **Conclusion**

In Postgres, the DEFAULT keyword is used with the help of CREATE TABLE or ALTER TABLE statement to set a default value to a column. DEFAULT must be a constant expression; it cannot refer to any other column or variable. The DEFAULT value for a column is useful when working with null values, as it helps prevent inserting NULL values in your data. This Postgres blog explained several ways to add or remove default values from a column in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-addset-a-default-value-to-a-column-in-postgresql/)

---

# How to Extract Year From DATE in PostgreSQL

> To extract a year from a date, the built-in EXTRACT() and DATE_PART() functions are used in Postgres. To do so, pass the “YEAR&quot; and the timestamp as arguments …

Dates in any programming language are tricky to work with, and PostgreSQL is no exception. Dates manipulation is an essential skill for any developer, whether it is extracting the year from a database, date of birth field, or dealing with timestamp data in a server log.

In Postgres, extracting the year from a date value is a common task when working with dates. It can be used to group data by year, create date ranges, or simply display the year.

Several approaches are available in Postgres to extract the year from a date, and in this tutorial, we'll show you the most convenient and efficient ones. For this purpose, the following topics will be covered in this blog:

  * How to Extract a Year From DATE in Postgres?
  * How to Extract a Year From Current Date Using EXTRACT() Function?
  * How to Extract a Year From Current Date Using DATE_PART() Function?
  * How to Extract a Year From a Specific TIMESTAMP Via EXTRACT() Function?
  * How to Extract a Year From a Specific TIMESTAMP Via DATE_PART() Function?
  * How to Extract a Year From a Specific INTERVAL Using EXTRACT() Function?
  * How to Extract a Year From a Specific INTERVAL Using DATE_PART() Function?
  * How to Group Table Records by Year in Postgres?



So, let’s get started!

 **How to Extract a Year From DATE in Postgres?**

To extract a year from a date, the built-in EXTRACT() and DATE_PART() functions are used in Postgres. For instance, to extract the year from a date in Postgres via the EXTRACT() function, you can use the following syntax:
    
    
    SELECT EXTRACT('dateField' FROM TIMESTAMP | INTERVAL );

Similarly, to extract the year from a date in Postgres via the DATE_PART() function, users need to follow the below syntax:
    
    
    SELECT DATE_PART('dateField', TIMESTAMP | INTERVAL );

In place of dateField, you must specify the “ **Year** ” to extract the year from the given timestamp or interval.

 **How to Extract a Year From Current Date Using EXTRACT() Function?**

In Postgres, the NOW() and CURRENT_DATE functions are used to get the current date. So, we will pass one of these functions and a field to be extracted (i.e., “Year” in our case) to the EXTRACT() function to extract the desired date field from the current date:
    
    
    SELECT EXTRACT('Year' FROM CURRENT_DATE);

The output shows that the current year is “2022”.

 **How to Extract a Year From Current Date Using DATE_PART() Function?**

To extract the desired date field from the current date, let’s pass a field to be extracted (i.e., “Year” in our case) as a first argument and a NOW() function as the second argument to the DATE_PART() function:
    
    
    SELECT DATE_PART('Year', NOW());

The output verifies the working of the **DATE_PART()** function as it retrieves the appropriate result.

 **How to Extract a Year From a Specific TIMESTAMP Via EXTRACT() Function?**

Specify the timestamp and the field of your choice to the EXTRACT() function to extract a year from the specified timestamp:
    
    
    SELECT EXTRACT('Year' FROM TIMESTAMP '2010/12/12');

The year has been successfully extracted from the specified date via Postgres’ EXTRACT() function.

 **How to Extract a Year From a Specific TIMESTAMP Via DATE_PART() Function?**

To extract a particular year from a specific TIMESTAMP, you need to pass the “Year" as the first argument and the timestamp as the second argument to the **DATE_PART()** function:
    
    
    SELECT DATE_PART('Year', TIMESTAMP '2015-12-12');

The output snippet clarifies that the year has been successfully extracted from the specified timestamp via the DATE_PART function.

 **How to Extract a Year From a Specific INTERVAL Using EXTRACT() Function?**

To extract a year from a specific interval, you can use the EXTRACT() function as follows:
    
    
    SELECT EXTRACT(YEAR FROM INTERVAL '16 years 10 months 3 days');

The output snippet shows that the specified “year” has been successfully extracted from the given interval successfully.

 **How to Extract a Year From a Specific INTERVAL Using DATE_PART() Function?**

Let’s pass a “YEAR” as a first argument and a specific interval as a second argument to the DATE_PART() function:
    
    
    SELECT DATE_PART('YEAR', INTERVAL '10 years 7 months 3 days');

From the above snippet, you can notice that the year has been successfully extracted from the specified interval.

 **How to Group Table Records by Year in Postgres?**

Postgres' DATE_PART() and EXTRACT() functions can be used to group data by year. For instance, in the below snippet, we will use the DATE_PART() function to extract a year from the specified table’s column and then group these records by year:
    
    
    SELECT DATE_PART('YEAR', published_date) AS published_year,
    COUNT(article_id) AS count
    FROM article_details
    GROUP BY DATE_PART('YEAR', published_date);

Similarly, you can use the EXTRACT() function instead of the DATE_PART() function to extract a year from the specified column.

That’s all from this Postgres guide!

 **Conclusion**

To extract a year from a date, the built-in **EXTRACT()** and **DATE_PART()** functions are used in Postgres. To do so, you need to pass the “YEAR” as the first argument and the timestamp/interval as the second argument to any of these functions. Consequently, the year from the specified date fields will be extracted. This Postgres blog presented a detailed guide on extracting a year from a date in Postgres via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-extract-year-from-date-in-postgresql/)

---

# PostgreSQL DELETE CASCADE With Examples

> In PostgreSQL, the DELETE CASCADE feature allows us to delete the records associated with some other tables (via foreign key constraints).

In PostgreSQL, a **DELETE CASCADE** is a powerful feature that is useful when you have multiple tables linked with each other via foreign key constraints. When a DELETE CASCADE feature is enabled, deleting a record from the referenced/parent table will also delete the referencing records from the child table.

> Try the new PgManage (Open Source) and get rid of PgAdmin!

This Postgres blog will present a step-by-step guide on how to use the **DELETE CASCADE** option in Postgres. So, let’s start!

 **When to Use DELETE CASCADE in Postgres?**

For instance, consider a database with a "customer_details" and an "order_details" table. The "order_details" table is linked with the "customer_details" table through a foreign key constraint. Suppose a user wants to delete a customer from the "customer_details" table. Then to keep the database clean and organized, he might also want to delete all of the orders associated with that customer from the "order_details" table. This is where Postgres’ DELETE CASCADE feature is extremely useful!

 **How to Use DELETE CASCADE in Postgres?**

To use a delete cascade in Postgres, specify the " **ON DELETE CASCADE** " option while creating/defining a foreign key constraint. This tells Postgres to automatically delete any rows in the referenced table that are related to the row being deleted in the referencing table.

Let’s comprehend it practically!

> [ **Contact us**](<https://commandprompt.com/contact-us/>) **today for all your Postgres and Open Source consulting and support needs.**

 **Example: How Does the DELETE CASCADE Work in Postgres?**

This example will present the stepwise instructions to use the DELETE CASCADE option in Postgres:

 **Step 1: Create Sample Tables**

Firstly, let’s create a “cutomer_details” table with two columns: “cust_id” and “cust_name”:
    
    
    CREATE TABLE customer_details (
    cust_id INTEGER PRIMARY KEY,
    cust_name TEXT NOT NULL
    );

Now create one more table named “order_details” with two regular columns and a foreign key:
    
    
    CREATE TABLE order_details(
    order_id INTEGER PRIMARY KEY,
    customer_id INTEGER REFERENCES customer_details (cust_id) ON DELETE CASCADE,
    order_date DATE
    );

An “order_details” table with a foreign key named “customer_id” having the DELETE CASCADE feature enabled has been created.

 **Step 2: Insert Data Into Sample Tables**

Let’s insert some records into the “customer_details” table via the “INSERT INTO” command:
    
    
    INSERT INTO customer_details (cust_id, cust_name)
    VALUES(1, 'Joe'),
    (2, 'Mike'),
    (3, 'Joseph');

The specified data has been inserted into the “customer_details” table successfully. Now, execute the INSERT INTO command one more time to insert the data into the “order_details” table:
    
    
    INSERT INTO order_details (order_id, customer_id, order_date)
    VALUES(1, 1, '2022-12-12'),
    (2, 1, '2022-12-12'),
    (3, 2, '2022-11-15'),
    (4, 3, '2022-12-16'),
    (5, 2, '2022-12-18');

Five records have been inserted into the order_details table successfully.

 **Step 3: Verify Tables’ Data**

Execute the “SELECT *” query to check the data of the “customer_details” table:

Now execute the “SELECT *” command one more time to fetch the data of the “order_details” table:

The output snippet shows the data of both tables.

 **Step 4: DELETE CASCADE**

Since we set/enabled the DELETE CASCADE feature while creating a foreign key, so deleting a record from the “customer_details” table will also delete the corresponding record from the “order_details” table:
    
    
    DELETE FROM customer_details 
    WHERE cust_id = 1;

The output shows that the DELETE command was executed successfully.

 **Step 5: Verify Record’s Deletion**

To verify the working of the DELETE CASCADE feature, let’s execute the “SELECT *” command as follows:

The output snippet shows that the customer having id 1 has been deleted from the customer_details table. Now, let’s execute the “SELECT *” command one more time to see if the selected record has been deleted from the child table or not:

The output snippet proves that Postgres automatically deleted the targeted record from the child table. This is how the DELETE CASCADE feature works in Postgres.

 **Conclusion**

In PostgreSQL, a **DELETE CASCADE** allows us to delete the records associated with some other tables (via foreign key constraints). To use a delete cascade in Postgres, specify the " **ON DELETE CASCADE** " option while creating/defining a foreign key constraint. By doing so, Postgres will automatically delete any rows in the referenced table that are related to the row being deleted in the referencing table. This Postgres blog has explained the usage of the DELETE CASCADE keyword via practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-delete-cascade-with-examples/)

---

# How to Group by Month in PostgreSQL

> In Postgres, the EXTRACT(), DATE_TRUNC(), and DATE_PART() functions are used to extract the month from a date field and then use the GROUP BY clause to group t…

The **GROUP BY** clause in Postgres allows us to group the table’s data based on specific column(s), making it easy to analyze and understand relationships and patterns within your data. In Postgres, you can use the **EXTRACT()** , **DATE_TRUNC()** , and **DATE_PART()** function to extract the month from a date field and then use the **GROUP BY** clause to group the results by month.

This blog will show you how to group the table’s data by month in Postgres. In this regard, the below-listed topics will be covered in this Postgres blog:

  * Sample Table
  * How to Group by Month in Postgres Using EXTRACT() Function?
  * How to Group by Month in Postgres Using DATE_TRUNC() Function?
  * How to Group by Month in Postgres Using DATE_PART() Function?



So, let’s start!

 **Sample Table**

We have already created a sample table named “ **article_details** ”, whose content is shown in the below snippet:

The “ **article_details** ” table has three columns: article_id, article_title, and published_date. This post will show you how to group the table’s data by month in Postgres.

 **How to Group by Month in Postgres Using EXTRACT() Function?**

In Postgres, you can use the EXTRACT() function to extract a month from the specified column and then use the GROUP BY clause to group the table’s data by date:
    
    
    SELECT EXTRACT('MONTH' FROM published_date) AS published_month,
    COUNT(article_id) AS article_count
    FROM article_details
    GROUP BY EXTRACT('MONTH' FROM published_date);

The output shows that the table’s data has been grouped by month successfully.

 **How to Group by Month in Postgres Using DATE_TRUNC() Function?**

The DATE_TRUNC() function, along with the GROUP BY clause, is used in Postgres to group the table’s data by month:
    
    
    SELECT DATE_TRUNC('MONTH', published_date) AS published_month,
    COUNT(article_id) AS count
    FROM article_details
    GROUP BY DATE_TRUNC('MONTH', published_date);

The DATE_TRUNC() function will truncate all the fields after the month to their initials(such as time will be initialized with 0, and days will be initialized with 1):

The output verifies that the table’s data has been grouped by month successfully.

 **How to Group by Month in Postgres Using DATE_PART() Function?**

The DATE_PART() function in Postgres lets you extract a month from a column and then group the data by date using the GROUP BY clause:
    
    
    SELECT DATE_PART('MONTH', published_date) AS published_month,
    COUNT(article_id) AS count
    FROM article_details
    GROUP BY DATE_PART('MONTH', published_date);

The output snippet shows that the table’s data has been grouped by month successfully.

That’s it from this Postgres guide!

 **Conclusion**

In Postgres, the **EXTRACT()** , **DATE_TRUNC()** , and **DATE_PART()** functions are used to extract the month from a date field and then use the **GROUP BY** clause to group the results by month. For this purpose, specify the “MONTH” as the first argument to any of the functions mentioned above and then use the GROUP BY clause to group the table’s data by month. This Postgres blog explained how to group the table’s data by month using different methods.

---
[View this page online](https://www.commandprompt.com/education/how-to-group-by-month-in-postgresql/)

---

# How to Subtract Days From a Date in PostgreSQL

> In PostgreSQL, the DATE_PART() function, INTERVAL, and the minus “-” operator is used to subtract a single or multiple days from a particular date.

Subtracting days from a date is a common task that you may need to perform while calculating the expiry dates, finding the difference between two dates, or simply adjusting a date to a past or future date. Thankfully, Postgres offers some in-built functions and operators that make it easy to subtract days from a date.

This Postgres blog will teach you how to use the Postgres **INTERVAL** , **DATE_PART()** function, and the **minus** “ **-** ” operator to subtract days from a date. The content of this blog will be organized as follows:

  * Subtracting Days From a Date Using a MINUS Operator
  * Subtracting Days From a Date Using INTERVAL
  * Subtracting Days From a Date Using DATE_PART() Function



So, let's get started!

 **Subtracting Days From a Date Via a MINUS Operator**

To subtract a single or multiple days from a date, use the minus "-" operator as follows:
    
    
    DATE 'dateField' - days;

In place of days, specify the number of days to be subtracted.

 **Example 1: How to Get the Current Date in Postgres?**

In Postgres, the CURRENT_DATE and NOW() functions are used to get the current date. In the following example, we will use the CURRENT_DATE function to find today’s date:
    
    
    SELECT CURRENT_DATE;

The output snippet shows that today’s date is 26th December 2022.

 **Example 2: Subtract One Day From the Current Date**

The below statement shows how to subtract a day from today’s date:
    
    
    SELECT CURRENT_DATE - 1;

In the above snippet, the CURRENT_DATE is used to get today’s date, while “1” represents the number of days to be subtracted from the current date:

The output shows that the MINUS operator subtracted one day from the current date.

 **Example 3: Subtract Multiple Days From Current Date?**

To subtract multiple days from the current date, you need to specify the CURRENT_DATE followed by the minus operator and then the number of days to be subtracted :
    
    
    SELECT CURRENT_DATE - 12;

The output verifies the working of the minus operator.

 **Example 4: Subtract Days From a Specific Date?**

Let’s learn how to subtract days from a specific date field using the minus operator:
    
    
    SELECT DATE '2019-11-14' - 18;

The output snippet authenticates the working of the minus operator.

 **Subtracting Days From a Date Via INTERVAL**

Another very convenient way to subtract days from the date is INTERVAL, as shown in the following snippet:
    
    
    DATE 'dateField' - INTERVAL 'no_of_days';

In place of days, specify the number of no_of_days to be subtracted.

 **Example 1: How to Subtract Specific Days From a Date Using Interval?**

Let’s learn how to use interval for subtracting days from a date in Postgres:
    
    
    SELECT DATE '2022-10-22' - INTERVAL '8 days';

The output snippet clarifies that the specified days have been subtracted from the given date.

 **Example 2: Specify Days Equivalent Hours to Subtract Days From a Date Using Interval**

In the following snippet, we will subtract two days from a specific date field by specifying the hours instead of days:
    
    
    SELECT DATE '2022-10-22' - INTERVAL '48 hours';

The output snippet clarifies that the two days have been subtracted from the given date.

 **Subtracting Days From a Date Via DATE_PART() Function**

Postgres offers a built-in DATE_PART() function that can be used to subtract the days from a month. To do so, use the below-provided syntax:
    
    
    DATE_PART('day', 'dateField' - no_of_days);

Specify the days to be subtracted in place of “no_of_days”.

 **Example 1: How to Subtract Days From Current Date Using DATE_PART() Function?**

In the following example, we will subtract seven days from the current date:
    
    
    SELECT DATE_PART('day', CURRENT_DATE - 7);

The output snippet proves the appropriateness of the DATE_PART() function.

 **Example 2: How to Subtract Days From a Specific Date Using DATE_PART() Function?**  
The below piece of code will subtract twelve days from the given date field via the DATE_PART() function:
    
    
    SELECT DATE_PART('day', DATE '2022-12-12' - 7);

The output shows that the DATE_PART() function subtracted the specified days from the given date field.

 **Conclusion**

In PostgreSQL, the DATE_PART() function, INTERVAL, and the minus “-” operator is used to subtract a single or multiple days from a particular date. The MINUS operator and INTERVAL are the most convenient and widely used approaches for subtracting the days from a date. This Postgres blog explained various methods for subtracting days from a date in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-subtract-days-from-a-date-in-postgresql/)

---

# PostgreSQL NOT Operator/Condition With Examples

> The NOT operator is a frequently used operator in Postgres that negates a boolean expression. It allows us to filter or exclude certain data from the query’s r…

The NOT operator is a frequently used operator in Postgres that negates a boolean expression. It's incredibly useful when filtering or excluding certain records from your result set. In Postgres, the NOT operator has various use cases, including in the WHERE clause of a SELECT statement, in the ON clause of a JOIN, and even in a CHECK constraint.

This blog will explain how the NOT operator can be used to manipulate and analyze data in Postgres. So, let’s begin.

 **NOT Operator/Condition in PostgreSQL**

The NOT operator in Postgres allows us to filter or exclude certain data from the query’s result set, providing greater control over the information returned by any query. It can be used/combined with other logical/comparison operators, such as IN, BETWEEN, EXISTS, etc. To use the NOT operator in Postgres, users must follow the below-provided syntax:
    
    
    NOT condition;

The most frequent use of the NOT operator is in the WHERE clause of a SELECT query.

 **Sample Table**

We have already created a table named “emp_information”, whose data is shown in the following snippet:
    
    
    SELECT * FROM emp_information;

We will use the above table in all the examples.

 **Example 1: How to Use NOT Operator With IN Operator in Postgres?**

The IN operator checks whether a value belongs to a list of values. However, using IN operator with NOT operator will negate the original result of the IN operator:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary NOT IN(3800, 3851, 4500, 5000);

The output shows that the NOT operator retrieves all the records except the specified ones.

 **Example 2: How to Use NOT Operator With BETWEEN Operator in Postgres?**

Using the NOT operator with BETWEEN operator will negate the original result of the BETWEEN operator:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary NOT BETWEEN 3800 AND 5000;

The above snippet proves the working of the NOT operator in Postgres.

 **Example 3: How to Use/Combine NOT Operator With IS NULL Operator in Postgres?**

The IS NULL operator retrieves the null values; however, using a NOT operator with IS NULL operator will retrieve all the non-null values:
    
    
    SELECT emp_name, emp_salary 
    FROM emp_information
    WHERE emp_salary IS NOT NULL;

The output authenticates the working of the NOT operator.

 **Example 4: How to Use NOT Operator With LIKE Operator in Postgres?**

The below-provided query will find the employees whose name doesn’t start with “J”:
    
    
    SELECT *
    FROM emp_information
    WHERE emp_name NOT LIKE 'J%';

The output shows that the NOT operator negates the working of the LIKE operator.

That’s it from this guide!

 **Conclusion**

The NOT operator is a frequently used operator in Postgres that negates a boolean expression. It allows us to filter or exclude certain data from the query’s result set, providing greater control over the information returned by any query. The NOT operator can be combined with other operators, such as IN, BETWEEN, EXISTS, etc. This blog explained the usage of the NOT operator via several practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-not-operatorcondition-with-examples/)

---

# PostgreSQL Numeric Data Type With Practical Examples

> In PostgreSQL, the NUMERIC data type is a more precise data type used to store decimal values. It can be defined with specific precision and scale.

Numeric data types are an essential part of any database system, and PostgreSQL is no exception. These data types allow us to store and manipulate numbers in various formats, from simple integers to complex decimal values. These data types include INTEGER, **NUMERIC** , BIGINT, etc., each of which is designed to store different types of numerical values.

The **NUMERIC** data type is a more precise data type that is used to store decimal values. It can be defined with specific precision and scale, allowing us to specify the number of decimal places to be stored.

This blog will explain the usage of the **NUMERIC** data type in Postgres via Practical examples. So, let’s start!

 **PostgreSQL Numeric Data Type**

The **NUMERIC** data type is a high-precision decimal data type in Postgres that is suitable for storing numbers requiring many decimal places. Here is the syntax to use the **NUMERIC** data type in Postgres:
    
    
    NUMERIC(precision, scale);

Here, the precision represents the total number of digits, while the scale parameter represents the number of fractional digits. For instance, a numeric value “13411.267” has a precision “ **8** ” and a scale “ **3** ”. The scale parameter is optional and can be omitted. Omitting the scale part will store the numeric values without the fractional part.

 **Example 1: Create a Column With NUMERIC Data Type (With Scale)**

In this example, we will create a table named “emp_data” with three columns: “ **emp_id** ”, “ **emp_name** ”, and “ **emp_salary** ”:
    
    
    CREATE TABLE emp_data (
    emp_id SERIAL PRIMARY KEY, 
    emp_name TEXT NOT NULL, 
    emp_salary NUMERIC(6,2)
    );

In this example, we created a column with NUMERIC data type having precision “6” and scale “2”:

The above snippet verifies that a table named emp_data with three columns has been created successfully. To insert the data into the “emp_data” table, you need to run the “INSERT INTO” statement as follows:
    
    
    INSERT INTO emp_data (emp_name, emp_salary)
    VALUES('Tim', 5500.5555),
    ('David', 4500.1234),
    ('Joseph', 4000.412),
    ('Joe', 3500.515),
    ('John', 3850.7123);

Let’s query the table’s data via the below-provided command:
    
    
    SELECT * FROM emp_data;

From the output, you can observe that the fractional part has been trimmed to two decimal places because the scale was set to “2”.

 **Example 2: Create a Column With NUMERIC Data Type (Without Scale)**

In this example, we will show you the usage of NUMERIC data type without the “scale” parameter:
    
    
    CREATE TABLE emp_information (
    emp_id SERIAL PRIMARY KEY, 
    emp_name TEXT NOT NULL, 
    emp_salary NUMERIC(6)
    );

The table with desired columns has been created. Now, it's time to insert the employee information into the newly created “employee_information” table:
    
    
    INSERT INTO emp_information (emp_name, emp_salary)
    VALUES('Tim', 5500.5555),
    ('David', 4500.1234),
    ('Joseph', 4000.412),
    ('Joe', 3500.515),
    ('John', 3850.7123);

Now execute the “ **SELECT *** ” command to verify the data insertion:
    
    
    SELECT * FROM emp_information;

The output snippet shows that the NUMERIC values are stored in the table without fractional parts. This is how the NUMERIC data type works if you omit the “scale” parameter.

That’s all from this Postgres guide!

 **Conclusion**

The **NUMERIC** data type is a more precise data type used to store decimal values. It can be defined with specific precision and scale, allowing us to specify the number of decimal places to be stored. The scale parameter is optional and can be omitted. Omitting the scale part will store the numeric values without the fractional part. This blog post explained what NUMERIC data type is, its basic syntax, and suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-numeric-data-type-with-practical-examples/)

---

# How to List Sessions/Active Connections in PostgreSQL

> Postgres allows you to find the list of active connections on your database server via the &quot;pg_stat_activity&quot; and pgAdmin&#x27;s &quot;Server Activity panel”.

If you are a Postgres database administrator or developer, you must be able to monitor and manage active connections on your database server. Knowing which connections are active can assist you in identifying potential problems, optimizing performance, and ensuring the smooth operation of your database.

This Postgres tutorial will guide you on how to find the list of active connections in PostgreSQL through practical demonstration. So, let’s start!

 **How to List Sessions/Active Connections in PostgreSQL?**

In Postgres, finding the list of sessions/connections currently active on your PostgreSQL database server can be accomplished via the “ **pg_stat_activity** ” and pgAdmin’s “ **Server Activity panel** ”.

 **1)** **Using pg_stat_activity View**

The view “ **pg_stat_activity** ” provides information about currently executing queries and other details, such as the user and client host for each session. The details about the pg_stat_activity view are listed below:

 **pid:** the process ID of the backend process managing the session.  
 **usename:** user’s name connected to the current session.  
 **datname:** the database’s name the backend process is linked to.  
 **state:** the session's current state (e.g., idle, active).  
 **backend_start:** the timestamp of when this session was started.  
 **xact_start:** the timestamp at which the current transaction was started(if any).  
 **query_start:** the timestamp of when the current query was started (if any).  
 **client_addr:** the client address for the session.  
 **client_hostname:** the client hostname (if available).  
 **client_port:** the client port for the connection.  
 **query:** the current query being executed (if any).  
 **waiting:** a boolean indicating whether the session is waiting on a lock (true) or not (false).

Let's look at how the pg_stat_activity view works via practical examples.

 **Example: How to List Sessions/Active Connections in Postgres Via pg_stat_activity View?**

Executing the below-provided command will retrieve the list of the currently active connections/sessions in your database:
    
    
    SELECT * FROM pg_stat_activity;

Move the slider to the right to see more details regarding currently active connections. The pg_stat_activity view retrieves all the columns, indicating the connection’s details. However, using the WHERE clause, you can also filter the results of pg_stat_activity. For instance, the below-provided query will return the name of the process, user, and current state:
    
    
    SELECT pid, usename, state
    FROM pg_stat_activity;

This is how the “pg_stat_activity” view works in Postgres.

 **2)** **Using Server Activity Panel**

Another GUI-based alternate method for finding the active connections is using pgAdmin’s “ **Server Activity panel** ”. For that, select the database from the browser pane and then click on the “Dashboard” tab:

Now, in the server activity, you can see all the details regarding the active connections:

This is how you can check the active connections in Postgres.

 **Conclusion**

Postgres allows you to find the list of active sessions/connections on your PostgreSQL database server via the " **pg_stat_activity** " and pgAdmin's " **Server Activity panel** ”. Both these approaches provide information about currently executing queries and other details, such as the user and client host for each session. This blog explained how to check the active connections in Postgres using different methods.

---
[View this page online](https://www.commandprompt.com/education/how-to-list-sessionsactive-connections-in-postgresql/)

---

# How to Show List of All Databases and Tables in PostgreSQL

> In Postgres, the “\l”, “\list”, and “pg_catalog” are used to show the list of databases, while the “\dt” and “pg_catalog.pg_table” are used to show the list of…

PostgreSQL allows us to perform operations on the databases and tables, such as creation, updation, deletion, etc. In Postgres, performing any task on an existing database or table requires the name of that particular database or table. However, trying to remember the names of all of your PostgreSQL databases and tables is not an easy task. Therefore, Postgres provides simple commands to list all your databases and tables to deal with such scenarios.

This blog will show you how simple commands/statements are used to list all your Postgres databases and tables. So, let’s start!

 **How to Show a List of All Databases and Tables in PostgreSQL?**

To get the list of databases, the “\l” command and pg_database catalog are used in Postgres. Let’s learn how to find the list of all databases using the “\l” command in Postgres:

 **Open SQL Shell:**

Firstly, launch the psql, and provide the required details to log in:

Once logged in, you will get an interface similar to the above one.

 **1)** **Show Databases Via \l:**

To show the list of all the databases, users must execute the “\l” command as follows:
    
    
    \l

The output snippet shows the list of all the available databases, including default/system databases.

 **Note:** Execute the “ **\l+** ” command to get the list of databases with more details like database size, description, etc.

 **2)** **Show Databases Via \list:**

Alternatively, you can execute the “\list” command as follows:
    
    
    \list

The list of databases contains all the default and user-defined databases.

 **3)** **Show Databases Via pg_catalog:**

Run the below-provided command to get the list of databases using the pg_database catalog:
    
    
    SELECT oid, datname 
    FROM pg_database;

The output snippet shows the list of all the available databases.

Now, let’s learn how to show the list of all the tables in Postgres.

 **Connect to a Database**

Firstly, you need to connect to a particular database; for this purpose, you must execute the “\c” command:
    
    
    \c example;

Once connected to the database of your choice, now, you can show the list of tables available in that particular database via the following methods:

 **1)** **List Tables Via “\dt”**

Executing the below-provided command will show you the list of tables available in the “example” database:
    
    
    \dt;

The output shows that the “\dt” command successfully shows the list of relations.

 **Note:** Execute the “\dt+” command to show the list of relations with more details, like description, access method, table size, etc.

 **2)** **List Tables Via pg_catalog**

Alternatively, you can use the pg_catalog schema to show the list of all tables:
    
    
    SELECT * FROM pg_catalog.pg_tables;

The output snippet shows all the tables, including system and user-defined tables. To show only user-defined tables, you must use the WHERE clause as follows:
    
    
    SELECT tablename
    FROM pg_catalog.pg_tables
    WHERE schemaname NOT IN ('pg_catalog','information_schema');

This is how you can show the list of all the databases and tables in Postgres.

 **Conclusion**

In PostgreSQL, the “ **\l** ”, “ **\list** ”, and “ **pg_catalog** ” are used to show the list of databases, while the “ **\dt** ” command and “ **pg_catalog.pg_table** ” schema is used to show the list of relations. Use the “\l+” and “\dt+” commands to get the more detailed information regarding the databases and tables. This Postgres blog explained how to show the list of databases and tables in Postgres via practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-show-list-of-all-databases-and-tables-in-postgresql/)

---

# Date Time Functions in PostgreSQL With Examples

> Postgres offers a wide range of built-in functions to efficiently manipulate date and time values. For instance, NOW(), TO_TIMESTAMP(), CURRENT_DATE, etc.

PostgreSQL offers many powerful and convenient date and time functions for working with dates and times. These functions assist the users in manipulating the date and time values efficiently. For instance, storing a date or time value in a database, getting the current date or time, extracting a specific date or time part, etc.

In this Postgres blog, we are going to discuss the most frequently used date and time functions via Practical examples:

 **Date/Time Functions in PostgreSQL With Examples**

This section will explain the working of the below-listed frequently used date-time functions via syntax and examples:

  * CURRENT_DATE
  * CURRENT_TIME
  * NOW()
  * TIMEOFDAY()
  * CURRENT_TIMESTAMP
  * LOCALTIMESTAMP
  * DATE_PART()
  * DATE_TRUNC()
  * EXTRACT()
  * TO_DATE()
  * ISFINITE()
  * AGE()
  * TO_TIMESTAMP()



So, let’s begin with the “CURRENT_DATE” function.

 **1)** **Postgres CURRENT_DATE Function**

The below-mentioned points illustrate the working of the Postgres [CURRENT_DATE](<https://commandprompt.com/education/how-to-format-a-date-in-postgresql/>) function:

\- In PostgreSQL, the **CURRENT_DATE** function is used to get the current/today’s date and time.  
\- It retrieves the date in “YYYY-MM-DD” format.

 **Basic syntax**

Follow the below syntax to avail the functionality of the **CURRENT_DATE** function:
    
    
    CURRENT_DATE;

The CURRENT_DATE function doesn’t accept any argument.

 **Return Type** : “DATE”.

 **Example: How to Use CURRENT_DATE in Postgres?**

The below snippet explains the working of the CURRENT_DATE function:
    
    
    SELECT CURRENT_DATE;

The output shows that the CURRENT_DATE function retrieves the current date in “ **YYYY-MM-DD** ” format.

 **2)** **CURRENT_TIME Function**

The following points illustrate how the Postgres [CURRENT_TIME](<https://www.commandprompt.com/education/postgresql-current_time-function-with-practical-examples/>) function works:

\- As the name suggests, Postgres’ **CURRENT_TIME** function is used to get the current time.  
\- It can accept an optional parameter “ **precision** ” that is used to specify the fractional seconds’ precision.  
\- It retrieves the time along with the time zone.

 **Basic syntax**

Follow the below syntax to avail the functionality of the **CURRENT_TIME** function:
    
    
    CURRENT_TIME;

 **Return Type:** “TIMESTAMPTZ”.

 **Example: How to Use CURRENT_TIME in Postgres?**

The below snippet explains the working of the CURRENT_TIME function:
    
    
    SELECT CURRENT_TIME;

The output shows that the targeted function retrieves the current time and the time zone.

 **3)** **Postgres NOW() Function**

Consider the following points to comprehend the working of the [NOW()](<https://www.commandprompt.com/education/postgresql-now-function-with-practical-examples/>) function:

\- Postgres offers an inbuilt date function named NOW() that retrieves the current date, time, and timezone.  
\- The NOW() function doesn’t require any argument.  
\- It retrieves the date in the “ **YYYY-MM-DD HH-MM-SS.MS-TZ** ” format.

 **Basic Syntax**

You must follow the below syntax to use the **NOW()** function in Postgres:
    
    
    NOW();

 **Return Type** : TIMESTAMPTZ.

 **Example: How Does the NOW() Function Work in Postgres?**

The below-stated piece of code will show you the current date, time, and time zone based on your system’s date:
    
    
    SELECT NOW();

The output proves the working of Postgres’ NOW() function.

 **4)** **Postgres TIMEOFDAY() Function**

The following points will assist you in understanding the working of Postgres’ **TIMEOFDAY()** function:

\- In Postgres, TIMEOFDAY() is a built-in date function that retrieves the current date and time.  
\- It retrieves the date/time in “Day Mon DD HH-MM-SS.MS YYYY TZ” format.

 **Basic Syntax**

You must follow the below syntax to use the TIMEOFDAY() function in Postgres:
    
    
    TIMEOFDAY();

 **Return Type:** TEXT.

 **Example: How Does the TIMEOFDAY() Function Work in Postgres?**

Execute the below line of code to obtain the date-time in “Text” format:
    
    
    SELECT TIMEOFDAY();

The output shows that the **TIMEOFDAY()** function retrieves the current date and time in TEXT format.

 **5)** **Postgres CURRENT_TIMESTAMP Function**

The below-listed points elaborate on the working of the [CURRENT_TIMESTAMP](<https://www.commandprompt.com/education/postgresql-current_timestamp-function-with-examples/>) function:

\- The **CURRENT_TIMESTAMP** function in Postgres retrieves the current date, time, and timezone at which a transaction begins.  
\- It retrieves the date/time in the “YYYY-MM-DD HH-MM-SS.MS-TZ” format.

 **Basic Syntax**

The syntax for using the CURRENT_TIMESTAMP is as follows:
    
    
    CURRENT_TIMESTAMP;

 **Return Type:** TIMESTAMPTZ.

 **Example: How to Use CURRENT_TIMESTAMP in Postgres?**

Executing the below line of code will show you how the CURRENT_TIMESTAMP function works in Postgres:
    
    
    SELECT CURRENT_TIMESTAMP;

The output snippet shows that the targeted function retrieves the timestamp with the time zone.

 **6)** **Postgres LOCALTIMESTAMP Function**

The below-listed points will help you understand the working of the [LOCALTIMESTAMP](<https://www.commandprompt.com/education/postgresql-current_timestamp-vs-localtimestamp/>) function:

\- Another widely used built-in function is LOCALTIMESTAMP, which retrieves the time and date at which the current transaction began.  
\- It retrieves the date/time in the “YYYY-MM-DD HH-MM-SS.MS” format.

 **Basic Syntax**

 **LOCALTIMESTAMP** function can be accessed using the following syntax:
    
    
    LOCALTIMESTAMP;

 **Return Type:** TIMESTAMP.

 **Example: How to Use the LOCALTIMESTAMP Function in Postgres?**

Run the following line of code to get the current date and time without the time zone:
    
    
    SELECT LOCALTIMESTAMP;

The output shows that the specified function retrieves the date and time without a time zone.

 **7)** **Postgres DATE_PART() Function**

[DATE_PART()](<https://commandprompt.com/education/how-to-use-date_trunc-function-in-postgresql/>) is a built-in function in Postgres that is used to get only a specific part/field of timestamp, date, interval, etc.

\- It accepts a field and a source as arguments.  
\- The value for the field argument should be valid.

 **Basic Syntax**

The syntax for using the DATE_PART() function is as follows:
    
    
    DATE_PART(field, source);

The above snippet shows that the DATE_PART() function accepts two arguments: a field and a source. The DATE_PART() function will extract/pull out the field from the specified source.

 **Return Type:** DOUBLE PRECISION.

 **Example: How Does the DATE_PART() Function Work in Postgres?**

Suppose we want to pull out a year from a specific date; for this purpose, we will use the DATE_PART() function as follows:
    
    
    SELECT DATE_PART('Year', TIMESTAMP '2022-12-09');

The output snippet shows that the DATE_PART() function pulls out the year from the given date.

 **8)** **Postgres DATE_TRUNC() Function**

In PostgreSQL, DATE_TRUNC() is a built-in date function that truncates/trims the unnecessary part from the date/time.

\- It accepts two arguments, a datePart, and a field.  
\- The value for the field parameter must be valid.  
\- It retrieves the trimmed part with a specific precision level.  
\- Using the DATE_TRUNC() function, all values of the given field except the specified date will be reset to their initials.

 **Basic Syntax**

Use the below syntax to avail the services of the DATE_TRUNC() function:
    
    
    DATE_TRUNC(datePart, field);

The datePart must be valid, as described in the “[DATE_TRUNC() Function in Postgres](<https://commandprompt.com/education/how-to-use-date_trunc-function-in-postgresql/>)” blog. While in place of a field argument, you can specify an INTERVAL or TIMESTAMP.

 **Return Type:** TIMESTAMP.

 **Example: How Does Postgres ' DATE_TRUNC() Work?**

Let’s learn how the DATE_TRUNC() function work in Postgres:
    
    
    SELECT DATE_TRUNC('Year', TIMESTAMP '2022-08-02 11:12:14');

The output shows that the DATE_TRUNC() function resets all the values of the input timestamp(other than the specified date part, i.e., “Year” in the above example) to their initials.

 **9)** **Postgres EXTRACT() Function**

In Postgres, the built-in [EXTRACT()](<https://commandprompt.com/education/how-to-use-extract-function-in-postgresql/>) function works the same way as the **DATE_PART()** function:

\- It is used to extract a particular field from the input **TIMESTAMP**.  
\- The return type of the **EXTRACT()** function is **DOUBLE PRECISION**.

 **Basic Syntax**

The basic syntax of the **EXTRACT()** function will go like this:
    
    
    EXTRACT(Field FROM Source);

The above syntax shows that the **EXTRACT()** function accepts two arguments: a field and a source. The EXTRACT() will extract the specified field from the given source.

 **Example: How Do I Use the EXTRACT() Function in Postgres?**

Suppose we need to extract the minutes from the current date/time; to do that, we will utilize the EXTRACT() function as follows:
    
    
    SELECT EXTRACT('MIN' FROM NOW());

The output snippet shows that minutes were successfully extracted from the current date and time.

 **10)** **Postgres TO_DATE() Function**

Postgres offers an in-built [TO_DATE()](<https://commandprompt.com/education/postgresql-to_date-function-convert-string-to-date/>) function that is used to convert a string/text into a date:

\- It accepts a string and a valid date format as arguments.  
\- The date format must be a valid pattern/format, as demonstrated in the following blog: “[Postgres’ TO_DATE() Function](<https://commandprompt.com/education/postgresql-to_date-function-convert-string-to-date/>)”.  
\- It converts the input string into a date according to the defined format.

 **Basic Syntax**

Postgres' **TO_DATE()** function can be accessed using the following syntax:
    
    
    TO_DATE(string, date_format);

The above snippet indicates that the **TO_DATE()** function accepts a string and a date_format as an argument. Consequently, it will convert the input string into a date based on the specified date_format.

 **Return Type:** “DATE”.

 **Example: How Do I Use the TO_DATE() Function in Postgres?**

To demonstrate how the TO_DATE() function works, let's pass a string and a date format as arguments:
    
    
    SELECT TO_DATE('2022-12-09','YYYY-MM-DD');

The output authenticates that the given string has been converted into the DATE data type.

 **11)** **Postgres ISFINITE() Function**

In Postgres the **ISFINITE()** Function is used to check if a date/time/interval is finite or not:

\- It accepts a date, time, or an interval as an argument and retrieves a boolean value.  
\- Retrieving a “ **TRUE** ” value means the specified date, time or interval is finite.  
\- Retrieving a “FALSE” value means the specified date, time or interval is infinite.

 **Basic Syntax**

Postgres' **ISFINITE** function can be accessed using the following syntax:
    
    
    ISFINITE(TIME | DATE | INTERVAL);

The return type of the ISFINITE() function is Boolean.

 **Example: How to Use the ISFINITE Function in Postgres?**

In this example, we will pass the NOW() function as an argument to the ISFINITE() function.
    
    
    SELECT ISFINITE(NOW());

The output shows that the given argument is finite.

 **12)** **Postgres AGE() Function**

Postgres provides a built-in [AGE()](<https://www.commandprompt.com/education/postgresql-age-function-with-examples/>) function that accepts two dates as arguments and finds the interval between the given dates. The second time stamp will be subtracted from the first one, and the resultant interval will be returned as output.

 **Basic Syntax**

Use the following syntax to get the services of the Postgres AGE() function:
    
    
    AGE(TIMESTAMP_1, TIMESTAMP_2);

 **Return Type:** INTERVAL.  
 **Example: How Do I Use the AGE() Function in Postgres?**

Let’s suppose we want to calculate the age of a person whose birth date is “1990-01-01”. To do that, we will execute the AGE() function as follows:
    
    
    SELECT AGE(CURRENT_DATE, '1990-01-01');

The output shows that the AGE() function calculates the age and retrieves an INTERVAL.

 **13)** **Postgres TO_TIMESTAMP() Function**

In Postgres, the built-in [TO_TIMESTAMP](<https://www.commandprompt.com/education/postgresql-to_timestamp-function-with-examples/>)() function is used for the string-to-timestamp conversion.

\- It accepts a string and a valid format as arguments.  
\- The format must be valid, as described in [this](<https://www.commandprompt.com/education/postgresql-to_timestamp-function-with-examples/>) blog post.

 **Basic Syntax**

The basic syntax of the **TO_TIMESTAMP()** function will go like this:
    
    
    TO_TIMESTAMP(timestamp, format);

The above syntax shows that the **TO_TIMESTAMP()** function accepts two arguments: a timestamp(as a string) and a format. The input string will be converted into a timestamp according to the defined format.

 **Return Type:** TIMESTAMPTZ.

 **Example: How Does the TO_TIMESTAMP() Function Work in Postgres?**

Suppose we need to convert a “2022-12-12” string to a timestamp; for that purpose, we will execute the TO_TIMESTAMP function as follows:
    
    
    SELECT TO_TIMESTAMP('2022-12-12', 'YYYY-MM-DD');

The output snippet shows that the input string has been converted into a timestamp.

That’s it from this Postgres blog.

 **Conclusion**

A wide range of built-in functions is available in PostgreSQL for working with dates and times. Using these functions, users can manipulate date and time values efficiently. For instance, functions like NOW(), CURRENT_DATE, CURRENT_TIME, etc., are used to get the current date or time. The AGE() function is used in Postgres to find a specific interval. While to extract a specific date-time part, the functions like EXTRACT(), DATE_PART(), etc., are used in Postgres. This Postgres blog has explained different date-time functions with practical examples.

---
[View this page online](https://www.commandprompt.com/education/date-time-functions-in-postgresql-with-examples/)

---

# How to Add Days to a Date in PostgreSQL

> Postgres allows us to add a certain number of days to a date field using the plus “+” operator. It retrieve a new date representing the original date plus the …

In SQL Server, a built-in function named DATEADD() is used to add days to a date. However, Postgres doesn’t support the DATEADD() function. In Postgres, the functionality of the DATEADD() function can be achieved via the “+” operator. The plus "+" operator in Postgres allows us to add specific days to a date field.

How to add days to a date field will be explained in this Postgres blog using Practical examples. So, let’s get started!

 **Postgres Add Days to Date**

To add a specific number of days to a date, users must use the plus “+” operator as follows:
    
    
    date_field + num_of_days;

The plus operator will retrieve a new date representing the original date plus the specified number of days.

 **Example 1: Find the Current Date**

Let’s first find today’s date using the below-provided command:
    
    
    SELECT CURRENT_DATE;

The output snippet shows that the current date is “2022-12-22”.

 **Example 2: Add Five Days to the Current Date**

Use the “+” operator to add 5 days to the current date:
    
    
    SELECT CURRENT_DATE + 5;

The output snippet shows that five days have been added to the current date successfully.

 **Example 3: Add INTERVAL to the Current Date**

You can also add the days to the date using the INTERVAL data type:
    
    
    SELECT CURRENT_DATE + INTERVAL '3 days';

Three days have been added to the current date successfully.

 **Example 4: Add 3 Days to a Specific Date Field**

You can add days to any specific date field as follows:
    
    
    SELECT DATE '2022-12-12' + 3;

The output snippet shows that three days have been added to the input date field.

 **Example 5: Add a Negative Number(Days) to a Specific Date Field**

Specifying a negative value will subtract the specified number of days from the given date field:
    
    
    SELECT DATE '2022-12-12' + INTERVAL '-3 days';

Three days have been subtracted from the given date field. Therefore, to add a negative number to the date field, users must use the “-” operator instead of the “ **+** ” operator:
    
    
    SELECT DATE '2022-12-12' - INTERVAL '-3 days';

The output snippet shows that the negative days have been added to the specified date field successfully.

 **Example 6: Use + Operator on Table’s Data**

Let’s consider a practical scenario to understand the working of the “+” operator in a better way:
    
    
    CREATE TABLE cnic (
    issued_date DATE,
    valid_until INTERVAL);

A sample table named “cnic” is created with two columns: issued_date and valid_until. Let’s run the below-provided query to insert a couple of records in the “cnic” table:
    
    
    INSERT INTO cnic(issued_date, valid_until) 
    VALUES ('2015-01-18', INTERVAL '1825 days'),
    ('2018-11-01', INTERVAL '1825 days');

Let’s query the data of “cnic” table using the below-provided command:
    
    
    SELECT * FROM cnic;

Now we will use the “+” operator to find the expiry date of the cnic:
    
    
    SELECT issued_date + valid_until as expiry_date
    FROM cnic;

This way, you can add any particular day(s) to a date field in Postgres.

 **Conclusion**

Postgres allows us to add a certain number of days to a date field using the plus “ **+** ” operator. In other databases like SQL Server, MySQL, etc., a built-in function named DATEADD() is used to add days to a date. However, Postgres doesn’t support the DATEADD() function. In Postgres, the functionality of the DATEADD() function can be achieved via the “+” operator. This Post explained how to add a certain number of days to a date in Postgres via several examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-add-days-to-a-date-in-postgresql/)

---

# PostgreSQL TIMESTAMP Data Types and Functions

> PostgreSQL provides two temporal data types to deal with the TIMESTAMPS: TIMESTAMP(without the time zone) and TIMESTAMPTZ(with a time zone).

PostgreSQL facilitates us with two temporal data types to deal with the **TIMESTAMPS**. For instance, **TIMESTAMP** and **TIMESTAMPTZ** : the first one stores the TIMESTAMP without the timezone, while the other one stores the TIMESTAMP with a timezone. Both these data types consume 8 bytes to store a TIMESTAMP value.

TIMESTAMP data types and functions will be explained in this Postgres blog using Practical examples. So, let’s get started!

 **PostgreSQL TIMESTAMP Data Types**

In Postgres, the **TIMESTAMP** data type is used to store the date and time without any time zone information. Therefore, changing a database's timezone will not update the timestamp values already stored in the database. The below snippet demonstrates how to create a column with TIMESTAMP data type:
    
    
    CREATE TABLE tab_name (
    col_name TIMESTAMP
    );

Specify the table name in place of “tab_name”. Next, specify the column name followed by the TIMESTAMP data type.

Use the Postgres’ **TIMESTAMPTZ** data type to store the date, time, and time zone information. The below syntax shows the usage of the TIMESTAMPTZ data type:
    
    
    CREATE TABLE tab_name (
    col_name TIMESTAMPTZ
    );

 **Note:** A value inserted into a column declared with the TIMESTAMPTZ data type will be converted into a universal time-coordinated value( **UTC** ). While Postgres converts the UTC value back to the **TIMESTAMPTZ** type when someone queries that value from the database.

 **Example 1: How to Create a Table Using TIMESTAMP and TIMESTAMPTZ in Postgres?**

To create a table in Postgres with a TIMESTAMP and TIMESTAMPTZ column, you can use the CREATE TABLE statement as follows:
    
    
    CREATE TABLE timestamp_example(
    time_ts TIMESTAMP NOT NULL,
    time_tz TIMESTAMPTZ NOT NULL
    );

The output snippet proves that the “ **timestamp_example** ” table has been created successfully. Let’s learn how to insert data into timestamp columns:
    
    
    INSERT INTO timestamp_example(time_ts, time_tz)
    VALUES ('2022-12-22 01:13:41.104131', '2022-12-22 01:13:41.104131-08');

The above snippet verifies that the INSERT INTO command was executed successfully. Use the “ **SELECT *** ” command to verify the newly inserted data:
    
    
    SELECT * FROM timestamp_example;

The output shows that the **TIMESTAMP** with timezone and without timezone has been inserted into the respective columns.

 **Example 2: How to Set the Current TIMESTAMP as a Column Default Value?**

Use the DEFAULT keyword along with the CURRENT_TIMESTAMP function to set the current timestamp as the default value of a column:
    
    
    CREATE TABLE emp_example(
    emp_id SERIAL PRIMARY KEY,
    emp_name TEXT,
    emp_login TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
    );

The **CURRENT_TIMESTAMP** function retrieves the time with the timezone, so by default, the **emp_login** column will accept the current date, time, and timezone:

The above snippet shows that the “emp_example” table has been created successfully. Now, execute the “ **INSERT INTO** ” command to insert the employee’s data into the “ **emp_example** ” table:
    
    
    INSERT INTO emp_example(emp_name)
    VALUES('Joseph'),
    ('Joe'),
    ('Alexa'),
    ('Natie'),
    ('Alex');

Five records have been inserted into the “ **emp_example** ” table. Let’s query the inserted data using the “ **SELECT *** ” command:
    
    
    SELECT * FROM emp_example;

The output snippet proves that the current timestamp has been successfully inserted into the “ **emp_login** ” column.

 **Postgres TIMESTAMP Functions**

PostgreSQL provides several functions that allow you to manipulate and work with timestamps. Here are some frequently used timestamp functions that you might find useful:

  * [CURRENT_TIMESTAMP](<https://www.commandprompt.com/education/postgresql-current_timestamp-function-with-examples/>): Retrieves the current date and time as a timestamp.
  * [NOW()](<https://www.commandprompt.com/education/postgresql-now-function-with-practical-examples/>): Retrieves today’s date and time as a TIMESTAMP.
  * [DATE_TRUNC(field, timestamp):](<https://commandprompt.com/education/how-to-use-date_trunc-function-in-postgresql/>) Truncates/trims a timestamp to the specified field, such as a month, year, etc.
  * [TO_TIMESTAMP(time_string, format)](<https://www.commandprompt.com/education/postgresql-to_timestamp-function-with-examples/>): Converts a string to a timestamp according to the given format.
  * [AGE(timestamp_1, timestamp_2)](<https://www.commandprompt.com/education/postgresql-age-function-with-examples/>): Calculates the difference between two timestamps and returns the result as an interval.
  * [EXTRACT(field FROM timestamp)](<https://commandprompt.com/education/how-to-use-extract-function-in-postgresql/>): Extracts a particular field, such as a month, day, year, etc., from a timestamp.



 **Note:** A wide range of TIMESTAMP functions are available in Postgres; only a few are discussed here. You can visit the following Postgres guide to learn more about the [TIMESTAMP](<https://www.commandprompt.com/education/date-time-functions-in-postgresql-with-examples/>) functions.

 **Conclusion**

PostgreSQL provides two temporal data types to deal with the TIMESTAMPS: **TIMESTAMP** and **TIMESTAMPTZ**. The first one stores the TIMESTAMP without the timezone, while the second one stores the **TIMESTAMP** with a timezone. Moreover, Postgres provides various built-in timestamp functions that allow us to manipulate and work with timestamps, such as NOW(), CURRENT_TIMESTAMP, AGE(), etc. This Postgres guide presented a thorough guide on using the TIMESTAMP data types and Functions in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-timestamp-data-types-and-functions/)

---

# How to Find the Interval Between Two Dates in PostgreSQL

> In PostgreSQL, finding the interval between two dates can be accomplished using the built-in AGE() function or the minus “-” operator.

Finding the interval between two dates in PostgreSQL is a common task that can be accomplished using the built-in **AGE()** function or the minus “-” operator. Both these approaches are useful for calculating the person's age, finding the duration of an event, analyzing job experience, and so on.

This tutorial will explore the usage of the Postgres’ AGE() function and the minus “ **-** ” operator via practical examples.

 **How to Find/Get the Interval Between Two Date Fields Via AGE() Function in Postgres?**

In Postgres, [AGE()](<https://www.commandprompt.com/education/postgresql-age-function-with-examples/>) is a built-in function that accepts two dates as arguments and finds the interval between the given dates. It subtracts the second timestamp/date field from the first and retrieves the resultant INTERVAL as output.

 **Syntax**

Use the following syntax to get the services of the Postgres AGE() function:
    
    
    AGE(TIMESTAMP_1, TIMESTAMP_2);

The above snippet shows that the AGE() function accepts two timestamps/dates as arguments.

 **Example 1: How to Calculate the Person’s Age Using AGE() Function in Postgres?**

Let’s suppose we want to calculate the age of a person whose birth date is “1980-07-11”. To do that, we will execute the AGE() function as follows:
    
    
    SELECT AGE(CURRENT_DATE, '1980-07-11');

In the above snippet, we pass today’s date as the first argument and the person’s birth date as the second argument. Consequently, the AGE() function will retrieve the following output:

The output shows that the AGE() function calculates the age of the selected person and retrieves an INTERVAL as output.

 **Example 2: How to Find Employees’ Work Experience Using the AGE() Function in Postgres?**

We have already created a table named “emp_example” that contains the necessary data of all the company’s employees:
    
    
    SELECT * FROM emp_example;

Let’s find the total work experience of each individual via the AGE() function:
    
    
    SELECT emp_name, AGE(emp_resign_date, emp_join_date) AS total_experience
    FROM emp_example;

This way, you can find the interval between two dates via the Postgres’ AGE() function.

 **How to Get an Interval Between Two Date Fields Via the “-” Operator in Postgres?**

In PostgreSQL, the minus “ **-** ” operator is used to get an interval between the two dates. Use the following syntax to get the interval via the “ **-** ” operator:
    
    
    'date_1'::DATE - 'date_2'::DATE;

The above query will retrieve an integer value representing the total number of days between the specified dates.

 **Example 1: How to Get the Interval Between Two Dates Using “-” Operator?**

Execute the following query to get the number of days between the given dates:
    
    
    SELECT '2020-02-01'::DATE - '2011-11-14'::DATE;

The output shows that the total number of days between the specified dates is 3001.

 **Example 2: How to Use the “-” Operator on the Table’s Data?**

Suppose we want to find the total duration of the published articles. For this purpose, we can use the “-” operator as follows:
    
    
    SELECT (CURRENT_DATE - published_date) AS total_days
    FROM published_articles;

In the above snippet, we utilized the “-” operator to find the interval between the current date and the articles’ published date:

The output snippet shows that the “-” operator finds the interval between the current_date and published_date successfully.

That’s it from this blog!

 **Conclusion**

In PostgreSQL, finding the interval between two dates can be accomplished using the built-in **AGE()** function or the minus “-” operator. Most users prefer the AGE() function because it retrieves detailed information regarding the interval; on the other hand, the “-” operator retrieves only the number of days. This blog post explained how to find the interval between two dates via the AGE() function or the minus “-” operator.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-the-interval-between-two-dates-in-postgresql/)

---

# How to Convert a TIMESTAMP to String in PostgreSQL

> PostgreSQL provides a built-in TO_CHAR() function that converts the given timestamp to a string. It utilizes a format mask to convert the input value to a stri…

PostgreSQL allows us to convert a date, interval, number, timestamp, etc., to a string via the **TO_CHAR()** function. The TO_CHAR() function utilizes a format mask to convert the input value to a string. The format mask must be a valid number or date.

This write-up will teach you how to use the **TO_CHAR()** function to convert a timestamp into a string in Postgres. So, let’s start!

 **How Do I Convert a TIMESTAMP to a String in Postgres?**

In Postgres, a built-in conversion function named **TO_CHAR()** is used to convert the given timestamp to a string. To do that, the TO_CHAR() function takes two arguments: a timestamp and a format string specifying how the timestamp should be formatted as a string:
    
    
    TO_CHAR(timestamp_expression, formatMask);

In place of the “timestamp_expression” parameter, you can specify a timestamp column or any built-in date time function like NOW(), CURRENT_TIMESTAMP, etc. While the ‘formatMask’ parameter represents a valid timestamp format as described in the official Postgres [documentation](<https://www.postgresql.org/docs/8.4/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE>).

 **Example: How to Convert a CURRENT_TIMESTAMP to a String in Postgres?**

In this example, we will pass the CURRENT_TIMESTAMP function as the first argument and a valid format as a second argument to the TO_CHAR() function:
    
    
    SELECT TO_CHAR(CURRENT_TIMESTAMP, 'YYYY/MM/DD HH12:MM:SS');

On successful execution of the TO_CHAR() function, the current date and time will be converted into a string:

The output snippet shows that the specified timestamp was successfully converted into the string.

 **Example 2: How to Convert a TIMESTAMP Column to a String in Postgres?**

First, let’s create a sample table with three columns: a_id, a_name, and p_date:
    
    
    CREATE TABLE article_information(
    a_id SERIAL PRIMARY KEY, 
    a_title TEXT,
    p_date TIMESTAMP);

The “ **a_id** ” column will accept numeric data, the “ **a_title** ” column will accept the textual data, and the “ **p_date** ” column will accept the TIMESTAMP values:

The table named “article_information” has been successfully created via the CREATE TABLE command. Now, execute the INSERT INTO command to insert some records into the newly created table:
    
    
    INSERT INTO article_information(a_title, p_date)
    VALUES ('IF Statement in Postgres', '2022-07-01 12:30:12'),
    ('How to Count Unique Values in Postgres', '2022-08-28 09:00:00'),
    ('How to Delete Duplicates in Postgres', '2022-09-15 11:10:50'),
    ('AVG() Function in PostgreSQL', '2022-07-10 12:12:52'),
    ('Delete Table PostgreSQL', '2022-07-01 12:24:12');

Now execute the “ **SELECT *** ” query to fetch all the records of the “article_information” table.
    
    
    SELECT * FROM article_information;

The output snippet shows that the “p_date” column has a TIMESTAMP data type. Let’s say we need to convert the “p-date” column into a string type. For this purpose, we will use the TO_CHAR() function as follows:
    
    
    SELECT a_title, p_date, TO_CHAR(p_date, 'YYYY/MM/DD HH:MM:SS') AS publised_date
    FROM article_information;

The output snippet proves that the given TIMESTAMP has been converted into a string successfully.

That’s it from this Postgres blog!

 **Conclusion**

PostgreSQL provides a built-in TO_CHAR() function that converts the given timestamp to a string. The **TO_CHAR()** function utilizes a format mask to convert the input value to a string. The format mask must be a valid number or date. This Postgres blog explained the working of the TO_CHAR() function for converting a TIMESTAMP to a string via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-convert-a-timestamp-to-string-in-postgresql/)

---

# How to Extract DOW in PostgreSQL?

> In PostgreSQL, the EXTRACT() and DATE_PART() functions are used to extract a DOW(an acronym for Day of Week) from a date or timestamp.

In PostgreSQL, built-in functions like **EXTRACT()** and **DATE_PART()** are used to extract a DOW(an acronym for Day of Week) from a date or timestamp. Using these two functions, you can extract any part from a date or timestamp, such as a day, month, year, minute, etc. However, in this post, we will only focus on extracting the day of the week from the given date or timestamp.

This tutorial will show you how to use PostgreSQL's built-in date functions to extract the day of the week (DOW) from a date field. So, let’s start!

 **How to Extract DOW in Postgres Using the EXTRACT() Function?**

Use the following syntax to extract the DOW from a date field:
    
    
    EXTRACT(DOW FROM source);

In place of the “source” parameter, specify the date field from which you want to extract the day of the week.

 **Note:** Extracting the day of the week using the EXTRACT() function will retrieve a value between 0-6. Here, the number 0 means Sunday, 1 means Monday, and so on.

 **Example 1: How to Extract a DOW From the Current Date Using EXTRACT() Function?**

Let’s pass “ **DOW** ” as the first argument and the “ **CURRENT_DATE** ” function as the second argument to the **EXTRACT()** function:
    
    
    SELECT EXTRACT('DOW' FROM CURRENT_DATE);

The **EXTRACT()** function retrieves “3”, indicating that the current day of the week is “Wednesday”.

 **Example 2: How to Extract a DOW From the Date Field Using EXTRACT() Function?**

In this example, we will use the EXTRACT() function to pull out the DOW from a specific date field:
    
    
    SELECT EXTRACT('DOW' FROM DATE '2022-12-12');

The output snippet shows that the day of the week in the specified date field is “ **Monday** ”.

 **How to Extract DOW in Postgres Using the DATE_PART() Function?**

Postgres offers another convenient date function named DATE_PART() that is used to extract the day of the week from the given date field:
    
    
    DATE_PART(DOW, source);

In place of the “source” parameter, specify the date field from which you want to extract the day of the week.

 **Example 1: How to Extract a DOW From the Current Date Using DATE_PART() Function?**

In this example, we will pass “ **DOW** ” as the first argument and the “ **NOW()** ” function as the second argument to the **DATE_PART()** function:
    
    
    SELECT DATE_PART('DOW', NOW());

The output shows “3”, which means the current day of the week is “Wednesday”.

 **Example 2: How to Extract a DOW From the Date Field Using DATE_PART() Function?**

Executing the below line of code will extract the DOW from a specific date field:
    
    
    SELECT DATE_PART('DOW', DATE '2022-01-15');

The output snippet shows that the DATE_PART() function retrieves “6”, indicating that the day of the week in the given date field is “Saturday”.

 **Example 3: How to Extract a DOW From the Table’s Data?**

We have already created a table named “article_information”, whose date is shown in the following snippet:
    
    
    SELECT * FROM article_information;

In this example, we will use the **EXTRACT()** and **DATE_PART()** functions side-by-side to extract the day of the week from the “ **p_date** ” column:
    
    
    SELECT p_date, EXTRACT(DOW FROM p_date), DATE_PART('DOW', p_date)
    FROM article_information;

The output authenticates the working of the EXTRACT() and DATE_PART() functions.

 **Conclusion**

In PostgreSQL, the **EXTRACT()** and **DATE_PART()** functions are used to extract a DOW(an acronym for Day of Week) from a date or timestamp. Both these functions accept two arguments: a “unit” argument like a month, day, year, etc., and a “date field” from which you want to extract the day of the week. Through examples, this write-up demonstrated how to extract DOW via Postgres’ **EXTRACT()** and **DATE_PART()** functions.

---
[View this page online](https://www.commandprompt.com/education/how-to-extract-dow-in-postgresql/)

---

# PostgreSQL TO_CHAR Function With Practical Examples

> In Postgres, a built-in function named TO_CHAR() is used to convert any data type, such as an integer, interval, timestamp, date, etc., to a string.

Postgres offers a built-in function named **TO_CHAR()** that converts any data type, such as an integer, interval, timestamp, date, etc., to a string. The TO_CHAR() function utilizes a format mask to convert the input value to a string. The format mask must be a valid number or date.

This blog post will show you how to use the TO_CHAR() function in PostgreSQL via practical examples. The below-mentioned concepts will be discussed in this write-up:

  * How to Use TO_CHAR() Function in Postgres?
  * How Do I Convert a Timestamp to a String in Postgres Via TO_CHAR() Function?
  * How to Convert an Interval to a String in Postgres Via TO_CHAR() Function?
  * How Do I Convert a Date Field to a String in Postgres Via TO_CHAR() Function?
  * How Do I Convert an Integer Value to a String in Postgres Via TO_CHAR() Function?
  * How Do I Convert a Numeric Value to a String in Postgres Via TO_CHAR() Function?



So, let’s begin!

 **How to Use TO_CHAR() Function in Postgres?**

In Postgres, the **TO_CHAR()** function converts a date, number, interval, etc., to a string. To put the TO_CHAR() function into practice, you must follow the below-given syntax:
    
    
    TO_CHAR(exp, format);

In the above syntax:

\- exp represents an expression to be converted.  
\- The specified expression can be a date/time stamp, an integer, a number, a double precision, or an interval.  
\- The format represents a valid/permitted numeric or timestamp format based on which the given expression will be converted into a string.

Valid [numeric](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-NUMERIC-TABLE>) and [timestamp](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE>) formats are explained in this document.

 **Example 1: How Do I Convert a Timestamp to a String in Postgres Via TO_CHAR() Function?**

In the following example code, we are going to use the current timestamp as the first argument and a format as a second argument in the **TO_CHAR()** function.
    
    
    SELECT TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-MM-DD HH24:MM:SS');

On successful execution of the TO_CHAR() function, the current date and time will be converted into a string:

The output snippet shows that the specified timestamp was successfully converted into the string.

 **Example 2: How to Convert an Interval to a String in Postgres Via TO_CHAR() Function?**

Let’s pass an interval as the first parameter and a valid format as the second parameter to the TO_CHAR() function:
    
    
    SELECT TO_CHAR(INTERVAL '5 year 6 months 12 days', 'YYYY/MM/DD');

On successful execution, the TO_CHAR() function will retrieve a string in YYYY/MM/DD format:

The above snippet proves that the given interval has been successfully converted into a string using the **TO_CHAR()** function.

 **Example 3: How Do I Convert a Date Field to a String in Postgres Via TO_CHAR() Function?**

To convert the current date into a string, let’s pass the current date and a valid format as arguments to the TO_CHAR() function.
    
    
    SELECT TO_CHAR(CURRENT_DATE, 'MON DD, YYYY');

The above piece of code will convert the current date into a “MON DD, YYYY” format:

The output authenticates the working of the **TO_CHAR()** function.

 **Example 4: How Do I Convert an Integer Value to a String in Postgres Via TO_CHAR() Function?**

Let’s pass an integer and a valid [numeric format](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-NUMERIC-TABLE>) to the TO_CHAR function to convert the input number into a string:
    
    
    SELECT TO_CHAR(572172, '999,999');

The above code uses "9" to represent numeric values and commas to separate them:

The output snippet shows that the given integer has been converted into a string via the TO_CHAR() function.

 **Example 5: How to Convert a NUMERIC Value to a String in Postgres Via TO_CHAR() Function?**

This example will teach you how to use the TO_CHAR() function to convert a numeric value to a string using a valid [numeric format](<https://www.postgresql.org/docs/current/functions-formatting.html#FUNCTIONS-FORMATTING-NUMERIC-TABLE>):
    
    
    SELECT TO_CHAR(572.172, '999D999');

The “D” is a numeric format used to represent a decimal point:

The given numeric value has been successfully converted into a string via the TO_CHAR() function.

 **Example 6: How to Use the TO_CHAR() Function on Table’s Data?**

We have created a sample table named “article_information” that contains the following data:
    
    
    SELECT * FROM article_infromation;

We will use the TO_CHAR() function to convert the TIMESTAMP column to a string. After that, we will use the concatenation operator “||” to concatenate the “ **a_title** ” and “ **p_date** ” columns:
    
    
    SELECT a_title || ' Published on ' || 
    TO_CHAR(p_date, 'YYYY/MM/DD') as article_info
    FROM article_information;

The output snippet shows that the "p_date" column has been successfully converted to a string and concatenated with the "a_title" column.

That’s it from this blog!

 **Conclusion**

In Postgres, a built-in function named **TO_CHAR()** is used to convert any data type, such as an integer, interval, timestamp, date, etc., to a string. The TO_CHAR() function utilizes a format mask to convert the input value to a string. The format mask must be a valid number or date. This Postgres blog presented various examples to explain the working of the TO_CHAR() function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-to_char-function-with-practical-examples/)

---

# PostgreSQL CURRENT_TIME Function With Practical Examples

> The CURRENT_TIME function retrieve the current time and the time zone. It can accept an optional parameter “precision” to set the precision of the retrieved fr…

Postgres offers numerous date/time functions such as CURRENT_TIMESTAMP, CURRENT_DATE, NOW(), etc. The **CURRENT_TIME** is one of the date/time functions that retrieve the current time and the time zone value. This blog post will teach you the basic syntax, usage, and practical implementation of Postgres’ **CURRENT_TIME** function.

Let’s start with the basic syntax of the CURRENT_TIME function!

 **How to Use the CURRENT_TIME Function in PostgreSQL?**

To use the **CURRENT_TIME** function in Postgres, the below-mentioned syntax must be followed:
    
    
    CURRENT_TIME(prec);

The **CURRENT_TIME** function may accept an optional parameter “ **precision** ” that is used to set the precision of the retrieved fractional seconds. If the precision parameter is omitted, the fractional seconds will be retrieved with the full precision available. The return type of the **CURRENT_TIME** is **TIMETZ**.

Let’s go through the below examples to perceive the working of the **CURRENT_TIME** function.

 **Example 1: What Does Postgres ' CURRENT_TIME Function Do?**

Executing the below statement will retrieve the current time and timezone:
    
    
    SELECT CURRENT_TIME;

The output snippet shows that the CURRENT_TIME function retrieves the current time and zone.

 **Example 2: How Does the CURRENT_TIME Function Work With Precision Parameter in Postgres?**

Let’s learn how to use the CURRENT_TIME function with the precision parameter:
    
    
    SELECT CURRENT_TIME(3);

From the output snippet, it is clear that the CURRENT_TIME function retrieves the current time based on the specified precision parameter.

 **Example 3: How to Use the CURRENT_TIME Function as the Column’s Default Value?**

Let’s create a sample table named “ **students_login** ” with three columns “ **student_id** ”, “ **student_name** ”, and “ **student_login** ”:
    
    
    CREATE TABLE students_login(
    student_id SERIAL PRIMARY KEY,
    student_name TEXT,
    student_login TIME DEFAULT CURRENT_TIME
    );

In the above code, we utilize the DEFAULT keyword to assign the current time as a default time to the student_login column:

The “students_login” table has been created successfully. Let’s insert the student details via the “ **INSERT INTO** ” command:
    
    
    INSERT INTO students_login (student_name)
    VALUES ('Joseph');

In the above snippet, we specified only the student’s name; the current time will be assigned to the student_login column by default:

Now, run the “SELECT *” command to check if a record has been inserted into the students_login table or not:
    
    
    SELECT * FROM students_login;

The output snippet indicates that a student named “ **Joseph** ”, having a student id “ **1** ”, logged in at “ **22:13:19.738302** ”.

Let’s insert one more record to understand the working of the CURRENT_TIME function more clearly:
    
    
    INSERT INTO students_login (student_name)
    VALUES ('Stephen');

The output snippet verifies that one more record has been inserted into the students_login table. To verify the details regarding the newly inserted record, run the “SELECT *” command:
    
    
    SELECT * FROM students_login;

The output snippet shows that another student named “ **Stephen** ”, having a student id “ **2** ”, logged in at “ **22:31:38.790645** ”.

This is how the CURRENT_TIME function works in PostgreSQL.

 **Conclusion**

The **CURRENT_TIME** function is one of the date/time functions that retrieve the current time and the time zone. The CURRENT_TIME function may accept an optional parameter “precision” to set the precision of the retrieved fractional seconds. If the precision parameter is omitted, the fractional seconds will be retrieved with the full precision available. This Postgres blog demonstrated the working of the CURRENT_TIME function with various examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-current_time-function-with-practical-examples/)

---

# CREATE TABLE AS SELECT Statement in PostgreSQL

> In Postgres, a new table can be created via the SELECT command; for this, the CREATE TABLE statement is used along with an AS clause followed by a SELECT state…

Postgres allows us to create a table via the SELECT command; for this purpose, the CREATE TABLE statement is used along with an AS clause followed by a SELECT statement. The newly created table will have the same table structure (e.g., column names, data types, etc.) as the columns in the SELECT query.

This blog post will consider various examples to demonstrate the working of the CREATE TABLE AS statement in Postgres. For this purpose, the following content will be covered in this write-up:

  * How Do I Create a Table Via the CREATE TABLE AS SELECT Statement in Postgres?
  * How to Create a TEMPORARY Table Via the CREATE TABLE AS SELECT Command in Postgres?
  * How to Create an UNLOGGED Table Via the CREATE TABLE AS SELECT Command in Postgres?
  * How to Avoid Table Already Existing Error in Postgres?



So, let’s begin!

 **How Do I Create a Table Via CREATE TABLE AS SELECT Statement in Postgres?**

In Postgres, the **CREATE TABLE AS** statement allows us to create a table from an existing one. It creates the table based on the result-set retrieved by the SELECT query. Follow the below syntax to avail the functionality of the Postgres’ **CREATE TABLE AS** statement:
    
    
    CREATE TABLE new_tab AS 
    SELECT col_list | expression
    FROM existing_tab_name
    [WHERE criteria];

In the above snippet, new_tab represents the table name to be created. Col_list represents the existing table's columns based on which a new table will be defined/created. WHERE is an optional clause used to specify a specific condition/criteria.

 **Note:** If the user wants a table with a different name, they can specify different table columns after the new table name.

 **Example 1: How Do I Create a Table via CREATE TABLE AS Statement?**

We have already created a table named “author_details” that has the following structure:
    
    
    SELECT * FROM author_details;

Let's say we want to create a table named " **author_info** " with the same columns and data as " **author_details** ". For this purpose, the CREATE TABLE AS statement will be executed as follows:
    
    
    CREATE TABLE author_info AS
    SELECT * 
    FROM author_details;

Let’s execute the SELECT * command to see the newly created table:
    
    
    SELECT * FROM author_info;

The output shows that the “ **author_info** ” table has been created with the same data as in the “ **author_details** ” table.

 **Example 2: How Do I Create a Table Without Data Using the CREATE TABLE AS Statement?**

Executing the **CREATE TABLE AS** Statement with the collaboration of the “ **WITH NO DATA** ” clause will copy only the table’s structure(without any data).
    
    
    CREATE TABLE author_information AS
    SELECT * 
    FROM author_details
    WITH NO DATA;

The output snippet indicates that the CREATE TABLE AS SELECT Statement gets executed successfully. Here is the verification snippet:
    
    
    SELECT * FROM author_information;

The output snippet authenticates the working of the “ **CREATE TABLE AS SELECT** ” statement.

 **How to Create a TEMPORARY Table Via the CREATE TABLE AS SELECT Command in Postgres?**

Use the **TEMP** keyword along with the **CREATE TABLE AS** command to create a temporary table in Postgres:
    
    
    CREATE TEMP TABLE tab_name AS
    SELECT col_list | expression
    FROM existing_tab_name
    [WHERE criteria];

 **Note:** A temporary table in Postgres has a short lifespan. These tables are available only in the current database session and disappear once a session has expired.

Let’s learn how to create a temporary table via the below example:

 **Example: How Do I Create a Temporary Table in Postgres?**

Let’s say we need to create a temporary table with the same structure as the “author_details” table. To do this, the “ **CREATE TABLE AS SELECT** ” statement will be executed as follows:
    
    
    CREATE TEMP TABLE temp_author AS
    SELECT *
    FROM author_details;

To verify the table’s creation, execute the SELECT * command as follows:
    
    
    SELECT * FROM temp_author;

The output snippet proves that a temporary table has been created with the same data as the “ **author_details** ” table.

 **How to Create an UNLOGGED Table Via the CREATE TABLE AS SELECT Command in Postgres?**

Postgres' **UNLOGGED** tables are special types of tables intended to store temporary or intermediate results that can be regenerated if necessary. They are faster as compared to regular tables because they do not need to be logged and do not require the overhead of maintaining a transaction log.

To create an **UNLOGGED** table using the **CREATE TABLE AS** statement in Postgres, you can use the following syntax:
    
    
    CREATE UNLOGGED TABLE new_tab_name AS 
    SELECT * FROM existing_tab_name;

Executing the above query will create a new table named “ **new_tab_name,** ” which is an exact copy of an existing table named “ **existing_tab_name** ”, with the additional property that it is an **UNLOGGED** table.

 **Example: How Do I Create an Unlogged Table in Postgres?**

Let’s execute the **CREATE TABLE AS** **SELECT** statement with an **UNLOGGED** keyword:
    
    
    CREATE UNLOGGED TABLE unlogged_example AS
    SELECT *
    FROM author_details
    WITH NO DATA;

This way, an unlogged table can be created in Postgres via the **CREATE TABLE AS SELECT** statement.

 **How to Avoid Table Already Exist Error in Postgres?**

Users may encounter the “ **table already exists** ” error while working with the “ **CREATE TABLE AS SELECT** ” statement. To avoid such an error, the “ **IF NOT EXISTS** ” option must be used alongside the “ **CREATE TABLE AS SELECT** ” statement.
    
    
    CREATE TABLE IF NOT EXIST new_tab AS 
    SELECT col_list | expression
    FROM existing_tab_name;

 **Example: How Do I Avoid Table Already Exists Error in Postgres?**

We have already created a table named “ **author_information** ”; trying to create a table with the same name will throw an error. However, if we specify the “ **IF NOT EXISTS** ” option, then we can avoid such errors:
    
    
    CREATE TABLE IF NOT EXISTS author_information 
    AS SELECT * FROM author_details;

Postgres generates a notice instead of throwing an error. It proves the working of the “ **IF NOT EXISTS** ” option.

 **Conclusion**

In PostgreSQL, a new table can be created via the **SELECT** command; for this purpose, the **CREATE TABLE** statement is used along with an AS clause followed by a **SELECT** statement. The newly created table will have the same table structure (e.g., column names, data types, etc.) as the columns in the SELECT query. This Postgres blog has provided an in-depth understanding of the CREATE TABLE AS SELECT statement via examples.

---
[View this page online](https://www.commandprompt.com/education/create-table-as-select-statement-in-postgresql/)

---

# PostgreSQL ARRAY_PREPEND() Function

> PostgreSQL provides a built-in ARRAY_PREPEND() function that is used to append an element at the start of an array. It accepts two arguments: an element and an…

PostgreSQL provides several built-in functions that allow us to work with the arrays. For instance, the ARRAY_LENGTH() retrieves the length of an array along with a particular dimension, the ARRAY_CAT() function concatenates two arrays, the ARRAY_APPEND() function appends an element to the end of an array, etc. The **ARRAY_PREPEND()** is one of the array functions that append an element at the start of an array.

Using suitable examples, this blog post will teach you how to use the **ARRAY_PREPEND()** function in Postgres. So, let’s start!

 **How to Use ARRAY_PREPEND() Function in Postgres?**

Postgres users can use the ARRAY_PREPEND() function to append an element at an array's starting index. To avail the functionality of the ARRAY_PREPEND() function, users must use the following syntax:
    
    
    ARRAY_PREPEND(item, arr);

" **item** " represents any element to be appended to an array at its starting index. While "arr" represents the array to which the element will be appended.

 **Example 1: How to Prepend a String Type Element to an Array in Postgres?**

Suppose we want to append the name “Joseph” at the start of an array; to do this, we will use the **ARRAY_PREPEND()** function as follows:
    
    
    SELECT ARRAY_PREPEND('Joseph', ARRAY['Mike', 'Seth', 'Alexa', 'Harry']);

The output snippet shows that the given element has been appended to the array at the beginning.

 **Example 2: How to Prepend an INTEGER Element to an Array in Postgres?**

If you want to append any integer to the start of an array, then you can use the **ARRAY_PREPEND()** function as follows:
    
    
    SELECT ARRAY_PREPEND(112, ARRAY[12, 43, 23, 123, 98, 87]);

The output shows that an integer value “112” has been appended at the start of the input array.

 **Example 3: Prepend an INTEGER With String Array**

If a user tries to prepend a string value with an integer array or vice versa, then Postgres will throw a “function does not exist” error.
    
    
    SELECT ARRAY_PREPEND(172, ARRAY['Mike', 'Seth', 'Alexa', 'Harry']);

The output snippet proves that arbitrary data types cannot be prepended to an array of a particular type.

That’s all! From this Postgres blog!

 **Conclusion**

PostgreSQL provides a built-in ARRAY_PREPEND() function that is used to append an element at the start of an array. It accepts two arguments: an element and an array; consequently, the ARRAY_PREPEND() function prepends the given element at the start of the targeted array. However, if a user tries to prepend a string value with an integer array or vice versa, then Postgres will throw a “function does not exist” error. This post demonstrated the working of the ARRAY_PREPEND() function with various suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-array_prepend-function/)

---

# PostgreSQL UNION ALL Operator With Examples

> In Postgres, the UNION ALL operator combines the result sets of two or more queries into one table, including the duplicate records.

PostgreSQL offers **UNION** and **UNION ALL** operators that combine/merge the result sets of at least two [SELECT](<https://www.commandprompt.com/education/how-to-use-select-query-in-postgresql/>) queries. Both these operators are responsible for combining the result set of different queries into one table. However, the behavior of both these operators is different, i.e., UNION combines only distinct records, while **UNION ALL** combines all records, including duplicates.

This guide will demonstrate how to combine different result sets using the UNION ALL operator in Postgres. For this purpose, the below-mentioned concepts will be discussed in this write-up:

  * Creating Sample Tables
  * Understanding Postgres UNION Operator
  * How to Use the UNION ALL Operator in Postgres?



So, let’s begin!

 **Creating Sample Tables**

Firstly we will create a couple of sample tables named “ **book_details** ” and “ **top_selling_books** ” using the [CREATE TABLE](<https://www.commandprompt.com/education/different-methods-to-create-a-table-in-postgresql/>) statement:
    
    
    CREATE TABLE book_details(
    b_id INT PRIMARY KEY,
    b_name TEXT
    );

Now, we will use the [INSERT INTO](<https://www.commandprompt.com/education/how-to-use-insert-query-in-postgresql/>) command to insert data into the newly created "book_details" table:
    
    
    INSERT INTO book_details(b_id, b_name)
    VALUES (1, 'The Great Gatsby'),
    (2, 'The Picture of Dorian Gray'),
    (3, 'Great Expectations'),
    (4, 'Wuthering Heights'),
    (5, 'The Kite Runner'),
    (6, 'The Catcher in the Rye'),
    (7, 'The Lord of the Rings'),
    (8, 'His Dark Materials'),
    (9, 'To Kill a Mockingbird'),
    (10, 'The Grapes of Wrath'),
    (11, 'Frankenstein'),
    (12, 'Think and Grow Rich');

In the above code snippet, twelve records have been inserted into the book_details table using the INSERT query.

Let’s create one more table named “top_selling_books” using the CREATE TABLE command:
    
    
    CREATE TABLE top_selling_books(
    b_id INT PRIMARY KEY,
    b_name TEXT);

Now, we will execute the INSERT query to insert data into the newly created "book_details" table:
    
    
    INSERT INTO top_selling_books(b_id, b_name)
    VALUES
    (2, 'The Picture of Dorian Gray'),
    (3, 'Great Expectations'),
    (4, 'Little Women'),
    (5, 'Charlotte's Web'),
    (6, 'The Catcher in the Rye'),
    (7, 'The Lord of the Rings'),
    (10, 'The Grapes of Wrath'),
    (11, 'Frankenstein'),
    (12, 'Think and Grow Rich');

The above snippet indicates that nine records have been inserted into the “top_selling_books” table using the INSERT query.

Before moving towards the UNION ALL operator, firstly, we will comprehend the working of the UNION operator.

 **Understanding Postgres UNION Operator**

To get the services of the UNION operator, users must follow the below syntax:
    
    
    SELECT column_list_1
    FROM tab_1
    UNION
    SELECT column_list_2
    FROM tab_2;

To combine the result sets of table_1 and table_2, the UNION operator is used in the above syntax.

 **Example: How the UNION Operator Works in Postgres?**

In this example, we will use the UNION operator to combine the result sets of book_details and top_selling_books:
    
    
    SELECT b_name
    FROM book_details
    UNION
    SELECT b_name
    FROM top_selling_books;

From the output, you can observe that the result sets of the “ **book_details** ” and “ **top_selling_books** ” have been combined successfully. However, the resultant table contains only unique records.

 **How to Use Postgres UNION All Operator?**

To include the duplicates in the resultant table, users must use the **UNION ALL** operator instead of the UNION operator:
    
    
    SELECT column_list_1
    FROM tab_1
    UNION ALL
    SELECT column_list_2
    FROM tab_2;

The syntax mentioned above will be used to combine the result set of table_1 with the result set of table_2, including the duplicates.

 **Key Points:**

The below-listed points explain the concept of UNION ALL operator in more detail:

\- While using the UNION ALL operator, both SELECT statements must contain the same number of expressions/columns.  
\- Use the WHERE clause and the UNION ALL operator to combine the filtered data(based on some particular condition).  
\- Use the ORDER BY clause with the UNION ALL operator to sort the data of the resultant table in a specific format, i.e., ASC or DESC.  
\- The resultant table will have the same column names as the first SELECT statement.

 **Example 1: How Does the UNION ALL Operator Work in Postgres?**

Execute the following query to combine the result sets of the “ **top_selling_books** ” and “ **book_details** ” tables:
    
    
    SELECT b_name
    FROM book_details
    UNION ALL
    SELECT b_name
    FROM top_selling_books;

The output snippet proves that the UNION ALL operator retrieves a total of twenty-one records, including duplicates.

 **Example 2: How to Sort the Result Set of UNION ALL Operator in Descending Order?**

Now, using the ORDER BY clause in conjunction with the UNION ALL operator, we will sort the result set retrieved by the UNION ALL operator as follows:
    
    
    SELECT b_id, b_name
    FROM book_details
    UNION ALL
    SELECT b_id, b_name
    FROM top_selling_books
    ORDER BY b_id DESC;

The result set will be sorted based on the “ **b_id** ” column:

The output proves that the ORDER BY clause sorted the resultant table in descending order.

That’s all from this Postgres guide!

 **Conclusion**

In Postgres, the **UNION ALL** operator combines the result sets of two or more queries into one table, including the duplicate records. While using the UNION ALL operator, both SELECT statements must contain the same number of expressions/columns. The resultant table will have the same column names as the first SELECT statement. This Postgres blog went through various examples to explain the working of the Postgres UNION ALL operator.

---
[View this page online](https://www.commandprompt.com/education/postgresql-union-all-operator-with-examples/)

---

# How to Find Array Length in PostgreSQL?

> In Postgres, the ARRAY_LENGTH() is used to find the array&#x27;s length. The ARRAY_LENGTH() function finds the array’s length based on the requested dimension.

PostgreSQL offers numerous built-in functions to deal with arrays. For instance ARRAY_APPEND(), ARRAY_CAT(), **ARRAY_LENGTH()** , and so on. All these array functions serve different functionalities. In Postgres, the **ARRAY_LENGTH()** is one of the most frequently used array functions that find the array's length.

This post will present an in-depth overview of the ARRAY_LENGTH() function with the help of appropriate examples. So, let’s get started!

 **How to Use the ARRAY_LENGTH() Function in Postgres?**

In PostgreSQL, the ARRAY_LENGTH() function accepts two arguments: an array and an integer value that represents the array dimensions to be measured:
    
    
    ARRAY_LENGTH(arr, int_val);

The ARRAY_LENGTH() function will find the array’s length based on the value specified as a second argument. For example, if you set “1” in place of the “int_val” parameter, then the ARRAY_LENGTH() function will find the array length based on the requested dimension, i.e., “1”.

 **Example 1: How Does ARRAY_LENGTH() Function Work With 1-Dimensional Array in Postgres?**

In this example, we will pass a numeric array as the first argument and “1” as the second argument to the ARRAY_LENGTH() function:
    
    
    SELECT ARRAY_LENGTH(ARRAY[12, 72, 513, 1, -3, 0], 1);

The output indicates that the one-dimensional input array has 6 elements in it.

 **Example 2: How Does ARRAY_LENGTH() Function Work With a 2-Dimensional Array in Postgres?**

Let’s learn how to find the length of the 2-D array in Postgres via the ARRAY_LENGTH() function:
    
    
    SELECT ARRAY_LENGTH(ARRAY[[12, 72, 513], [1, -3, 0]], 2);

The output indicates the length of the two-dimensional input array is “3”.

Similarly, if you have to find the length of a 3-d array, specify “3” as the second parameter to the **ARRAY_LENGTH()** function, and so on.

 **Example 3: How Does ARRAY_LENGTH() Function Work on Table’s Data in Postgres?**

We have already created a table named “staff_data,” whose data is shown in the following snippet:
    
    
    SELECT * FROM staff_data;

Let’s utilize the **ARRAY_LENGTH()** function to find the length of each record for the “st_email” column:
    
    
    SELECT st_email, ARRAY_LENGTH(st_email, 1)
    FROM staff_data;

The output proves that the ARRAY_LENGTH() function retrieves the appropriate array length for each record.

 **Example 4: How to Use** **ARRAY_LENGTH() Function With WHERE Clause in Postgres?**

In the previous example, we didn’t specify any condition, so the **ARRAY_LENGTH()** function finds the length of each array present in the “st_email” column. Use the **WHERE** clause to find the array length for only a specific record:
    
    
    SELECT st_email, ARRAY_LENGTH(st_email, 1)
    FROM staff_data
    WHERE st_id = 2;

This is how you can find the length of only a specific array in Postgres.

 **Conclusion**

In Postgres, the **ARRAY_LENGTH()** is used to find the array's length. In PostgresQL, the ARRAY_LENGTH() function accepts two arguments: an array and an integer value representing the array dimensions to be measured. The ARRAY_LENGTH() function will find the array’s length based on the requested dimension. This blog post explained how to find the array length in Postgres via the ARRAY_LENGTH() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-array-length-in-postgresql/)

---

# PostgreSQL DROP VIEW IF EXISTS

> If a VIEW to be dropped doesn’t exist, then Postgres throws a VIEW doesn’t exist error. To rectify this error, the “IF EXISTS” option is used with the DROP VIE…

PostgreSQL provides a **DROP VIEW** statement that is used to delete/drop single or multiple views from the database. However, if the specified **VIEW** doesn’t exist, then Postgres throws a **VIEW** doesn’t exist error. The “ **IF EXISTS** ” option is used with the **DROP VIEW** statement in Postgres to rectify this error.

This article will present a detailed overview of the **DROP VIEW** statement with suitable examples. So, let’s start!

 **How to Use DROP VIEW IF EXISTS Statement in Postgres?**

To use the DROP VIEW statement in Postgres, users must follow the below syntax:
    
    
    DROP VIEW IF EXISTS view_name 
    CASCADE | RESTRICT;

Let’s understand the above statement step-by-step:

\- **View_name** represents a view to be deleted.  
\- The “ **IF** **EXISTS** ” is an optional clause used to avoid the view does not exist error.  
\- **CASCADE** is an optional clause that allows us to drop a view and any objects that depend on it. If you do not specify the **CASCADE** clause and some objects depend on the view, the DROP VIEW statement causes an error.  
\- **RESTRICT** is an optional clause that prevents the DROP VIEW statement from deleting the view if some objects depend on it.

Through practical examples, let’s comprehend the working of the **DROP VIEW IF EXISTS** statement. But before that, we will understand what would happen if we didn’t specify the IF EXISTS option.

 **Example 1: How to Drop a View in Postgres?**

Execute the below-provided statement to delete a view named “example_view”:
    
    
    DROP VIEW example_view;

The output shows that the targeted view has been dropped successfully. Let’s execute the DROP VIEW statement one more time to see how it works:
    
    
    DROP VIEW example_view;

The output shows an error when we try to drop a view that doesn’t exist.

 **Example 2: How to Use the IF EXISTS Option With the DROP VIEW Statement in Postgres?**

Let’s learn how the IF EXISTS option deals with the “view doesn’t exist” error:
    
    
    DROP VIEW IF EXISTS example_view;

The output snippet verifies that the IF EXISTS option shows a notice instead of throwing an error.

That’s it from this Postgres guide!

 **Conclusion**

In PostgreSQL, the **DROP VIEW** statement is used to delete/drop single or multiple views from the database. However, if the specified **VIEW** doesn’t exist, then Postgres throws a **VIEW** doesn’t exist error. To rectify this error, users must use the “ **IF EXISTS** ” option with the **DROP VIEW** statement. This Postgres blog explained the working of the “DROP VIEW IF EXISTS” option with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-drop-view-if-exists/)

---

# VIEWS in PostgreSQL: CREATE VIEW, DROP VIEW, UPDATE VIEW

> Postgres provides the “CREATE VIEW”, “CREATE OR REPLACE VIEW”, and “DROP VIEW” statements to create, update or drop a view from the database.

A PostgreSQL **view** is a virtual table created based on the SELECT command. It does not physically store data but rather displays the results of a SELECT statement every time it is queried.

A view can simplify queries, join multiple tables together, perform calculations, and return the results. It can also be used to provide users with a simplified version of the data in the underlying tables or restrict the visible data to the user.

This write-up will use suitable examples to demonstrate how to create, drop, or update a view in Postgres. So, let’s start!

 **What is a VIEW in PostgreSQL?**

In Postgres, a view is a virtual table representing data of one or more underlying tables using the SELECT command. Once a view is created, you can select data from it the same way as you select from a real/ordinary table.

 **Why Should Someone Use the VIEWS in Postgres?**

Views are useful for many reasons, some of which are listed below:

\- VIEWS in Postgres allows us to encapsulate complex SELECT statements and present the data to users in a simpler way.  
\- A VIEW can be created only to display a subset of the data in a table, thereby limiting access to the data.  
\- VIEWS can be used to simplify the structure of a database by abstracting complex queries into simpler views.

 **How to Create a VIEW in Postgres?**

Here is the basic syntax for creating a view in Postgres:
    
    
    CREATE <OR REPLACE> VIEW view_name AS
    SELECT col_list
    FROM tab_name
    WHERE condition;

In the above snippet, the “OR REPLACE” is an optional clause used to avoid the “ **VIEW already exists** ” error.

 **Example: How Does the CREATE VIEW Command Work in Postgres?**

Let’s create a view(virtual table) named “example_view” based on the result set of the **SELECT** statement:
    
    
    CREATE VIEW example_view AS
    SELECT st_id, st_name, st_phone, st_email
    FROM staff_data;

The output snippet clarifies that a view named example_view has been created successfully. To query the newly created view, you must execute the following command:
    
    
    SELECT * FROM example_view;

The output verifies the working of the CREATE VIEW statement.

 **How to Update/Modify a VIEW in Postgres?**

To update/alter the definition of an already existing view, use the “ **CREATE OR REPLACE VIEW** ” command. Here is the basic syntax for updating a view in Postgres:
    
    
    CREATE OR REPLACE VIEW view_name AS
    SELECT col_list
    FROM tab
    WHERE conditions;

This statement assists the users in modifying the view’s definition without dropping it.

 **Example: How to Alter a View in Postgres?**

Let’s learn how to modify the definition of an already existing view in Postgres:
    
    
    CREATE OR REPLACE VIEW example_view AS
    SELECT st_id, st_name, st_phone, st_email
    FROM staff_data
    WHERE st_id > 1;

The above snippet shows that the “ **CREATE OR REPLACE VIEW** ” statement was executed successfully. Let’s execute the “SELECT *” command to query the updated view:
    
    
    SELECT * FROM example_view;

The output shows that the example_view has been updated successfully.

 **How to Drop a VIEW in Postgres?**

To use the DROP VIEW statement in Postgres, users must follow the below syntax:
    
    
    DROP VIEW <IF EXISTS> view_name;

The “IF EXISTS” is an optional clause used to avoid the view does not exist error.

 **Example: How Does the DROP VIEW Statement Work in Postgres?**

Execute the below-provided statement to delete a view named “example_view”:
    
    
    DROP VIEW example_view;

The output shows that the targeted view has been dropped successfully.

 **Conclusion**

In PostgreSQL, a **view** is a virtual table that is created based on a SELECT query. Postgres provides the “ **CREATE VIEW** ”, “ **CREATE OR REPLACE VIEW** ”, and “ **DROP VIEW** ” statements to create, update or drop a view from the database. The WHERE clause can be used with these statements to create, update, or delete a view based on some specific condition. This Postgres blog demonstrated various examples to explain the working of the “ **CREATE VIEW** ”, “ **CREATE OR REPLACE VIEW** ”, and “ **DROP VIEW** ” statements.

---
[View this page online](https://www.commandprompt.com/education/views-in-postgresql-create-view-drop-view-update-view/)

---

# How to Use POWER() Function in PostgreSQL

> The POWER() or POW() function accepts two numeric values as arguments and retrieves the first value raised to the power of the second value.

PostgreSQL offers a wide range of mathematical functions to work with numeric data, such as ABS(), MOD(), ROUND(), etc. The **POWER()** function is one of the mathematical functions used to calculate a number's power. In Postgres, the POWER() function can also be used as POW().

This write-up will teach you the basic syntax, working, and implementation of the Postgres POWER() function. So, let’s begin!

 **How to Use the POWER() Function in PostgreSQL?**

The POWER() or POW() function accepts two numeric values as arguments and retrieves the first value/argument raised to the power of the second value/argument:
    
    
    POWER(val_1, val_2);

val_1 and val_2 represent any numeric/double precision values.

 **Example 1: Find the Square of a Value Using the POWER() Function**

The following example will show you how the POWER() function works in Postgres:
    
    
    SELECT POWER(12, 2);

The output snippet proves that the POWER() function retrieves the accurate result (i.e., 12 * 12 = 144).

 **Example 2: Find the Cube of a Number Using the POWER() Function**

Let’s learn how to find the cube of a number using the Postgres POWER() function:
    
    
    SELECT POWER(5, 3);

The output snippet shows that the POWER() function retrieves the appropriate result (i.e., 5 * 5 * 5 = 125).

 **Example 3: Find Power of a Fractional Point Value Using the POWER() Function**

Let’s pass a fractional point value to the POWER function and see how the POWER() works in such a situation:
    
    
    SELECT POWER(12.14, 3);

The output shows that the POWER() function retrieves the accurate value.

 **Example 4: How to Use POWER() Function on Negative Values?**

In this example, we will use all three possibilities to use a negative value in POWER function:
    
    
    SELECT POWER(-5, 5), 
    POWER(-5, -5), 
    POWER(5, -5);

This is how the POWER() function works on negative values.

 **Example 5: Calculate the Power of Large Values**

Let’s execute the following command to see how the POWER() function works on large values:
    
    
    SELECT POWER(500, 12);

This way, the POWER() function deals with the large values.

 **Example 6: How to Use POWER() Function on Table’s Data?**

We have created a table named find_power, whose data is shown in the following snippet:

The find_power table contains various values. The below-provided table will show you an in-depth understanding of the POWER() function:
    
    
    SELECT val_1, val_2, POWER(val_1, val_2)
    FROM find_power;

This is how the POWER() function works on the table’s data.

 **Conclusion**

The POWER() or POW() function accepts two numeric values as arguments and retrieves the first value/argument raised to the power of the second value/argument. The POWER() function can calculate the power of any number, i.e., positive, negative, fractional, etc. This write-up explains Postgres’ POWER() function with practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-power-function-in-postgresql/)

---

# How to Sort Table Data BY Date in PostgreSQL

> To sort the table’s data into a specific format, the ORDER BY clause is used in Postgres. Postgres users must use the ORDER BY clause on the DATE type column t…

To sort the table’s data into a specific format, the ORDER BY clause is used in Postgres. Users can sort the table’s records based on any particular column using the ORDER BY clause. In Postgres, the table’s data can be sorted in ascending or descending format. Postgres users must use the ORDER BY clause on the DATE type column to sort the table data by date.

This Postgres blog will teach you how to sort a table by date via practical demonstration.

 **How Do I Sort the Table’s Data by Date in Postgres?**

The below syntax must be used in Postgres to sort the table’s data using ascending or descending order:
    
    
    SELECT col_list
    FROM table_name
    ORDER BY col_name [ASC | DESC];

In the above syntax:

\- The SELECT query will retrieve the data of the targeted table.  
\- col_list represents a column or list of columns to be fetched.  
\- Sorting the result set retrieved by the SELECT statement will be done with the ORDER BY clause.  
\- ORDER BY will sort the results according to the specified column.

 **Example#1: How to Sort Table Data by Date in Ascending Order?**

A table named “article_details”, whose details are shown in the below snippet:
    
    
    SELECT * FROM article_details;

The above snippet shows that the table contains unsorted data. Let’s sort the table’s data in ascending order for the “ **published_date** ” column:
    
    
    SELECT * FROM article_details
    ORDER BY published_date ASC;

The output verified that the table’s data had been sorted into ascending order (by means of the “published_date” column).

 **Example#2: How to Sort Table Data by Date in Descending Order?**

Let’s learn how to sort the table by date in descending order:
    
    
    SELECT * FROM article_details
    ORDER BY published_date DESC;

In the above query, the “ **DESC** ” keyword is used to sort the “published_date” column in descending order:

The output verified that the targeted table had been sorted in descending order(in terms of the published date column).

That’s it from this Postgres blog!

 **Conclusion**

To sort the table’s data into a specific format, the ORDER BY clause is used in Postgres. Postgres users must use the ORDER BY clause on the DATE type column to sort the table data by date. The SELECT query retrieves the result set in an unsorted format. Query results can be sorted using the ORDER BY clause. ORDER BY will sort the results according to the specified column. This write-up taught us how to sort a table by date in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-sort-table-data-by-date-in-postgresql/)

---

# Alias in PostgreSQL With Examples

> ALIASES are used in Postgres to provide a temporary name to the columns, tables, etc., while executing/writing Postgres queries.

PostgreSQL offers the concept of “ALIASES”, which provides ease to users while working with complex queries. ALIASES are used in Postgres to provide a temporary name to the columns, tables, etc., while executing/writing Postgres queries. ALIASES increase the readability of a table, column, etc.

This write-up will teach you how to use PostgreSQL's table and column aliases with practical examples. So let’s begin!

 **How Do I Use ALIAS for Long Table Names?**

You can use the alias for a table that has a long name, such as “this_is_example_table”. Adding aliases to tables will improve query readability and user experience. To avail the functionality of alias, the “AS” keyword is used in PostgreSQL:
    
    
    SELECT column_list
    FROM tab_name AS alias_name;

The above syntax shows that an “AS” keyword is used between the table and alias names. However, it is optional you can skip it as follows:
    
    
    SELECT column_list
    FROM tab_name alias_name;

The above query will work the same way as the previous one.

 **Example: How Does the Table Alias Work in Postgres?**

We have created a table named “article_details”, whose data is shown in the below snippet:
    
    
    SELECT * FROM article_details;

The above snippet shows the data of the “article_details” table. Suppose we want to fetch those articles whose id is greater than 6. To make the query easily readable, we can use the table aliases as follows:
    
    
    SELECT ad.article_id, ad.article_title, ad.published_date
    FROM article_details AS ad
    WHERE ad.article_id >= 6;

This is how the table ALIAS works in Postgres.

 **How Do I Use ALIAS for Table Columns?**

The below-mentioned syntax must be followed to use the column alias in Postgres:
    
    
    SELECT col_name AS alias_name
    FROM tbl_name;

The “AS” keyword is used in the above syntax for the column alias. It is optional and can be skipped, as shown in the below syntax:
    
    
    SELECT col_name alias_name
    FROM tbl_name;

The column will be assigned a new temporary name that can be used throughout the given query.

 **Example 1: How Does the Column Alias Work in Postgres?**

In this example, we will explain the working of the column alias using the article_info table, whose data is shown in the below snippet:
    
    
    SELECT * FROM article_info;

In the below snippet, we will utilize the column alias for the article_title column:
    
    
    SELECT article_title AS title
    FROM article_info;

This is how the column alias works in Postgres.

 **Example 2: How to Use Column Alias With Built-in Functions?**

We have created a table named “addition_example”, whose data is shown in the following snippet:
    
    
    SELECT * FROM addition_example;

Let’s perform addition on the given column using the built-in SUM() function. We will use the column alias to assign a temporary name to the resultant column:
    
    
    SELECT SUM(val) AS total
    FROM addition_example;

This way, you can use the column alias on built-in functions in Postgres.

 **Conclusion**

ALIASES are used in Postgres to provide a temporary name to the columns, tables, etc., while executing/writing Postgres queries. The aliases in Postgres improve query readability and enhance the user experience. To avail the functionality of alias, the “AS” keyword is used in PostgreSQL. PostgreSQL's table and column ALIASES were explained using practical examples in this write-up.

---
[View this page online](https://www.commandprompt.com/education/alias-in-postgresql-with-examples/)

---

# How to Fix Column Does not Exist Exception/Error in PostgreSQL

> In Postgres, the “column doesn’t exist” error occurs because of various reasons, such as the searched column doesn’t exist, typo mistakes, column alias being u…

In PostgreSQL, multiple scenarios can cause a Column doesn’t exist error. For instance, the searched column doesn’t exist in the targeted table, the column’s naming convention doesn’t match, typo mistakes, etc. The stated error might occur in Postgres while executing the SELECT query, UPDATE query, INSERT query, ALTER statement, etc. To rectify the stated error, multiple approaches can be used in PostgreSQL.

This write-up will show you various causes and their respective solutions in Postgres. This post will cover the below-listed content to fix the “column does not exist exception/error” in Postgres.

Reason 1: Column Doesn’t Exist  
\- Solution: Add the Respective Column

Reason 2: Incorrect Column Spelling  
\- Solution: Correct the Column Name

Reason 3: Using Column Alias Incorrectly  
\- Solution: Use the Column Alias Correctly

So, let’s begin!

 **Reason 1: Column Doesn’t Exist**

The most common reason that causes the stated error can be selecting a column that doesn’t exist in the targeted table. For instance, we have created a table named emp_info, whose data is shown in the below snippet:
    
    
    SELECT * FROM emp_info;

The above snippet shows that the emp_info table has two columns: emp_id and emp_name. Now, trying to insert the data into a column that doesn’t exist in the table will throw the stated error:
    
    
    INSERT INTO emp_info(emp_id, emp_name, emp_email)
    VALUES (3, 'Joe', 'joe321@xyz.com');

The output shows that a “column doesn’t exist” error occurred when we accessed a column that didn’t exist in the table.

 **Solution: Add the Respective Column**

To resolve the stated error, specify only those columns that exist in the targeted table or first add the desired column to the table; then, you can insert the data into that column. Execute the below command to add the “emp_email” column to the “emp_info” table:
    
    
    ALTER TABLE emp_info
    ADD COLUMN emp_email VARCHAR;

A new column has been added to the emp_info table. Now you can insert the data into that particular column as well:
    
    
    INSERT INTO emp_info(emp_id, emp_name, emp_email)
    VALUES (3, 'Joe', 'joe321@xyz.com');

The above snippet shows that the INSERT query was executed successfully, and the stated error has been resolved. You can verify the inserted data using the SELECT query:
    
    
    SELECT * FROM emp_info;

This is how you can rectify the stated error in Postgres.

 **Reason 2: Incorrect Column Spelling**

Another notable reason that can cause this error is accessing a column with incorrect spellings:
    
    
    SELECT emp_nam
    FROM emp_info;

The output snippet showed an error when a column was accessed with incorrect spellings. Postgres shows a hint that will help you rectify the stated error.

 **Solution: Correct the Column Name**

To rectify the stated error, you must access the table’s column with the correct spellings as shown in the “HINT”:
    
    
    SELECT emp_name 
    FROM emp_info;

The output shows that correcting the column’s spelling resolves the stated error.

 **Reason 3: Using Column Alias Incorrectly**

The “column doesn’t exist” error can occur if a column alias is used incorrectly. For instance, we have created two tables in Postgres named “article_details” and “article_info,” whose details are shown below:
    
    
    SELECT * FROM article_details;

Now, we will fetch all the details about the “article_info” table:
    
    
    SELECT * FROM article_info;

In the below snippet, we will use the column alias for the article_title column of the article_details table. Next, we will use the EXCEPT operator to find all those records that don’t exist in the article_info table. Finally, we will use the ORDER BY clause to sort the result set in descending order:
    
    
    (SELECT article_title AS titles FROM article_details)
    EXCEPT
    (SELECT article_title FROM article_info)
    ORDER BY article_title DESC;

In the above snippet, the stated error occurs because we use the column name instead of the column alias, which creates ambiguity.

 **Solution: Use the Column Alias Correctly**

To fix the stated error, either remove the column alias from the SELECT statement or use the column alias in the ORDER BY clause. Let’s use the column alias in the ORDER BY clause and see whether the stated error has been resolved or not:
    
    
    (SELECT article_title AS titles FROM article_details)
    EXCEPT
    (SELECT article_title FROM article_info)
    ORDER BY titles DESC;

The output snippet proves that the “column doesn’t exist” error has been resolved successfully.

 **Conclusion**

In PostgreSQL, the “column doesn’t exist” error can occur because of various reasons, such as the searched column doesn’t exist in the targeted table, typo mistakes, column alias being used incorrectly, etc. The stated error might occur in Postgres while executing the SELECT query, UPDATE query, INSERT query, ALTER statement, etc. Multiple approaches are explained in this Postgres guide to rectify the stated error.

---
[View this page online](https://www.commandprompt.com/education/how-to-fix-column-does-not-exist-exceptionerror-in-postgresql/)

---

# How to Define an Auto Increment Primary Key in PostgreSQL

> To define an auto-incremented primary key in Postgres, specify a column name followed by a pseudo data type named “SERIAL”, and then specify the PRIMARY KEY ke…

The primary keys are widely used in all relational databases, including Postgres. Developers prefer to create every table with a primary key. The primary keys in Postgres are used to identify a record uniquely. You can create a primary key for any data type; however, most frequently, the primary keys are defined using the INT data type. In such cases, the user specified a unique value for each primary key while inserting the data into a table.

In Postgres, a pseudo data type named “SERIAL” can be used for the PRIMARY KEY column to define an auto-incremented primary key.

This write-up will teach you how to define an auto-incremented primary key in Postgres via practical examples.

 **How to Define/Create an Auto Incremented Primary Key in Postgres?**

You can define an auto-increment primary key at the time of table creation using the following syntax:
    
    
    CREATE TABLE table_name(
    col_name SERIAL PRIMARY KEY
    )

An auto-incremented unique identifier will be created using the syntax above.

 **Example: How Do I Create/Define an Auto-Incremented Primary Key in Postgres?**

This example will show you how to define an auto-incremented primary key while table creation:
    
    
    CREATE TABLE company_details(
    c_id SERIAL PRIMARY KEY,
    c_ceo TEXT,
    ceo_id INT
    );

The above query will create an auto-incremented PRIMARY KEY named “c_id” for the company_details table:

The above snippet shows that a table named “company_details” has been created with three columns: c_id, c_ceo, and ceo_id. Now, we will execute the INSERT INTO statement to insert the data into the “company_details” table:
    
    
    INSERT INTO company_details(c_ceo, ceo_id)
    VALUES ('Joe', 5),
    ('Joseph', 2),
    ('Alex', 3),
    ('Ambrose', 1),
    ('Mike', 4),
    ('Seth', 6);

Since the c_id column is defined with the SERIAL data type, so there is no need to specify the value for that particular column while data insertion. The value of the c_id column will be auto-incremented for each record:

All the records have been inserted into the company_details table. Executing the SELECT * command will show the table’s data:
    
    
    SELECT * FROM company_details;

The output snippet authenticates the working of the auto-incremented primary key.

This is how you can create an auto-incremented Primary key in Postgres.

 **Conclusion**

To define an auto-incremented primary key in Postgres, specify a column name followed by a pseudo data type named “SERIAL”, and then specify the PRIMARY KEY keyword. In such cases, PostgreSQL will address all behind the scene complexities and auto-increment the primary key value for each insertion. This write-up explained how to define/create an auto-incremented primary in Postgres using the SERIAL pseudo-data type.

---
[View this page online](https://www.commandprompt.com/education/how-to-define-an-auto-increment-primary-key-in-postgresql/)

---

# ARRAY_TO_STRING() Function in PostgreSQL

> PostgreSQL offers an ARRAY_TO_STRING() function that accepts three arguments: an array, a delimiter, and a text to replace the null values.

PostgreSQL offers a built-in array function named **ARRAY_TO_STRING()** that accepts an array, converts it into strings, and concatenates the strings using a delimiter/separator. The separator can be any value, such as white space, comma, semi-colon, etc.

This write-up will teach you how to use the **ARRAY_TO_STRING()** function in Postgres via suitable examples. So, let’s start!

 **How to Use ARRAY_TO_STRING() Function in Postgres?**

In Postgres, the below-mentioned syntax is used for the ARRAY_TO_STRING() function:
    
    
    ARRAY_TO_STRING(arr, sep[, text]);

In the above syntax:

\- “arr” represents an array to be converted to strings.  
\- “sep” represents a separator/delimiter that will be used between the strings.  
\- “text” is an optional parameter that replaces the NULL values with the specified text.

The return type of the ARRAY_TO_STRING() function will be TEXT.

 **Example 1: How to Use ARRAY_TO_STRING() Function in Postgres?**

Let’s learn the working of the ARRAY_TO_STRING() function using the below code:
    
    
    SELECT ARRAY_TO_STRING(
    ARRAY[1, 23, 150, -1, 2, -3, -1, 12, 121], ',', '0'
    );

In this example:

\- An array is passed as the first argument.  
\- A comma is passed as a separator.  
\- And “0” is passed as the third parameter that will replace the NULL value(if any) with the 0.

The output snippet proves that the given array has been converted into a string, and a comma is concatenated with each array element.

 **Example 2: How Does the ARRAY_TO_STRING() Function Deals With the Null Values in Postgres?**

In the below-given input array, there are some NULL values. We will pass “0” as the third parameter to the ARRAY_TO_STRING() function. Consequently, it will replace the NULL value(if any) with 0:
    
    
    SELECT ARRAY_TO_STRING(
    ARRAY[1, 23, NULL, -1, 2, NULL, -1, NULL, 121], ',', '0'
    );

The output shows that the NULL values have been replaced with the specified null_text, i.e., “0”.

 **Example 3: How to Use ARRAY_TO_STRING() Function on Table’s Data in Postgres?**

We have created a table named “st_information” that contains the following data:
    
    
    SELECT * FROM st_information;

Let’s use the ARRAY_TO_STRING() function on “st_name” array to convert it into a string:
    
    
    SELECT ARRAY_TO_STRING(st_name, ':', '-')
    FROM st_information;

In the above example code:

\- An array-type column is passed as the first argument to the ARRAY_TO_STRING() function.  
\- A colon is passed as a separator/delimiter.  
\- “-” is passed as the third parameter that will replace the NULL value(if any) with “-”.

The output clarifies that the input array has been converted into a string.

That’s it from this Postgres tutorial!

 **Conclusion**

PostgreSQL offers a built-in array function named **ARRAY_TO_STRING()** that accepts three arguments: an array, a delimiter/separator, and a text to replace the null values. The **ARRAY_TO_STRING()** function converts the given array into strings and concatenates the strings using a delimiter/separator. The return type of the ARRAY_TO_STRING() function is TEXT. Postgres ARRAY_TO_STRING() function is explained with practical examples in this write-up.

---
[View this page online](https://www.commandprompt.com/education/array_to_string-function-in-postgresql/)

---

# PostgreSQL TRUNC() VS ROUND() Function

> The TRUNC() function trims the whole fractional part or up to specified precision, while the ROUND() function rounds the input number to the nearest integer/sp…

In PostgreSQL, the **TRUNC()** and **ROUND()** functions belong to the mathematical functions. The TRUNC() function trims the whole fractional part or up to specified precision, while the ROUND() function rounds the input number to the nearest integer/specified fractional places.

This blog post will compare the TRUNC(), and ROUND() functions through suitable examples. So, let’s begin.

 **PostgreSQL TRUNC() Function**

In Postgres, the TRUNC() function accepts a numeric value as an argument, trims the fractional part, and retrieves the resultant integer:
    
    
    TRUNC(val_1, val_2);

Here, the first argument indicates the input number, while the second argument determines the number of digits to be trimmed. Skipping the second argument will truncate the whole fractional part of the input number.

 **Example 1: TRUNC() Function With One Argument**

If you pass only a single value, then the TRUNC() function will trim the whole fractional part:
    
    
    SELECT TRUNC(7214.57212);

From the output, you can observe that the fractional part has been trimmed completely.

 **Example 2: TRUNC() Function With Two Arguments**

If you pass two values to the TRUNC() function, then the TRUNC() function will trim the input number based on the second value:
    
    
    SELECT TRUNC(7214.57212, 3);

In the TRUNC() function, we specified ‘3’ as a second argument, so the input number will keep only three digits and skips the remaining fractional part:

The output authenticates the working of the TRUNC() function.

 **PostgreSQL ROUND() Function**

In Postgres, the ROUND() function accepts a numeric value as an argument, rounds the fractional part up to the nearest integer, and retrieves the resultant integer:
    
    
    ROUND(val_1, val_2);

In the above syntax, the first argument represents the input number, while the second argument determines the number of digits to be rounded.

 **Note:** The ROUND() function rounds the number nearest integer(upward if the fractional value is greater than or equal to the “.5” and downward if the value is less than “.5”)

 **Example 1: ROUND() Function With One Argument ( >=.5)**

Let’s pass a numeric value to the ROUND() function and see how it works:
    
    
    SELECT ROUND(7214.57212);

Since the fraction value was >= .5, therefore the ROUND() function rounds up the given number to the nearest integer.

 **Example 2: ROUND() Function With One Argument ( <.5)**

We will pass a numeric value “7214.17212” to the ROUND() function in this example:
    
    
    SELECT ROUND(7214.17212);

The above snippet shows that the fractional part of the input value is less than “.5”. Let’s see how the ROUND() function work in such a situation:

The above snippet shows that the ROUND() function rounded down the input number to the nearest integer.

 **PostgreSQL TRUNC() VS ROUND() Function**

To understand the working of TRUNC() and ROUND() functions in a better way, let’s implement both these functions on the “pro_price” column of the product_details table:
    
    
    SELECT pro_price, ROUND(pro_price), TRUNC(pro_price)
    FROM product_details;

The output snippet proves that the TRUNC() function trims the fractional part irrespective of what exactly it is. While the ROUND() function rounds the input number based on the fractional/decimal part(i.e., >= .5 or <.5).

 **Conclusion**

TRUNC() and ROUND() are mathematical functions in PostgreSQL. The TRUNC() function trims the whole fractional part or up to specified precision, while the ROUND() function rounds the input number to the nearest integer/specified fractional places. The TRUNC() function trims the fractional part irrespective of what exactly it is(i.e., Greater than or less than .5). While the ROUND() function rounds the input number based on the fractional/decimal part. This write-up presented a comparative analysis of the Postgre TRUNC(), and ROUND() functions using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-trunc-vs-round-function/)

---

# String Arrays in PostgreSQL

> PostgreSQL allows us to create a string array using one of three data types: CHAR, VARCHAR, and TEXT. Once an array is created, various operations can be perfo…

PostgreSQL offers three types to work with the string data, i.e., **TEXT, VARCHAR,** and **CHAR**. Postgres allows us to create a string array using one of these data types. We can perform various operations on string arrays using different queries and built-in functions, such as insert, update, append, etc.

This write-up will teach you how to create and use string arrays in Postgres using practical examples. So, let’s start!

 **How to Create a String Array in Postgres?**

To create a string array in Postgres, specify the column name followed by the data type and a set of square brackets:
    
    
    CREATE TABLE st_information (
    st_id SERIAL PRIMARY KEY, 
    st_name TEXT[],
    st_email VARCHAR[]
    );

The st_information table with four columns has been created successfully.

 **How to Fetch/Display the Data of a String Array in Postgres?**

Execute the “SELECT *” command to show the table’s data:
    
    
    SELECT * FROM st_information;

The output shows that the st_information has three columns. Two of them are string-type arrays.

 **How Do I INSERT Data/Records Into a String Array in Postgres?**

In Postgres, the ARRAY keyword, followed by a set of square brackets, is used to insert data into a string array. Alternatively, a set of curly braces enclosed within the single quotations can be used in Postgres. Let’s learn how to insert data into a string array using the INSERT INTO statement:
    
    
    INSERT INTO st_information(st_name, st_email)
    VALUES('{"Joe", "Root"}', '{"joe@xyz.com", "ceo@xyz.com"}'),
    ('{"Tim", "David"}', '{"tim@xyz.com"}');

The above snippet shows that the INSERT INTO query was executed successfully. Let’s verify the data insertion using the “st_information” table:
    
    
    SELECT * FROM st_information;

The output clarifies that the data has been successfully inserted into the string arrays.

 **How to Update a String Array in Postgres?**

Use the UPDATE query with the SET clause to modify the whole string array or a specific index of the string array:
    
    
    UPDATE st_information
    SET st_email[1] = 'hr@xyz.com '
    WHERE st_id = 2;

Let’s run the SELECT query to see the modified value:
    
    
    SELECT * FROM st_information;

The output proves that the targeted string array has been updated successfully.

 **How to Append an Element to String Array in Postgres?**

You can use any array function to achieve various functionalities, such as the ARRAY_APPEND() function, the ARRAY_LENGTH() function, etc. In this example, we will use the append function to append “tim@xyz.com” at the end of the “st_email” array:
    
    
    SELECT ARRAY_APPEND(st_email, 'tim@xyz.com')
    FROM st_information
    WHERE st_id = 2;

The above snippet shows that an element is appended at the end of the input string array.

That’s it from this Postgres guide!

 **Conclusion**

PostgreSQL allows us to create a string array using one of three data types: CHAR, VARCHAR, and TEXT. We can perform various operations on string arrays using different queries and built-in functions, such as INSERT, UPDATE, ARRAY_APPEND(), etc. This write-up explained how to create a string array and perform various operations on that array using different queries and built-in functions.

---
[View this page online](https://www.commandprompt.com/education/string-arrays-in-postgresql/)

---

# ARRAY_REMOVE() Function in PostgreSQL

> ARRAY_REMOVE() function accepts an array and a specific number as arguments and deletes all the occurrences of that particular number from the input array.

PostgreSQL offers a built-in **ARRAY_REMOVE()** function that is used to delete all the occurrences of a specific value. The ARRAY_REMOVE() function works on one-dimensional arrays. It can be used to remove any type of data, such as INT, TEXT, VARCHAR, etc.

This write-up will teach you how the **ARRAY_REMOVE()** function works in Postgres. So, let’s begin!

 **How to Use the ARRAY_REMOVE() Function in Postgres?**

ARRAY_REMOVE() is an inbuilt array function that accepts an array and a specific number as arguments and deletes all the occurrences of that particular number from the input array. The input array must be one-dimensional:
    
    
    ARRAY_REMOVE(input_array, num);

The input_array represents an array from which the input number “num” will be removed.

 **Example 1: How to Remove a Numeric Value From an Array in Postgres?**

In this example, we will eliminate all the occurrences of “-1” from the given array:
    
    
    SELECT ARRAY_REMOVE(
    ARRAY[1, 23, 150, -1, 2, -3, -1, 12, 121], -1
    );

In the above example program, an array is passed as the first argument, and “-1” is passed as the second argument. Consequently, all the occurrences of “-1” will be deleted from the input array:

From the output, you can observe that “-1” has been removed from the resultant array.

 **Example 2: How to Remove a String Value From an Array in Postgres?**

This example will show you the usage of the ARRAY_REMOVE() function on the string-type data:
    
    
    SELECT ARRAY_REMOVE(
    ARRAY['Ambrose', 'Joseph', 'Alexa', 'Anna', 'Joseph', 'Stephanie', 'Joseph'], 'Joseph'
    );

In this example program, a string array is passed as the first argument, and “Joseph” is passed as the second argument. Consequently, all the occurrences of “Joseph” will be eliminated from the given string array:

The output snippet verifies that the ARRAY_REMOVE() function successfully removes the specified string from the array.

 **Example 3: Is ARRAY_REMOVE() Case-sensitive?**

Let’s run the following command to see if the ARRAY_REMOVE() function is case-sensitive or not:
    
    
    SELECT ARRAY_REMOVE(
    ARRAY['Ambrose', 'Joseph', 'Alexa', 'Joseph', 'Stephanie', 'Joseph'], 'joseph'
    );

The output snippet proves that the ARRAY_REMOVE() function is case-sensitive.

 **Example 4: How to Use ARRAY_REMOVE() Function on Table’s Data?**

We have created a table named “st_information” that contains the following data:
    
    
    SELECT * FROM st_information;

Suppose we want to remove “joe” from the st_name column. For that purpose, we will use the ARRAY_REMOVE() function as follows:
    
    
    SELECT ARRAY_REMOVE(st_name, 'Joe')
    FROM st_information;

The output snippet authenticates that a string “Joe” has been removed from the st_name column.

That’s it from this Postgres blog!

 **Conclusion**

ARRAY_REMOVE() is an inbuilt array function that accepts an array and a specific number as arguments and deletes all the occurrences of that particular number from the input array. The input array must be one-dimensional. The ARRAY_REMOVE() function is case-sensitive. It can be used to remove/eliminate any type of data, such as INTEGER, TEXT, VARCHAR, etc. Postgres ARRAY_REMOVE() function is explained with practical examples in this write-up.

---
[View this page online](https://www.commandprompt.com/education/array_remove-function-in-postgresql/)

---

# How to Update Multiple Rows in PostgreSQL

> In PostgreSQL, the UPDATE statement must be executed with the semi-colon-separated syntax to modify multiple rows with different values.

PostgreSQL provides an UPDATE statement that is used along with the SET clause to update any particular table record. UPDATE statement uses the WHERE clause to specify a condition for updating the specific table records. All the rows that satisfy the given criteria will be updated with the specified value in such a case. If you didn’t specify a WHERE clause in the UPDATE query, then the entire table will be modified with the specified value.

This write-up will teach you how to update several records using a single UPDATE statement. So, let’s begin!

 **How to Update Multiple Rows in Postgres?**

The below-mentioned syntax is used to update the table’s record with a new value:
    
    
    UPDATE tbl_name
    SET column_1 = value_1, column_2 = value_2, …, column_n = value_n
    WHERE criteria;

Using the above syntax, you can modify one or more than one column.

 **Example 1: Updating Multiple Rows With the Same Value**

We have created a table named “emp_info” that contains the following records:
    
    
    SELECT * FROM emp_info;

We will update all employees whose emp_id is less than 4 with "Seth" by executing the below statement:
    
    
    UPDATE emp_info 
    SET emp_name = 'Seth'
    WHERE emp_id < 4;

The output shows that three records have been updated, you can verify updated records using the following statement:

The output authenticates that multiple records have been updated with the same value.

 **Example 2: Updating All Rows With the Same Value**

We can modify all table rows at once by skipping the WHERE clause from the UPDATE statement:
    
    
    UPDATE emp_info 
    SET emp_name = 'Seth';

The above snippet will update all the rows of the emp_name column with the same value, i.e., “Seth”:

The output snippet shows that six records have been modified. Let’s verify the updated rows using the SELECT command:
    
    
    SELECT * FROM emp_info;

The output authenticates that skipping the WHERE clause updated the whole column with the same value.

 **Example 3: Updating Multiple Rows With Different Values**

We must execute the update query with the semi-colon-separated syntax to modify multiple rows with different values:
    
    
    UPDATE emp_info SET emp_id = 10, emp_name = 'joseph' WHERE emp_id = 3;
    UPDATE emp_info SET emp_id = 12, emp_name = 'joe' WHERE emp_id = 1;
    UPDATE emp_info SET emp_id = 13, emp_name = 'Ambrose' WHERE emp_id = 2;

Let’s verify the updated records using the SELECT statement:
    
    
    SELECT * FROM emp_info;

The output verified that multiple records had been updated in the emp_info table.

That’s it from this Postgres blog!

 **Conclusion**

In PostgreSQL, the UPDATE query must be executed with the semi-colon-separated syntax to modify multiple rows with different values. In Postgres, the UPDATE statement is used along with the SET clause to update any particular table record. In the WHERE clause, users can specify a condition based on which the table will be updated. All the rows that satisfy the given criteria will be updated with the specified value in such a case. Skipping the WHERE clause will modify the entire table with the specified value. This write-up explained how to update multiple table rows with the same or different values using the Postgres UPDATE query.

---
[View this page online](https://www.commandprompt.com/education/how-to-update-multiple-rows-in-postgresql/)

---

# ARRAY_REPLACE() Function in PostgreSQL

> The ARRAY_REPLACE() is an inbuilt array function in Postgres that allows us to replace all the occurrences of an array element with a new element.

PostgreSQL provides several built-in functions that perform different functionalities on the arrays. For instance, the **ARRAY_LENGTH()** function is used to find the length of an array, the **ARRAY_CAT()** is used to concatenate two arrays, etc. The **ARRAY_REPLACE()** is also an array function that replaces an array's specific value with a new value.

This write-up will teach you how to replace a specific value in an array using the Postgres **ARRAY_REPLACE()** function. So, let’s start!

 **How to Use ARRAY_REPLACE() Function in PostgreSQL?**

The ARRAY_REPLACE() is an inbuilt array function in Postgres that allows us to replace all the occurrences of an array element with a new element. It accepts three arguments: an array, an element to be replaced, and an element that will replace the targeted array element:
    
    
    ARRAY_REPLACE(arr, val_1, val_2);

In the above snippet:

\- arr represents an array to be modified.  
\- val_1 represents the array element to be replaced.  
\- val_2 represents a new element that will be inserted in the targeted array in place of val_1.

 **Example 1: How to Replace an Integer Value in an Array Using ARRAY_REPLACE() Function?**

The below-given code will replace all the occurrences of the “-1” with 5 in the given array:
    
    
    SELECT ARRAY_REPLACE(
    ARRAY[1, 23, 150, -1, 2, -3, -1, 12, 121], -1, 5
    );

In the above example program, an array is passed as the first argument, “-1” is passed as the second argument, and 5 is passed as the third argument. Consequently, all the occurrences of “-1” will be replaced with 5 in the input array:

The output shows that “-1” has been replaced with “5” in the resultant array.

 **Example 2: How to Replace a String Value in an Array Using ARRAY_REPLACE() Function?**

Let’s learn how to use the ARRAY_REPLACE() function on the string-type array in Postgres:
    
    
    SELECT ARRAY_REPLACE(
    ARRAY['Ambrose', 'Joe', 'Alexa', 'Joe', 'Mike', 'Joe'], 'Joe','Joseph'
    );

In the above snippet, the ARRAY_REPLACE() function is used to replace “Joe” with “Joseph”:

The output proves that the targeted element has been replaced with “Joseph” in the resultant array.

 **Example 3: Is ARRAY_REPLACE() Case-sensitive?**

Let’s run the following code to see if the ARRAY_REPLACE() function is case-sensitive or not:
    
    
    SELECT ARRAY_REPLACE(
    ARRAY['Ambrose', 'Joe', 'Alexa', 'Joe', 'Mike', 'Joe'], 'joe','Joseph'
    );

The output shows that the ARRAY_REPLACE() function didn’t replace the targeted element. It proves that the ARRAY_REPLACE() function is case-sensitive.

 **Example 4: How to Use ARRAY_REPLACE() Function on Table’s Data?**

We have created a table named “st_information” that contains the following data:
    
    
    SELECT * FROM st_information;

Suppose we want to replace “Joe” with “Alex” in the st_name column. For that purpose, we will use the ARRAY_REPLACE() function as follows:
    
    
    SELECT ARRAY_REPLACE(st_name, 'Joe', 'Alex')
    FROM st_information;

The above snippet proves that an array element “Joe” has been replaced with “Alex”.

 **Conclusion**

The ARRAY_REPLACE() is an inbuilt array function in Postgres that allows us to replace all the occurrences of an array element with a new element. It accepts three arguments: an array, an element to be replaced, and an element that will replace the targeted array element. Postgres ARRAY_REPLACE() function is explained with practical examples in this write-up.

---
[View this page online](https://www.commandprompt.com/education/array_replace-function-in-postgresql/)

---

# Wildcards in PostgreSQL With Practical Examples

> Pattern matching in PostgreSQL is performed using wildcards. PostgreSQL offers two wildcards represented with a percentage sign “%” and an underscore sign “_”.

In PostgreSQL, wildcards are used to perform pattern matching. PostgreSQL supports two types of wildcards represented with a percentage sign **“%,”** and an underscore sign “_”. The percentage wildcard "%" matches sequences of characters, while the underscore wildcard "_" matches a single character. These wildcards are used with the LIKE operator to perform the pattern matching.

This write-up will teach you what wildcards are and how to use them in Postgres. So, let’s begin!

 **Underscore Wildcard “_” in Postgres**

In PostgreSQL, the underscore wildcard is used to signify only a single number/character. For instance, the below-given syntaxes will be used to achieve different functionalities in Postgres:
    
    
    _x

The above pattern will be used to fetch all those values that start with anything but their second letter must be “x”.
    
    
    _x_

The above pattern indicates that you can place anything at the first and third index however the second index must have the letter “x”.

This way, you can create different patterns using the underscore wildcard.

 **Percentage Wildcard “%” in Postgres**

In PostgreSQL, the percentage wildcard is used to signify zero, one, or more than one number/character. For instance, the below-given syntaxes will be used to achieve different functionalities in Postgres:
    
    
    %xx%

The above pattern will fetch all those values containing a substring “xx”.
    
    
    %xx

The above pattern indicates that it will be used to find all those strings that end with “xx”.
    
    
    xx%

The above pattern indicates that it will be used to find all those strings that start with “xx”.

This way, you can use the percentage wildcard to match the pattern.

 **Note:** Use both wildcards combinedly to achieve maximum functionality.

 **Example 1: Find a Substring “Function”**

We have created a table named “article_info”, whose data is shown in the following snippet:
    
    
    SELECT * FROM article_info;

We will utilize the percent wildcard to find a substring “function” from the article_title column of the given table:
    
    
    SELECT article_title 
    FROM article_info
    WHERE article_title LIKE '%Function%';

The output snippet proves that there are two titles in the “artile_info” table that contain a substring “Function”.

 **Example 2: Find a Title Whose Second Last Letter is “r”**

In this example, we will use the underscore wildcard to find all those titles whose second last letter is “r”
    
    
    SELECT article_title FROM article_info
    WHERE article_title LIKE '%r_';

In the above example, we utilized the combination of both percent and underscore wildcards. The % sign states there can be anything at the start of the string. The second last letter must be “r”, and the underscore wildcard at the end of the string indicates that there will be only one letter after “r”:

The output snippet authenticates the working of the Postgres wildcards.

 **Conclusion**

Pattern matching in PostgreSQL is performed using wildcards. PostgreSQL offers two wildcards represented with a percentage sign **“%”** and an underscore sign “_”. The percentage wildcard "%" matches sequences of characters/numbers, while the underscore wildcard "_" matches a single character/number. This write-up explained how to use wildcards in Postgres using practical examples.

---
[View this page online](https://www.commandprompt.com/education/wildcards-in-postgresql-with-practical-examples/)

---

# STRING_TO_ARRAY() Function in PostgreSQL

> The STRING_TO_ARRAY() function accepts a string as the first argument, splits it into array elements, and concatenates the array elements using a delimiter/sep…

PostgreSQL provides various array functions such as **ARRAY_APPEND(), ARRAY_TO_STRING(), ARRAY_REPLACE()** , etc. **STRING_TO_ARRAY()** is one of them. Each array function serves a unique functionality. For instance, the STRING_TO_ARRAY() function converts a string into an array.

This write-up will teach you how to use the **STRING_TO_ARRAY()** function in Postgres via suitable examples. So, let’s start!

 **How to Use the STRING_TO_ARRAY() Function in Postgres?**

In PostgreSQL, STRING_TO_ARRAY() is a built-in array function that accepts three arguments: a string, a delimiter, and a text to replace the null values. The STRING_TO_ARRAY() function accepts a string as the first argument, splits it into array elements, and concatenates the array elements using a delimiter/separator. The separator can be any value, such as white space, comma, semi-colon, etc.
    
    
    STRING_TO_ARRAY(str, sep[, text]);

In the above syntax:

\- “str” represents a string to be converted into an array.  
\- “sep” represents a splitter based on which the given string will be split to array elements.  
\- “text” is an optional parameter that replaces the NULL values with the specified text.

 **Note:** The return type of the STRING_TO_ARRAY() function will be an ARRAY.

 **Example 1: What Does the STRING_TO_ARRAY() Function Do in Postgres?**

This example will explain the working of the STRING_TO_ARRAY() function in Postgres:
    
    
    SELECT STRING_TO_ARRAY(
    'HELLO WELCOME TO COMMAND PROMPT', ' ');

In the above example:

\- A string is passed to the STRING_TO_ARRAY() function as the first argument.  
\- White space is passed as a second argument to the STRING_TO_ARRAY() function, which will split the given string from the white spaces:

The above snippet shows that the given string has been split into array elements.

 **Example 2: How Does the STRING_TO_ARRAY() Function Work on Table’s Data in Postgres?**

We have created a table named “employee_data” that consists of three columns: emp_id, emp_name, and emp_email_address:
    
    
    SELECT * FROM employee_data;

The above snippet shows that the emp_name column has string-type data. Let’s use the STRING_TO_DATE() function on the “emp_name” column to convert the string into an array:
    
    
    SELECT STRING_TO_ARRAY(emp_name, ' ')
    FROM employee_data;

The above snippet authenticates that the STRING_TO_ARRAY() function was executed successfully. The STRING_TO_ARRAY() function splits the input string into array elements. The output shows that the return type of the returned array is text.

That’s it from this Postgres guide!

 **Conclusion**

In PostgreSQL, **STRING_TO_ARRAY()** is a built-in array function that accepts three arguments: a string, a delimiter, and a text to replace the null values. The STRING_TO_ARRAY() function accepts a string as the first argument, splits it into array elements, and concatenates the array elements using a delimiter/separator. The separator can be any value, such as white space, comma, semi-colon, etc. This write-up explained Postgres' STRING_TO_ARRAY() function with practical examples.

---
[View this page online](https://www.commandprompt.com/education/string_to_array-function-in-postgresql/)

---

# ARRAY_CAT() Function in PostgreSQL

> ARRAY_CAT() is another very convenient function in Postgres that is used to concatenate two arrays. It accepts two arrays as arguments and retrieves a concaten…

PostgreSQL offers a variety of built-in functions that are used to perform different functionalities on the arrays. For instance, **ARRAY_APPEND()** function appends an element to an array, **ARRAY_LENGTH()** function finds the length of an array, the **ARRAY_REMOVE()** function removes the elements from an array, and so on. **ARRAY_CAT()** is another very convenient function in Postgres that is used to concatenate two arrays.

This write-up will teach you how to concatenate two arrays using the **ARRAY_CAT()** function in PostgreSQL. So, let’s get started!

 **How to Use ARRAY_CAT() Function in Postgres?**

The **ARRAY_CAT()** function accepts two arrays as arguments and retrieves a concatenated array. For this purpose, use the below-mentioned syntax:
    
    
    ARRAY_CAT(arr_1, arr_2);

In the above snippet, arr_1 and arr_2 represent the arrays to be concatenated.

 **Example 1: How to Concatenate Two NUMERIC Arrays in Postgres?**

Suppose we want to concatenate the following two arrays: [1, 23, 150, -1, 2, 0, 12, 14] and [-3, -1, 12, 121, 21, 32, 54]. To do that, we will pass both these arrays as arguments to the ARRAY_CAT() function:
    
    
    SELECT ARRAY_CAT(
    ARRAY[1, 23, 150, -1, 2, 0, 12, 14], 
    ARRAY[-3, -1, 12, 121, 21, 32, 54]
    );

The output shows that the ARRAY_CAT() function successfully concatenated the input arrays. The data type of the retrieved array is INT.

 **Example 2: How to Concatenate Two STRING Arrays in Postgres?**

Let’s learn how to concatenate two string-type arrays using the ARRAY_CAT() function:
    
    
    SELECT ARRAY_CAT(
    ARRAY['Ambrose', 'John', 'Joe', 'Joseph'], 
    ARRAY['Natie', 'Alexa', 'Anna', 'Stephanie']
    );

The output proves that the ARRAY_CAT() function successfully concatenated the given string arrays. The data type of the retrieved array is TEXT.

 **Example 3: How to ARRAY_CAT() Function on Table’s Data?**

We have created a table named st_information that contains the following data:
    
    
    SELECT * FROM st_information;

The above snippet shows that the st_information table has two string-type arrays. To concatenate both these arrays, you can use the ARRAY_CAT() function as follows:
    
    
    SELECT ARRAY_CAT(st_name, st_email)
    FROM st_information;

The output snippet proves that both arrays have been merged successfully. The data type of the retrieved array is TEXT.

That’s it from this Postgres guide!

 **Conclusion**

 **ARRAY_CAT()** is another very convenient function in Postgres that is used to concatenate two arrays. For this purpose, the **ARRAY_CAT()** function accepts two arrays as arguments and retrieves a concatenated array. The data type of the retrieved array depends on the input arrays. Postgres ARRAY_CAT() function is explained with practical examples in this write-up.

---
[View this page online](https://www.commandprompt.com/education/array_cat-function-in-postgresql/)

---

# How to Filter Data Using PostgreSQL WHERE Clause

> In PostgreSQL, the WHERE clause allows us to filter the result set retrieved by the UPDATE, SELECT, or DELETE query. The WHERE clause filters the data based on…

In PostgreSQL, the **WHERE** clause is used to filter the result set retrieved by the UPDATE, SELECT, or DELETE query. Using the **WHERE** clause, you can specify single or various conditions based on which the data will be filtered. Only those records will be added to the result set that satisfies the given criteria, and the rest of the records will be eliminated.

This post will teach you how to use the WHERE clause to filter the data of a result set retrieved by any query. So, let’s begin!

 **How to Filter Data Using PostgreSQL WHERE Clause?**

The logical and comparison operators can be used within the WHERE clause to specify one or more conditions. The WHERE clause must be specified before the GROUP BY clause, ORDER BY clause, and HAVING clause. As shown in the syntax below, it must be placed right after the FROM clause:
    
    
    SELECT col_list
    FROM tab_name
    WHERE condition | conditions
    GROUP BY col_list
    HAVING condition 
    ORDER BY ASC | DESC;

 **Note:** In the above syntax, the GROUP BY clause, HAVING clause, and ORDER BY clause are optional. In the above snippet, we specify all these clauses just to show you the order in which these clauses will be used.

 **Example 1: Filter Articles Whose id is Less Than 6**

We have created a table named article_details, whose details are listed in the below snippet:
    
    
    SELECT * FROM article_details;

Execute the below query to filter the articles with article_id less than 6:
    
    
    SELECT article_id, article_title, published_date
    FROM article_details
    WHERE article_id < 6;

The output shows that the WHERE clause filters the result set based on the specified condition.

 **Example 2: Filter Data Based on Two Conditions**

In this example, we will show you how to specify two conditions in the WHERE clause using logical operators:
    
    
    SELECT article_id, article_title, published_date
    FROM article_details
    WHERE article_id >= 3 AND article_id <= 9;

The above-specified query will filter the articles between the article_id greater than or equal to three but less than or equal to nine:

The output shows that the WHERE clause filters the data based on the specified conditions.

 **Example 3: Filter Data Between Two Values**

Let’s use the WHERE clause to filter the articles between article id 4 to 9:
    
    
    SELECT article_id, article_title, published_date
    FROM article_details
    WHERE article_id BETWEEN 4 AND 9;

The output snippet verifies that article details have been fetched between the specified ranges.

This way, you can use any comparison or logical operator within the WHERE clause to specify a condition.

 **Conclusion**

In PostgreSQL, the **WHERE** clause allows us to filter the result set retrieved by the UPDATE, SELECT, or DELETE query. The **WHERE** clause filters the data based on a specific condition or several conditions. Only those records will be added to the result set that satisfies the given criteria, and the rest of the records will be eliminated. This write-up explained how to filter the data in PostgreSQL using the WHERE clause.

---
[View this page online](https://www.commandprompt.com/education/how-to-filter-data-using-postgresql-where-clause/)

---

# How to Insert Data Into an Array in PostgreSQL

> In PostgreSQL, several syntaxes can be used to insert data into an array, such as using the ARRAY keyword with square brackets “[]” or curly braces enclosed wi…

In PostgreSQL, we can create arrays of any type while table creation, such as INT, TEXT, VARCHAR, etc. Using arrays in Postgres, we can store data of any predefined, user-defined, and enumerated type. Once an array is created in Postgres, you can perform any specific operation on the array, such as inserting data into an array, appending to an array, fetching the array’s data, etc.

Several approaches for inserting data into a Postgres array will be explained in this write-up via practical examples.

 **Create a Sample Table**

The below snippet shows how to create an array column during table creation:
    
    
    CREATE TABLE employee_data(
    emp_id INT PRIMARY KEY,
    emp_name TEXT,
    emp_email_address VARCHAR[]
    );

The desired table has been created successfully. You can execute the SELECT statement to check the table’s structure:
    
    
    SELECT * FROM employee_data;

The output shows that the “employee_data” table has three columns.

 **Inserting Data Into Postgres Arrays**

Several syntaxes can be used to insert data into a Postgres array, such as using the **ARRAY** keyword with square brackets “[]” or curly braces enclosed within single quotes.

 **Syntax 1: ARRAY Keyword With Square Brackets “[]”**

The below syntax explains how to insert data into an array using the ARRAY keyword:
    
    
    INSERT INTO table_name (col_list)
    VALUES (ARRAY ['val_1','val_2']);

The above syntax shows that the **INSERT INTO** statement is used to insert the data into an array in Postgres.

 **Example 1: Inserting Data Into an Array Using ARRAY Keyword**

Let’s learn how to insert data into any particular array using the ARRAY keyword:
    
    
    INSERT INTO employee_data (emp_id, emp_name, emp_email_address)
    VALUES (1, 'Alex Root', ARRAY ['alex@xyz.com','ceo@xyz.com']),
    (2, 'Tim Joseph', ARRAY ['tim@xyz.com', 'joseph@xyz.com']),
    (3, 'Mike Ambrose', ARRAY ['ambrose@xyz.com']),
    (4, 'Seth Jones', ARRAY ['seth@xyz.com']),
    (5, 'Stephenie Tylor', ARRAY ['stephenie@xyz.com','hr@xyz.com']);

Five records have been inserted into the employee_data table. Let’s verify the data insertion via the SELECT query:
    
    
    SELECT * FROM employee_data;

This is how you can insert the data into an array in Postgres.

 **Syntax 1: Using Curly Braces**

The below syntax explains how to insert data into an array using the curly braces:
    
    
    INSERT INTO table_name (col_list)
    VALUES ('{val_1, val_2, …, val_n}');

Let’s understand it practically!

 **Example: Inserting Data Into an Array Using Curly Braces**

In this example, we will explain how to insert data using curly braces syntax:
    
    
    INSERT INTO employee_data (emp_id, emp_name, emp_email_address)
    VALUES (6, 'Ben Stokes', '{"ben@xyz.com","stokes@xyz.com"}'),
    (7, 'Mitchel Marsh', '{"mitch@xyz.com", "marsh@xyz.com"}'),
    (8, 'Paul Allen', '{"paul@xyz.com"}');

Let’s verify the data insertion using the SELECT statement:
    
    
    SELECT * FROM employee_data;

The output proves that the data has been inserted into the array successfully.

 **Conclusion**

In PostgreSQL, several syntaxes can be used to insert data into an array, such as using the ARRAY keyword with square brackets “[]” or curly braces enclosed within single quotes. Any of these syntaxes can be used with the INSERT INTO statement to insert data into a Postgres array. This write-up explains how to insert data into a Postgres array using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-insert-data-into-an-array-in-postgresql/)

---

# How to Rename a User/Role in PostgreSQL

> In PostgreSQL, the RENAME TO clause is used along with the ALTER USER or the ALTER ROLE statement to rename a user/role.

PostgreSQL provides a **RENAME TO** clause that is used with the **ALTER ROLE** or the **ALTER USER** statements to rename a user. In Postgres, the session user(currently logged in) can't be renamed. You must log out from the current user and log in as another user to rename the current session user.

This write-up will teach you how to rename a user in Postgres via ALTER ROLE and ALTER USER commands.

 **How Do I Rename a User/Role in Postgres Using ALTER ROLE Command?**

The below syntax must be followed to rename a user in Postgres:
    
    
    ALTER ROLE user_name
    RENAME TO new_user_name;

Let’s implement it practically!

 **Example 1: Rename User Using ALTER ROLE Statement**

Firstly, execute the “\du” command to see the available users:
    
    
    \du;

Suppose we want to rename the “sample_user” to “sample_role”. For this purpose, the ALTER ROLE statement will be executed as follows:
    
    
    ALTER ROLE sample_user
    RENAME TO sample_role;

Let’s verify the user alteration via the “\du” command:
    
    
    \du;

The output snippet shows that the “sample_user” has been renamed to “sample_role”.

 **Example 2: Rename Currently Logged in User**

We are logged in as “command_prompt”

Let’s try to rename it using the ALTER ROLE statement:
    
    
    ALTER ROLE command_prompt
    RENAME TO cp_user;

An error occurred when we tried to rename the session user. To rectify this error, we must log in from some other user, as shown below:

In the above snippet, we are logged in as “postgres” users. Let’s execute the ALTER ROLE statement to rename the “command_prompt” user to “cp_user”:
    
    
    ALTER ROLE command_prompt
    RENAME TO cp_user;

The above snippet verifies that the ALTER ROLE statement was executed successfully. Let’s verify the role’s modified name using the “\du” command:
    
    
    \du;

The output clarifies that the “command_prompt” user has been renamed to “cp_user” successfully.

 **How Do I Rename a User/Role in Postgres Using ALTER USER Command?**

To rename a user via **ALTER USER** statement, specify the **ALTER USER** statement followed by the user name. Next, specify the RENAME TO clause and the new username:
    
    
    ALTER USER user_name
    RENAME TO new_user_name;

Let’s understand this concept practically.

 **Example: Rename User Using ALTER USER Statement**

Let’s check the available users using the “\du” command:
    
    
    \du;

Suppose we need to rename the “example_user” to “user_1”. For this purpose, we will execute the “ALTER USER” statement as follows:
    
    
    ALTER USER example_user
    RENAME TO user_1;

You can verify the user’s modified name using the “\du” command:
    
    
    \du;

The output snippet verifies that the “example_user” has been renamed to “user_1” successfully.

 **Conclusion**

In PostgreSQL, the **RENAME TO** clause is used with the **ALTER USER** or **ALTER ROLE** statement to rename a user. In Postgres, the session user(currently logged in) can't be renamed. To do that, log out from the current user, log in as another user, and execute the ALTER USER or ALTER ROLE statement with the RENAME TO clause to rename the current session user. This write-up explained how to rename a user/role in Postgres via the ALTER ROLE and ALTER USER statements.

---
[View this page online](https://www.commandprompt.com/education/how-to-rename-a-userrole-in-postgresql/)

---

# How to Insert Bulk Data in PostgreSQL

> In PostgreSQL, bulk data can be inserted into a table using an INSERT INTO statement or COPY command. In Postgres, the COPY command allows us to load bulk data…

In PostgreSQL, bulk data can be inserted into a table using an [**INSERT INTO**](<https://www.commandprompt.com/education/how-to-use-insert-query-in-postgresql/>) statement or [**COPY**](<https://www.commandprompt.com/education/how-to-import-a-csv-file-to-a-postgresql-table/>) command. In Postgres, the COPY command allows us to load bulk data from one or more files. While the multi-value INSERT command allows us to insert bulk data into a Postgres table in one go.

This blog post will show you how to insert bulk data in Postgres using INSERT and COPY commands. So, let’s begin!

 **How to Insert Bulk Data in Postgres Using INSERT Statement?**

The comma-separated syntax must be used to insert bulk data using a single INSERT statement:
    
    
    INSERT INTO table_name (column_list) 
    VALUES
    (value_list_1),
    (value_list_2),
    (value_list_3),
    ...
    (value_list_n);

Here, in the above syntax, the “table_name” represents a table where data will be inserted. The “column_list” represents the targeted columns, while “vlaue_list_n” represents the “n” number of values to be inserted into the selected table.

 **Example 1: How Do I Insert Bulk Data Using INSERT Statement?**

Let’s execute the **SELECT** statement to see the structure of an already created table named “shorlisted_students”:
    
    
    SELECT * FROM shortlisted_students;

The output snippet shows that the “shortlisted_students” table has three columns: student_id, student_name, and student_email. Let’s learn how to insert the bulk data into the targeted table via the INSERT statement:
    
    
    INSERT INTO shortlisted_students(student_id, student_name, student_email) 
    VALUES
    (1, 'Joe', 'joe@abc.com'),
    (2, 'Joseph', 'joseph@abc.com'),
    (3, 'Stephenie', 'stephenie@abc.com'),
    (4, 'Natie', 'natie@abc.com'),
    (5, 'Shaun', 'shaun@abc.com'),
    (6, 'John', 'john@abc.com'),
    (7, 'Anna', 'joe@abc.com'),
    (8, 'Nataliya', 'nataliya@abc.com'),
    (9, 'Sasha', 'sasha@abc.com'),
    (10, 'Ambrose', 'ambrose@abc.com');

The bulk of ten records has been inserted into the “shortlisted_students” table successfully. Let’s verify the bulk insertion via the below-stated command:
    
    
    SELECT * FROM shortlisted _students;

In this example, we inserted only ten records; however, you can insert as many records as you want using a single INSERT statement.

 **How to Insert Bulk Data in Postgres Using COPY Command?**

To insert the bulk data via COPY command, users must follow the below syntax:
    
    
    COPY table_name [(column_list)]
    FROM 'file_name| file_path' 
    CSV HEADER;

The above snippet will copy the bulk data from the CSV file to the Postgres table.

 **Example # How Do I Copy Bulk Data Using COPY Command?**

Let’s execute the **SELECT** statement to see the structure of an already created table named “staff_info”:
    
    
    SELECT * FROM staff_info;

The above snippet shows that the staff_info table has three columns. Suppose we want to insert bulk data from a CSV file into a Postgres table. The CSV file contains the following data:

Inserting every single row one by one will be a time taking process. So, to save time, we will execute the COPY command as follows:
    
    
    COPY staff_info FROM 'C:\Windows\Temp\students_info.csv' CSV HEADER;

The output snippet indicates that the copy command executed successfully. To verify the bulk insertion, you can execute the following query:
    
    
    SELECT * FROM staff_info;

From the output snippet, you can clearly observe that the bulk data has been inserted/copied into the staff_info table successfully.

 **Conclusion**

In PostgreSQL, bulk data can be inserted into a table using an INSERT INTO statement or COPY command. The COPY command in Postgres lets us load bulk data from single or multiple files. Also, we can use the multi-value INSERT command to insert bulk data into a Postgres table in one go. For this purpose, the INSERT statement is used with the comma-separated syntax in Postgres. This blog post explained how to insert bulk data in Postgres using INSERT and COPY commands.

---
[View this page online](https://www.commandprompt.com/education/how-to-insert-bulk-data-in-postgresql/)

---

# How to Create a User in PostgreSQL

> To create a user in Postgres, specify the “CREATE USER” command followed by the user name, and after that, assign the privileges to the user using the “WITH” c…

PostgreSQL provides a **CREATE USER** command that assists us in creating the users. Using **CREATE USER** command, we can create an ordinary or a superuser. While creating a user, we can specify the privileges to that particular user, such as login, CREATEDB, CREATEROLE, etc. In PostgreSQL, you can also create a user via pgAdmin.

Through practical examples, this blog post will show you how to create a user in Postgres.

 **How to Use CREATE USER Command in PostgreSQL?**

To create a user in Postgres, specify the “ **CREATE USER** ” command followed by the user name, and after that, assign the privileges to the user using the “ **WITH** ” clause:
    
    
    CREATE USER user_name WITH option;

In place of the option, you can assign any privileges of your choice, such as SUPERUSER, PASSWORD, VALID UNTIL, LOG-IN, CONNECTION LIMIT, CREATEDB, CREATEROLE, etc.

 **Note:** You can specify multiple options for a single user using the space-separated syntax.

 **Example 1: How to Create a User in Postgres?**

Let’s learn how to create an ordinary user with the “ **CREATEDB** ” and “ **CREATE ROLE** ” privileges:
    
    
    CREATE USER tsep 
    WITH CREATEDB CREATEROLE;

In the above snippet:

\- We created a user named “tsep” using the CREATE USER statement.  
\- Next, we utilized the WITH clause to assign multiple options to the user named “tsep”.  
\- The user named tsep will have CREATEDB and CREATEROLE privileges.

In the above snippet, the “ **CREATE ROLE** ” message appears as a output when we execute the **CREATE USER** statement. It proves that the specified user has been created. To verify the user creation, you can execute the “\du” command as follows:
    
    
    \du;

The output authenticates that the user named “tsep” has been created with the specified attributes.

 **Example 2: How to Create a Superuser in Postgres?**

To create a superuser in Postgres, execute the CREATE USER statement and assign it the SUPERUSER attribute with the assistance of the WITH clause:
    
    
    CREATE USER TSEP_LTD 
    WITH SUPERUSER;

The output snippet authenticates that the user named TSEP_LTD has been created. Let’s verify the user’s creation using the “\du” command:
    
    
    \du;

The above snippet verifies that a superuser named “tsep_ltd” has been created successfully.

 **How to Create a User/Role in Postgres Using pgAdmin?**

To create a user via pgAdmin, firstly, launch the pgAdmin, expand the “Servers” tree and follow the below-listed steps:

 **Step 1: Select Login/Group Roles**

In pgAdmin, search for the “Login/Group Roles” under the “Servers” tree. Once you find the “Login/Group roles” option, right-click on it, then hover over the “Create” option and click on the “Login/Group Roles”:

Clicking on the “Login/Group roles” option will pop up a new window.

 **Step 2: Specify User’s Name**

In the “Create-Login/Group roles” window, specify the name of the role:

 **Step 3: Select Definition Tab**

Now switch to the definition tab, and provide the password and its validity date:

In the above snippet, we specified a password that will expire on “2022-12-31 11:59:00 +05:00”.

 **Step 4: Assign Privileges**

Select the "Privileges" tab and select the attributes that you want to assign to the role:

The above snippet indicates that the specified role is a superuser.

 **Step 5: Check SQL Query**

To see the respective SQL query for the specified role, select the “SQL” tab:

Click on the Save button to create a user named “example_role” with superuser privileges.

 **Step 5: Verify User’s Creation**

Expand the “Login/Group roles” and search for the newly created user:

The output snippet authenticates that the user named “example_role” has been created successfully.

 **Conclusion**

In PostgreSQL, a user can be created using the CREATE USER statement. To do so, specify the “ **CREATE USER** ” command followed by the user name, and after that, assign the privileges to the user using the “ **WITH** ” clause. Postgres allows us to create a user via pgAdmin. To do that, firstly right-click on the “Login/ roles” option, then hover over the “Create” option and click on the “Login/Group Roles”. After that, specify the login details and privileges. Finally, hit the save button to create a user. This blog post explained how to create a user via pgAdmin and SQL SHELL.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-user-in-postgresql/)

---

# How to Concatenate a String and a Number in PostgreSQL

> PostgreSQL allows us to concatenate a string with a number using a built-in “CONCAT()” function or a pipe concatenation operator “||”.

PostgreSQL allows us to concatenate a string with a number using a built-in “ **CONCAT()** ” function or a pipe operator **“||”**. Using these two approaches, we can add a separator, like a comma, space, etc., between a string and a number.

This blog post will show you how to concatenate a string with a number using the practical implementation of the **CONCAT()** function and pipe concatenation operator **“||”**.

 **Key Points**

Before learning how to concatenate a string and a number in Postgres, firstly, we need to understand the following points:

\- The return type of the pipe concatenation operator **||** and CONCAT() function is “ **TEXT** ”.  
\- Multiple strings can be concatenated using the **CONCAT()** function or the || operator.  
\- Using the **CONCAT()** function or the **||** operator, you can concatenate the strings with a number.  
\- In Postgres, you can’t concatenate only numeric values using the **CONCAT()** function or || operator. There must be at least one string. This is because the return type of both these approaches is **TEXT**.  
\- Concatenating a NULL value with a number or string will retrieve “ **NULL** ”.

 **Concatenating a String and a Number in Postgres Using CONCAT() Function**

To concatenate a string with a number, users must pass a string and a number to the CONCAT() function as arguments:
    
    
    CONCAT(arg_1, arg_2);

 **Example 1: How Do I Concatenate a String With a Number Using CONCAT() Function?**

Suppose we have a string “ **Postgres** ” and the number “ **14.4** ”. Suppose we want to concatenate the given string and the number. To do so, we will execute the **CONCAT()** function as follows:
    
    
    SELECT CONCAT('Postgres', 14.4);

The output authenticates the working of the CONCAT() function as it concatenates the given number and a string successfully.

 **Example 2: Concatenate a String and a Number With a Separator**

You can use a separator like space, comma, semicolon, etc., between the given string and number to present the concatenated result in a better way:
    
    
    SELECT CONCAT('Postgres', ':', 14.4);

The given number and string are concatenated using the ":" as a separator.

 **Example 3: Concatenate Table’s Column Using CONCAT() Function**

In our Postgres database, we have a table named “emp_info” that contains the following records:
    
    
    SELECT * FROM emp_info;

Let’s learn how to concatenate a numeric column with a string-type column using the CONCAT() function:
    
    
    SELECT CONCAT(emp_id, ',', emp_name)
    FROM emp_info;

The output shows that a numeric column has been successfully concatenated with a text-type column.

 **How to Concatenate a String and a Number in Postgres Using “||” Operator?**

To concatenate a string with a number, users must use the pipe concatenation operator between the input values as follows:
    
    
    SELECT arg_1 || arg_2;

You can append any separator between the input values using the || operator.

 **Example 1: Concatenate a Number With a String Using Pipe Concatenation Operator**

In this example, we will concatenate a string “PostgreSQL” and a number “14.4” using the **“||”** operator:
    
    
    SELECT 'PostgreSQL' || ' ' || 14.4;

The output proves that the input values have been concatenated successfully.

 **Example 2: Concatenate a Numeric Column With a String Type Column Using || Operator**

Let’s concatenate the “ **emp_id** ”, and “ **emp_name** ” columns of the “ **emp_info** ” table using the **||** operator:
    
    
    SELECT emp_id || '-' || emp_name
    FROM emp_info;

The output shows that both columns have been concatenated successfully.

 **Conclusion**

PostgreSQL allows us to concatenate a string with a number using a built-in “ **CONCAT()** ” function or a pipe operator **“||”**. The return type of the pipe concatenation operator || and CONCAT() function is “TEXT”. So, using these methods, you can concatenate multiple strings and numbers in Postgres. Through practical examples, this blog post explained how to concatenate a string with a number in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-concatenate-a-string-and-a-number-in-postgresql/)

---

# How to Use ALTER USER Statement in PostgreSQL

> A Postgres user&#x27;s attributes can be changed using the ALTER USER statement. Using the ALTER USER command, we can modify/alter the user&#x27;s password, privileges, …

PostgreSQL offers an **ALTER USER** statement that is used to modify the attributes of a Postgres user. The ALTER USER command allows us to alter/change the user password, privileges, properties, etc. In Postgres, the superusers can use the ALTER USER command to modify the attributes of any Postgres users. However, ordinary users can only change their attributes using the ALTER USER statement.

This Postgres blog will cover the below-given aspects of the ALTER USER statement:

  * How to Alter User Permissions in Postgres?
  * How to Alter User Password in Postgres?
  * How to Alter User's Validity Date in Postgres?
  * How to Alter a User to Superuser in Postgres?



So, let’s begin!

 **How to Alter User Permissions in Postgres?**

In PostgreSQL, use the “ **ALTER USER** ” statement with the help of the “ **WITH** ” clause to change the user’s permission:
    
    
    ALTER USER user_name WITH user_privileges;

The above snippet shows that to change the user’s permission, you must use the ALTER USER statement followed by the user name. After that, specify the WITH clause followed by the permissions that you want to assign to that particular user.

Let’s do it practically.

 **Example: Change User Permissions**

Let’s follow the below steps to change the user permissions:

 **Step 1: List of Users**

Let’s log in as a superuser and execute the below command to see the list of users:
    
    
    \du;

In the above snippet, you can see that the user named “sample_user” doesn’t have the privileges to create a role, database, user, etc.

 **Step 2: Change Permissions**

Let’s assign CREATEDB and CREATEROLE privileges to the “sample_user” using ALTER USER statement:
    
    
    ALTER USER sample_user 
    WITH CREATEDB, CREATEROLE;

In the above snippet, the “ALTER ROLE” message shows that the “ALTER USER” statement executed successfully.

 **Step 3: Verify User Permissions**

Let’s execute the “\du” command to verify the user permissions:
    
    
    \du;

The above snippet proves that the user privileges have been altered/modified successfully.

 **How to Alter User Password in Postgres?**

Use the **ALTER USER** statement with **PASSWORD** attribute and specify the modified password within the single quotation to alter the user’s password:
    
    
    ALTER USER user_name
    WITH PASSWORD 'modified_password';

Specify the modified password of your choice in place of the ‘modified_password’.

 **Example: Change the User Password in Postgres**

Let’s suppose we want to change the password of the “hr_role” user. For this purpose, we will use the ALTER USER statement as follows:
    
    
    ALTER USER hr_role
    WITH PASSWORD '12345';

The above snippet proves that the password has been changed.

 **How to Alter User 's Validity Date in Postgres?**

To alter the user’s password validity date, use the ALTER USER with VALID UNTIL clause:
    
    
    ALTER USER user_name
    WITH PASSWORD 'modified_password'
    VALID UNTIL 'expiry_date_time';

In the above-given syntaxes:

\- The ALTER USER is the Postgres statement that modifies a particular role/user.  
\- user_name is a user to be modified.  
\- Specify the modified password of your choice in place of the ‘modified_password’.  
\- VALID UNTIL is used to specify the password validation until a specific date and time.

 **Example: Change a User’s Password Validity Date in Postgres**

Let’s alter the password validity date of a user named ‘sample_user’:
    
    
    ALTER USER sample_user
    WITH PASSWORD '123456'
    VALID UNTIL '2025-12-10 11:59:59';

Let’s verify the working of the ALTER USER statement:
    
    
    \du sample_user;

The output proves that the “sample_user” has been altered successfully.

 **How to Alter a User to Superuser in Postgres?**

Use the **ALTER USER** command with the **SUPERUSER** attribute to modify a user to superuser in Postgres:
    
    
    ALTER USER user_name 
    WITH SUPERUSER;

In the above snippet:

\- user_name represents a user to be altered.  
\- WITH is an option used to specify the SUPERUSER attribute.

 **Example: Change User to Superuser in Postgres**

Follow the steps provided below to change a particular user to a superuser in Postgres:

 **Step 1: List Users**

Run the “\du” command to get the list of users:
    
    
    \du;

The output shows that a user named “hr_role” is an ordinary user.

 **Step 2: Alter User to Superuser**

Let’s suppose we want to alter an ordinary user “hr_role” to a super user:
    
    
    ALTER USER hr_role 
    WITH SUPERUSER;

The “ALTER ROLE” message proves that the ALTER USER statement was executed successfully.

 **Step 3: Verify Superuser**

Let’s verify the superuser via the below command:
    
    
    \du;

The output authenticates that the user named “hr_role” has been altered successfully.

That’s it from this Postgres guide.

 **Conclusion**

A Postgres user's attributes can be changed using the **ALTER USER** statement. We can modify/alter a user's password, privileges, etc., with the ALTER USER command. The superusers in Postgres can change any Postgres user's attributes using the ALTER USER command. While ordinary users can only change their own attributes using the ALTER USER command. This Postgres guide has explained the working of ALTER USER statements via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-alter-user-statement-in-postgresql/)

---

# How to Find Logged In Users in PostgreSQL

> To find the logged-in users in Postgres, the “pg_stat_activity” view is used. While to find all Postgres users, a system table named &quot;pg_user&quot; is used.

PostgreSQL allows us to find/check all the users or only those users that are currently logged into Postgres. To find all users, a system table named “ **pg_user** ” is used, while to find only currently logged-in users, a system view named “ **pg_stat_activity** ” is used in Postgres.

This blog post will explain how to find logged-in users in Postgres. For that purpose, the below-listed concepts will be covered in this write-up:

  * How to Find Users in Postgres?
  * How to Find Currently Logged-in Users in Postgres?



 **How to Find Users in Postgres?**

Use the pg_user table to find all the users, including ordinary users, superusers, etc. The pg_user table has various columns, as shown below:

\- **usesysid** : It represents the user ID.  
\- **usename** : It represents the user name.  
\- **usersuper** : It retrieves a boolean value: “t” if the user is a superuser, and “f” if the user is not a superuser.  
\- **usecreatedb:** It retrieves a boolean “ **t** ” or “ **f** ”: “t” if a user has privileges to create a database and “f” if the user doesn’t create a database.  
\- **passwd** : It represents the user password.  
\- **valuntil** : It shows the validity date of the password.  
\- **usecatupd** : It retrieves a boolean value “ **t** ” or “ **f** ”: “ **t** ” represents the user can update the system catalogs, while “ **f** ” represents the user can’t update the system catalogs.  
\- **userepl** : It retrieves a boolean value, “ **t** ” or “ **f** ”, which signifies whether the user can initiate replication or not.  
\- **useconfig** : It shows the session defaults for the runtime configuration variable.

 **Example: How Do I Find the Users in Postgres?**

In this example, we will find user names, IDs, and createdb privileges using the pg_user table:
    
    
    SELECT usename, usesysid, usecreatedb
    FROM pg_user;

The output shows that the pg_user table retrieves the “ **user names** ”, their “ **system ids** ”, and “ **create database** ” privileges successfully.

 **How to Find Currently Logged-in Users in Postgres?**

Use the pg_stat_activity to find all users currently connected/logged in to PostgreSQL. The “ **pg_stat_activity** ” consists of the following columns that are used to get all the information regarding a user:

\- **usesysid** : It represents the user ID.  
\- **usename** : It represents the user name.  
\- **pid** : It represents the Process ID.  
\- **datid** : It indicates the database ID where the process is executing.  
\- **datname** : It represents the database name.  
\- **client_hostname** : It indicates the client's hostname.  
\- **client_port:** It retrieves the client's port number.  
\- **client_addr** : It shows the client's address.  
\- **application_name:** It represents the application name.  
\- **query** : It represents a current query.  
\- **state** : It shows the query state.  
\- **query_start** : It represents the query’s start time.  
\- **state_change** : This column shows the time when the state of the query was changed.  
\- **waiting:** It retrieves a boolean value( **t** or **f** ) that indicates the query's waiting status.

 **Note** : To view processes owned by other users, you must have superuser privileges.

 **Example: How Do I Find the Currently Logged-in Users in Postgres?**

In this example, we will find the names and IDs of the users currently logged in to Postgres:
    
    
    SELECT DISTINCT usename, usesysid
    FROM pg_stat_activity;

The above snippet shows that currently, two users are logged into PostgreSQL.

 **Conclusion**

To find the logged-in users in Postgres, the “pg_stat_activity” view is used. The “ **pg_stat_activity** ” view consists of various columns that are used to get all the information regarding a user, such as usesysid, usename, pid, etc. In PostgreSQL, to find all the users, including ordinary users, superusers, etc., use the pg_user table. This blog post explained how to find the logged in users in PostgreSQL via practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-logged-in-users-in-postgresql/)

---

# Postgres Length Functions With Practical Examples

> Postgres offers various built-in length functions to calculate the length of a string, such as LENGTH(), BIT_LENGTH(), CHAR_LENGTH(), and BYTE_LENGTH().

In PostgreSQL, you can perform various operations on the strings, such as concatenating various strings, finding the length of strings, extracting substrings from strings, etc. To manipulate the string data efficiently, Postgres offers a wide range of built-in string functions, such as **CONCAT(), LENGTH(), SUBSTRING(),** etc.

Several length functions will be explained by examples in this blog post.

 **What are Length Functions in PostgreSQL?**

Postgres offers various built-in length functions to calculate the length of a string. The length functions, along with the description listed below:

\- **LENGTH()** : The length function takes a string as an argument and retrieves the length of the input string(total number of characters, including white spaces).  
\- **CHAR_LENGTH()** : The CHAR_LENGTH() or CHARACTER_LENGTH() function calculates the string’s length in terms of characters(same as the LENGTH() function).  
\- **BIT_LENGTH():** The BIT_LENGTH() function retrieves the length of the string in terms of bits.  
\- **OCTET_LENGTH():** The OCTET_LENGTH() function accepts a string as an argument and retrieves the string’s length in terms of bytes.

 **Example 1: How Do I Use the LENGTH() Function in Postgres?**

Let’s comprehend the working of the Postgres LENGTH() function by passing a string as an argument to it:
    
    
    SELECT LENGTH('Hello! Welcome to commandprompt.com');

The snippet provided above shows that the LENGTH() function retrieves the string’s length by counting the number of characters, including spaces.

 **Example 2: How Do I Use the CHAR_LENGTH() Function in Postgres?**

The CHAR_LENGTH() function works the same as the LENGTH() function, i.e., it accepts a string as an argument and retrieves the length of the string by counting the total number of characters:
    
    
    SELECT CHAR_LENGTH();

The output authenticates the working of the CHAR_LENGTH() function as it retrieves the total numbers present in the input string.

 **Example 3: How Do I Use the BIT_LENGTH() Function in Postgres?**

Let’s pass a string to the BIT_LENGTH() function and see how it works in Postgres:
    
    
    SELECT BIT_LENGTH('Hello! Welcome to commandprompt.com');

The output shows that the BIT_LENGTH() function retrieves the string length in bits.

 **Example 4: How Do I Use the OCTET_LENGTH() Function in Postgres?**

Let’s pass the same string to the OCTET_LENGTH() and see how it works:
    
    
    SELECT OCTET_LENGTH('Hello! Welcome to commandprompt.com');

The OCTET_LENGTH() function retrieves the output in bytes.

To comprehend the working of each function, let’s consider the below example.

 **Example 5: How Do I Use the OCTET_LENGTH() Function in Postgres?**

Firstly, let’s create a table named “sample_tab” with two columns: id and value:
    
    
    CREATE TABLE sample_tab(
    id INT, 
    value VARCHAR);

Let’s insert a bulk of values into the “smaple_tab” table:
    
    
    INSERT INTO sample_tab (id, value)
    VALUES (1, ‘a’),
    (2, ‘₩'),
    (3, ‘hello world’);

Three values have been inserted into the “smaple_tab”. Now let’s implement each of the length functions on the table’s data to clarify their working:
    
    
    SELECT value, LENGTH(value), 
    CHAR_LENGTH(value),
    BIT_LENGTH(value),
    OCTET_LENGTH(value)
    FROM sample_tab;

“₩” is a special symbol that takes three bytes:

\- So, when it is passed to LENGTH() and CHAR_LENGTH() functions, they consider it a single character and hence retrieve ‘1’ as the total length.  
\- When the “₩” symbol is passed to the BIT_LENGTH() function, it calculates and retrieves the total number of bits as output. Since one byte is equal to eight bits, therefore, it retrieves 24 as output (3*8).  
\- The OCTET_BYTE() retrieves “3” since the “₩” symbol takes three bytes.

 **Conclusion**

Postgres offers various built-in length functions to calculate the length of a string, such as **LENGTH(), BIT_LENGTH(), CHAR_LENGTH(),** and **BYTE_LENGTH()**. The LENGTH() and CHAR_LENGTH() functions take a string as an argument and retrieve the length of the input string(total number of characters, including white spaces). The BIT_LENGTH() function retrieves the length of the string in terms of bits. While the OCTET_LENGTH() function accepts a string as an argument and retrieves the string’s length in terms of bytes. This write-up demonstrated the working of various length functions using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgres-length-functions-with-practical-examples/)

---

# How to Change a User to Superuser in PostgreSQL

> In PostgreSQL, the ALTER USER and ALTER ROLE statements are used along with the SUPERUSER attribute to change an ordinary user to a superuser.

A superuser account with broad privileges is required for system administration. Superusers in Postgres have access to high-level privileges beyond ordinary users. To create a superuser in Postgres, use the **CREATE ROLE** or **CREATE USER** statement with the **SUPERUSER** attribute. However, if you have already created a user without the SUPERUSER attribute, you can modify it using the **ALTER USER** or **ALTER ROLE** command.

This Postgres blog will teach you how to change a user to a superuser via practical examples. The below concepts will be covered in this blog post:

  * Create an Ordinary User
  * How to Change an Ordinary User to a Superuser Using ALTER USER Statement?
  * How to Change an Ordinary User to a Superuser Using ALTER ROLE Statement?



 **Create an Ordinary User**

Firstly, let’s create a user without SUPERUSER privileges using the CREATE USER command:
    
    
    CREATE USER Joe;

Run the \du command to verify the user creation:
    
    
    \du;

The above snippet shows that a user named “joe” has been created without the “ **SUPERUSER** ” attribute.

 **How to Change an Ordinary User to a Superuser Using ALTER USER Statement?**

To change an ordinary user to a superuser in Postgres, use the ALTER USER command with the SUPERUSER attribute:
    
    
    ALTER USER user_name WITH SUPERUSER;

In the above syntax, user_name represents a user to be altered, while the “WITH” option is used to specify the SUPERUSER attribute.

 **Example: How Do I Change an Ordinary User to Superuser in Postgres?**

Run the “ALTER USER” command using the “WITH” clause to change a user named “joe” to a superuser:
    
    
    ALTER USER joe WITH SUPERUSER;

Run the below command to check if the specified user has been changed to the superuser or not:
    
    
    \du;

The output snippet proves that the “joe” has been changed to a superuser successfully.

 **How to Change an Ordinary User to a Superuser Using ALTER ROLE Statement?**

To alter an existing role/user to a superuser, execute the ALTER ROLE statement with the SUPERUSER clause as follows:
    
    
    ALTER ROLE user_name
    WITH SUPERUSER;

In the above syntax, user_name represents a user to be altered, while the “WITH” option is used to specify the SUPERUSER attribute.

 **Example: How Do I Change an Ordinary User to Superuser in Postgres?**

Suppose we need to alter a user named “emp_limit” to the superuser. For this purpose, we will execute the **ALTER ROLE** command as follows:
    
    
    ALTER ROLE emp_limit 
    WITH SUPERUSER;

The targeted role has been altered successfully. Let’s verify it via the below command:
    
    
    \du;

The output authenticates the working of ALTER ROLE statement as it succeeded in changing an ordinary user to a superuser.

 **Conclusion**

In PostgreSQL, the **ALTER USER** and **ALTER ROLE** statements are used to change an ordinary user to a superuser. For this purpose, execute the ALTER USER or ALTER ROLE statement along with the **SUPERUSER** attribute. To specify a SUPERUSER attribute, the “WITH” option is used in PostgreSQL. This Postgres blog taught us how to change an ordinary user to a super user using ALTER USER and ALTER ROLE statements.

---
[View this page online](https://www.commandprompt.com/education/how-to-change-a-user-to-superuser-in-postgresql/)

---

# PostgreSQL DROP CONSTRAINT With Practical Examples

> In PostgreSQL, Users must execute the DROP CONSTRAINT with the ALTER TABLE command to drop any particular constraint from a Postgres table.

PostgreSQL offers a “ **DROP CONSTRAINT** ” clause that allows us to drop any constraint from an existing table. For instance, PRIMARY KEY CONSTRAINT, UNIQUE CONSTRAINT, FOREIGN KEY CONSTRAINT, CHECK CONSTRAINT, or NOT NULL CONSTRAINT.

This blog post will explain how to drop a constraint in PostgreSQL through Practical examples. So, let’s begin!

 **How to Drop a Constraint in Postgres?**

To drop any particular constraint from a Postgres table, users must execute the **DROP CONSTRAINT** with the **ALTER TABLE** command.

The following content will be covered in this section regarding adding or dropping a CONSTRAINT in PostgreSQL:

  * Create a Sample Table
  * How to Drop a PRIMARY KEY CONSTRAINT in Postgres?
  * How to Drop a FOREIGN KEY CONSTRAINT in Postgres?
  * How to Drop a UNIQUE CONSTRAINT in Postgres?
  * How to Drop a CHECK CONSTRAINT in Postgres?
  * How to Remove/Drop a NOT NULL CONSTRAINT From a Postgres Table?



 **Create a Sample Table**

Firstly, we will create a sample table with some columns without any constraints. Afterward, we will add and drop a specific constraint according to the requirement.
    
    
    CREATE TABLE staff_bio(
    st_id INT,
    st_name TEXT,
    st_department TEXT,
    st_age SMALLINT
    );

The table name **staff_bio** has been created with four columns: st_id, st_name, st_department, and st_age.

 **How to Drop a PRIMARY KEY CONSTRAINT in Postgres?**

In Postgres, Primary keys are used to identify a table’s record uniquely. This section will teach you how to add or drop a PRIMARY KEY CONSTRAINT in Postgres Using ALTER TABLE command.

 **Step 1: Add Primary Key Constraint**

Firstly, let’s add a primary key constraint on the “st_id” column using **ALTER TABLE** command and **ADD CONSTRAINT** clause:
    
    
    ALTER TABLE staff_bio
    ADD CONSTRAINT st_id_pk 
    PRIMARY KEY (st_id);

In the above snippet,

\- The “staff_bio” is a table to be altered.  
\- The “st_id_pk” represents the name of the primary key.  
\- The “st_id” represents a primary key column.

The “ALTER TABLE” message in the output window proves that the “staff_bio” table has been modified successfully. Let’s validate the table’s structure via the following command:
    
    
    SELECT * FROM staff_bio;

This way, you can add a primary key to any table’s column.

 **Step 2: Drop Primary Key Constraint**

The DROP CONSTRAINT clause can be used in conjunction with ALTER TABLE to drop a primary key constraint from a Postgres table.
    
    
    ALTER TABLE staff_bio
    DROP CONSTRAINT st_id_pk;

In this coding example, we dropped a primary key constraint named st_id_pk from the staff_bio table:

Let’s verify the constraint deletion via the below command:
    
    
    SELECT * FROM staff_bio;

The output clarifies that the primary key constraint has been removed successfully.

 **How to Drop a FOREIGN KEY CONSTRAINT in Postgres?**

A FOREIGN KEY is a column that points to the PRIMARY KEY of some other Postgres table.

In this section, we will learn how to add or drop a FOREIGN KEY CONSTRAINT in Postgres Using ALTER TABLE command.

To explain the concept of foreign key constraint, we will use the “staff_info” and “employee_info” tables, whose details are shown below:
    
    
    SELECT * FROM customers_info;
    
    
    SELECT * FROM orders_details;

 **Step 1: Add Foreign Key Constraint**

Suppose we want to refer the “ **customer_id** ” column from the “ **orders_details** ” table to the “ **c_id** ” column of the “ **order_details** ” table. To do that, let’s run the below statement:
    
    
    ALTER TABLE orders_details
    ADD CONSTRAINT fk_ord_cust 
    FOREIGN KEY (customer_id) REFERENCES customers_info (c_id);

The output snippet shows that the foreign key constraint has been added to the orders_details table successfully.

 **Step 2: Drop Foreign Key Constraint**

To drop a foreign key constraint from a table, use the ALTER TABLE with the DROP CONSTRAINT clause:
    
    
    ALTER TABLE orders_details
    DROP CONSTRAINT fk_ord_cust;

The “ALTER TABLE” message in the output window proves that the foreign key named “fk_ord_cust” has been dropped successfully.

 **How to Drop a UNIQUE CONSTRAINT in Postgres?**

A **UNIQUE** constraint in Postgres ensures that all the rows in a column are unique. When a new record is inserted in a table, the UNIQUE constraint checks whether or not the input record already exists in the targeted table.

 **Step 1: Add a UNIQUE Constraint**

To add a UNIQUE constraint on the “st_id” column, use the **ALTER TABLE** command alongside **ADD CONSTRAINT** clause:
    
    
    ALTER TABLE staff_bio
    ADD CONSTRAINT st_id_unique UNIQUE (st_id);

In the above snippet,

\- The “staff_bio” is a table to be altered.  
\- The “st_id_unique” represents unique constraint.  
\- The UNIQUE constraint will be applied to the column named "st_id".

Let’s verify the working of the UNIQUE constraint by adding a couple of duplicate records in the st_id column:
    
    
    INSERT INTO staff_bio(st_id, st_name, st_department, st_age)
    VALUES (1, 'Joe', 'HR', 24),
    (1, 'Joseph', 'Author', 26);

The stated error proves that duplicate entries can’t be inserted into a column that is created with a UNIQUE CONSTRAINT.

 **Step 2: DROP a UNIQUE Constraint**

A UNIQUE constraint can be dropped from a column using the DROP CONSTRAINT clause with ALTER TABLE statement.
    
    
    ALTER TABLE staff_bio
    DROP CONSTRAINT st_id_unique;

In the above snippet:

\- staff_bio is a table to be altered/modified.  
\- st_id_unique is a unique constraint that needs to be dropped from the staff_bio table.

To verify if the UNIQUE constraint is dropped or not, insert a couple of duplicate records in the st_id column. If the column accepts the duplicate records, this means the UNIQUE constraint has been dropped:
    
    
    INSERT INTO staff_bio(st_id, st_name, st_department, st_age)
    VALUES (1, 'Joe', 'HR', 24),
    (1, 'Joseph', 'Author', 26);

Two records with the same “st_id” have been inserted into the staff_bio table. It proves that the UNIQUE constraint has been removed from the st_id column.

 **How to Drop a CHECK CONSTRAINT in Postgres?**

In Postgres, the CHECK constraint is used to insert/update values into a column based on some particular condition.

 **Step 1: Add CHECK Constraint**

Execute the ALTER TABLE alongside ADD CONSTRAINT clause to add a check constraint to a table’s column:
    
    
    ALTER TABLE staff_bio
    ADD CONSTRAINT check_st_age 
    CHECK (st_age <= 20);

In the above snippet:

\- staff_bio is a table to be modified.  
\- check_st_age represents the name of the check constraint.  
\- CHECK (st_age <= 20) means the st_age column will accept only values less than or equal to 20.

Let’s verify the working of the CHECK constraint by adding a value greater than 20 in the st_age column:
    
    
    INSERT INTO staff_bio(st_id, st_name, st_department, st_age)
    VALUES (1, 'Joe', 'HR', 24);

The stated error proves that only those entries will be accepted by the st_age column that satisfies the specified condition for the CHECK CONSTRAINT.

 **Step 2: Drop CHECK Constraint**

To drop a CHECK constraint from a table’s column, use the DROP CONSTRAINT clause with the collaboration of the ALTER TABLE command.
    
    
    ALTER TABLE staff_bio
    DROP CONSTRAINT check_st_age;

In the above snippet, check_st_age is a constraint (check) to be dropped:

To verify if the CHECK constraint is dropped, insert a value greater than 20 in the st_age column. If the column accepts the specified value, this means the CHECK constraint has been dropped:
    
    
    INSERT INTO staff_bio(st_id, st_name, st_department, st_age)
    VALUES (1, 'Joe', 'HR', 24);

The st_age column accepts a value greater than 20. It proves that the CHECK constraint has been dropped successfully.

 **How to Remove/Drop a NOT NULL CONSTRAINT From a Postgres Table?**

In PostgreSQL, a table column created with a **NOT NULL** constraint accepts only non-null values. This section will teach you how to add or drop a NOT NULL constraint in Postgres using ALTER TABLE command.

 **Step 1: Add NOT NULL Constraint**

ALTER TABLE statement with ALTER COLUMN clause is used in Postgres to add **NOT NULL** constraints to the columns of any existing table:
    
    
    ALTER TABLE staff_bio
    ALTER COLUMN st_name SET NOT NULL;

In the above snippet:

\- The “staff_bio” is a table to be altered/modified.  
\- The “st_name” represents a column to be modified.  
\- The SET clause is used to add a NOT NULL constraint on the st_name column:

The output snippet verifies that the table has been altered successfully. Let’s insert a null value into the st_name column to comprehend the working of the NOT NULL constraint:
    
    
    INSERT INTO staff_bio(st_name)
    VALUES (NULL);

The output proves that a null value can’t be inserted into a column declared with a NOT NULL constraint.

 **Step 2: Drop NOT NULL Constraints**

A NOT NULL constraint can be dropped from a column via the ALTER TABLE statement and the ALTER COLUMN clause:
    
    
    ALTER TABLE staff_bio
    ALTER COLUMN st_name DROP NOT NULL;

In this coding example, the ALTER TABLE and ALTER COLUMN statements are used to remove/drop the NOT NULL constraint from the "st_name" column:

The output snippet verifies that the table has been altered successfully. Inserting a null value into the st_name column will assist you in understanding the working of the NOT NULL constraint:
    
    
    INSERT INTO staff_bio(st_name)
    VALUES (NULL);

A NULL value has been inserted into the st_name column. It proves that the NOT NULL constraint has been dropped successfully.

That’s it from this Postgres blog!

 **Conclusion**

In Postgres, Users must execute the **DROP CONSTRAINT** with the **ALTER TABLE** command to drop any particular constraint from a Postgres table. A **NOT NULL** constraint can be dropped from a column via the **ALTER TABLE** statement and the ALTER COLUMN clause. This blog has presented a thorough overview of how to use **DROP CONSTRAINTS** in PostgreSQL using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-drop-constraint-with-practical-examples/)

---

# Is NVL() Function Same as COALESCE() in PostgreSQL

> PostgreSQL doesn’t support the NVL() function. In Postgres, a built-in function named COALESCE() is used as an alternative to the NVL() function.

ORACLE provides a built-in function named **NVL()** that replaces the NULL entries with a default entry/value. When it comes to PostgreSQL, it doesn’t support the **NVL()** function. However, it offers a **COALESCE()** function that can be used as an alternative to **NVL()** function.

This blog post will explain the following topics/concepts regarding the NVL() function:

  * What is NVL() and How Does it Work?
  * What is the Postgres Equivalent of NVL() Function?
  * Is ORACLE’s NVL() Function the Same as the Postgres COALESCE()?
  * Practical Demonstration



So, let’s begin!

 **What is NVL() and How Does it Work?**

 **NVL()** is an inbuilt function in ORACLE that replaces the NULL values with some other meaningful values in the resultant table of a query. Following will be the syntax for the NVL() function:
    
    
    NVL(val_1, val_2);

It accepts two values as arguments:

\- If the value of the first parameter is non-null, then the NVL() function will retrieve val_1.  
\- If the value of the first parameter “val_1” is equal to “NULL”, then the NVL() function will retrieve the value of the second parameter “val_2”.  
\- So, in the second parameter, users can specify any value as an alternative to the “NULL” value. So that if the value of the first argument becomes “NULL”, the NVL() function retrieves the specified value instead of retrieving the null value.

 **What is the Postgres Equivalent of NVL() Function?**

In PostgreSQL, **the COALESCE()** function is used as an alternative to the NVL **()** function. It takes “n” arguments and retrieves the first non-null value among them.
    
    
    COALESCE (value_1, value_2, …, value_n);

The COALESCE() function stops its execution immediately when it finds a first non-null value.

When working with the table’s data, you can specify the column name as the first argument and any non-null value as the second argument. Consequently, if a null value occurs in a table, then it will be replaced with the specified non-null value:
    
    
    COALESCE(col_name, 0);

In the above syntax, we specified “0” as a second argument; however, you can specify any non-null value of your choice.

 **Is ORACLE’s NVL() Function the Same as the Postgres COALESCE()?**

Between these two functions, there are a couple of notable differences. The below-listed points will help you understand this concept in a better way:

\- ORACLE's **NVL()** function takes only 2 arguments; on the other hand, Postgres’ **COALESCE()** function can accept various arguments.  
\- The **NVL()** function evaluates both arguments and retrieves the result accordingly.  
\- Postgres’ COALESCE() function stops the execution when it finds the first non-null entry.

So, all in all, both **NVL()** and **COALESCE()** functions can be used for the same purpose, i.e., replacing a NULL value with any value other than NULL.

 **Practical Demonstration**

The “products_info” table has already been created in the “example” database. To fetch the table’s data, execute the SELECT query as follows:
    
    
    SELECT * FROM products_info;

In the above snippet, you can see that the second record in the pro_discount column has a null value. Let’s implement the COALESCE() function on the “pro_price” and “pro_discount” columns to find the discounted price of each product:
    
    
    SELECT pro_price - COALESCE(pro_discount, 0) AS discounted_price
    FROM products_info;

In the above snippet:

\- The COALESCE() function is used to find the products’ discounted prices.  
\- The two arguments are passed to the COALESCE() function: the “pro_discount” column and “0” to replace the null values with 0.  
\- The result of the COALESCE() function will be subtracted from the product’s original price.  
\- The discounted price for each product will be displayed in the "discounted_price" column.

The above snippet shows that the COALESCE() function successfully retrieves each product's discounted price.

[Click here](<https://commandprompt.com/education/how-to-get-first-non-null-value-in-postgresql/>) to learn more about the Postgres **COALESCE()** function.

 **Conclusion**

In ORACLE, the NVL() function replaces a null value with any user-specified value other than null. However, Postgres doesn’t support the **NVL()** function. In Postgres, a built-in function named **COALESCE()** is used as an alternative to the NVL **()** function. To do so, specify the expression/table’s column as the first argument and any non-null value as the second argument. Consequently, the null values will be replaced with the specified non-null value. This write-up presented an in-depth overview of is NVL() function same as COALESCE() in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/is-nvl-function-same-as-coalesce-in-postgresql/)

---

# How to Rename Tables in Postgres

> To rename a particular table in PostgreSQL, use the RENAME TO clause in conjunction with the ALTER TABLE statement.

PostgreSQL provides different commands/statements to perform the different operations on the Postgres tables. For instance, the **CREATE TABLE** statement creates a table, the **DROP TABLE** deletes a table, and the **ALTER TABLE** updates an existing table. A Postgres table can be **renamed** using the **ALTER TABLE** command.

This blog post will teach you how to **rename** a **table** in Postgres through practical examples. So, let’s get started!

 **How to Rename a Table in Postgres?**

To rename a particular table in PostgreSQL, use the **RENAME TO** clause in conjunction with the [**ALTER TABLE**](<https://www.commandprompt.com/education/how-to-use-the-alter-table-command-in-postgresql/>) statement:
    
    
    ALTER TABLE tab_name
    RENAME TO new_tab_name;

In the above syntax:

\- tab_name represents a table to be renamed.  
\- new_tab_name represents a new/modified name of the targeted table.

 **IF EXISTS Option**

Postgres experts prefer to use the **IF EXISTS** option with the **ALTER TABLE** statement to avoid the “table does not exist” error:
    
    
    ALTER TABLE IF EXISTS tab_name
    RENAME TO new_tab_name;

The **IF EXISTS** option is used with the **ALTER TABLE** command in the above syntax. Consequently, if a table with the specified name does not exist, a notice will be issued rather than an error.

 **Key Points**

The following points will assist Postgres users in understanding the "ALTER TABLE RENAME TO" statement in a better way:

\- You can’t rename multiple tables in one go. To rename more than one table, you must execute the “ **ALTER TABLE RENAME TO** ” statement several times. In simple terms, each table will be renamed one by one.  
\- Use the **IF EXISTS** option to avoid the “table does not exist” error.  
\- PostgreSQL automatically updates its dependent objects when you rename a table, such as foreign key constraints, views, etc.

For a profound understanding, let’s implement the “ **ALTER TABLE RENAME TO** ” statement practically.

 **Example: How Do I Rename a Table in Postgres?**

Follow the below provided stepwise instructions to rename a table in Postgres:

 **Step 1: Create Table**

First, we will create a sample Postgres table named “employee_data” with three columns: employee_id, employee_name, and employee_age:
    
    
    CREATE TABLE employee_data(
    employee_id INT PRIMARY KEY,
    employee_name TEXT,
    employee_age SMALLINT);

The “CREATE TABLE” message in the output shows that the specified command was executed successfully.

 **Step 2: Verify Table** **Creation**

To verify the table creation, execute the “\dt” command:
    
    
    \dt;

The “employee_data” table has been created successfully.

 **Step 3: Rename Table**

Suppose we want to rename the “employee_data” table to “staff_data”. To do that, execute the “ALTER TABLE RENAME TO” statement as follows:
    
    
    ALTER TABLE employee_data 
    RENAME TO staff_data;

The “ALTER TABLE” message in the output proves that the specified command was executed successfully.

 **Step 4: Verify Table Alteration**

To verify if the table has been renamed or not, execute the “\dt” command:
    
    
    \dt;

The above snippet shows that the “employee_data” has been renamed to “staff_data” successfully.

In this way, you can rename any table in PostgreSQL.

 **Conclusion**

To rename a particular table in PostgreSQL, use the **RENAME TO** clause in conjunction with the **ALTER TABLE** statement. You can’t rename multiple tables simultaneously. To do so, you must execute the “ALTER TABLE RENAME TO” statement several times. PostgreSQL automatically updates its dependent objects when you rename a table, such as foreign key constraints, views, etc. In Postgres, you can use the IF EXISTS option with the ALTER TABLE command to avoid the “table does not exist” error. This blog post demonstrated how the "ALTER TABLE RENAME TO" statement works in Postgres by providing practical examples.

---
[View this page online](https://www.commandprompt.com/education/alter-table-rename-to-in-postgresql/)

---

# How to Create a Superuser in PostgreSQL

> To create a superuser in PostgreSQL, users must use the CREATE ROLE or CREATE USER statement along with the SUPERUSER attribute.

In PostgreSQL, a superuser bypasses all the permission checks except for logging in. Managing a system requires a superuser account, which has broad privileges. To create a superuser in Postgres, use the **CREATE ROLE** or **CREATE USER** statement with the **SUPERUSER** attribute.

This Postgres blog will teach you how to create a superuser or change a user to a superuser via practical examples. So, let’s start!

 **How to Create a Superuser in Postgres?**

In Postgres, the CREATE ROLE or CREATE USER statements are used to create a user/role. The CREATE USER statement is the same as CREATE ROLE, with the exception that the CREATE USER statement has LOGIN privileges by default, whereas CREATE ROLE doesn’t.

 **Syntax**

To create a superuser in Postgres, use the CREATE USER statement followed by the user name and finally specify the SUPERUSER attribute:
    
    
    CREATE USER user_name SUPERUSER;

To create a superuser, you can also use the CREATE ROLE statement as follows:
    
    
    CREATE ROLE user_name SUPERUSER LOGIN PASSWORD 'password';

 **Example 1: How Do I Create a Superuser in Postgres Using CREATE USER Statement?**

Let’s execute the below statement from the SQL Shell to create a superuser in Postgres:
    
    
    CREATE USER example_user SUPERUSER;

The “CREATE ROLE” message in the output indicates that the user has been created. Run the “\du” command to verify the user creation:
    
    
    \du;

From the above snippet, you can authenticate that a superuser named “example_user” has been created successfully.

 **Example 2: How Do I Create a Superuser in Postgres Using CREATE ROLE Statement?**

As mentioned earlier, the CREATE ROLE statement has no login credentials/privileges by default. So you must specify the LOGIN attribute alongside the SUPERUSER attribute to create a superuser using CREATE ROLE statement:
    
    
    CREATE ROLE user_admin SUPERUSER LOGIN PASSWORD '12345';

Let’s verify the user creation via the below command:
    
    
    \du;

A superuser named “user_admin” has been created successfully.

 **How to Change/Alter a Simple User to Superuser in Postgres?**

Use the ALTER USER command with the SUPERUSER attribute to modify a user to superuser in Postgres:
    
    
    ALTER USER user_name WITH SUPERUSER;

In the above snippet:

\- User_name represents a user to be altered.  
\- WITH is an option used to specify the SUPERUSER attribute.

 **Example: How Do I Change/Modify a Simple User to Superuser in Postgres?**

Follow the steps provided below to change a particular user to a superuser in Postgres:

 **Step 1: List Users**

Run the “\du” command to get the list of users:
    
    
    \du;

Suppose we want to change a user named “hr_manager” to a superuser.

 **Step 2: Change User to Superuser**

Run the below-provided command to change the “hr_manager” from user to superuser:
    
    
    ALTER USER hr_manager WITH SUPERUSER;

The “ALTER ROLE” message in the output signifies that the given user has been altered to a superuser.

 **Step 3: Verify User Alteration**

Run the below command to check if the specified user has been changed to the superuser or not:
    
    
    \du;

The output snippet proves that the hr_manager has been changed to a superuser successfully.

That’s it from this Postgres blog!

 **Conclusion**

To create a superuser in Postgres, use the **CREATE ROLE** or **CREATE USER** statement with the **SUPERUSER** attribute. The CREATE USER statement is the same as CREATE ROLE, with the exception that the CREATE USER statement has LOGIN privileges by default, whereas CREATE ROLE doesn’t. Use the ALTER USER command with the SUPERUSER attribute to modify a user to a superuser in Postgres. This blog post has demonstrated how to create a superuser in PostgreSQL using various examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-superuser-in-postgresql/)

---

# SYSDATE Equivalent in PostgreSQL

> In PostgreSQL, there is no SYSDATE function. However, PostgreSQL provides different functions that are equivalent to the SYSDATE function.

In ORACLE, **SYSDATE** is an in-built function that retrieves the system’s(on which the database is running) date and time. When it comes to PostgreSQL, there is no **SYSDATE** function. However, PostgreSQL offers some other functions that perform the same functionality. For instance, **NOW(), CURRENT_DATE, CURRENT_TIMESTAMP,** etc., are used in Postgres for retrieving the system’s current date and time.

This blog post will explain the SYSDATE equivalent functions in Postgres using suitable examples. So, let’s begin.

 **SYSDATE Equivalent in PostgreSQL**

Here are some frequently used Postgres functions that offer the same functionality as ORACLE’s **SYSDATE** function:

\- The **NOW(), CURRENT_TIMESTAMP, TIMEOFDAY(), and CLOCK_TIMESTAMP()** function retrieve the system’s date, time, and timezone.  
\- In Postgres, the **LOCALTIMESTAMP** function provides the system’s date and time without a timezone.  
\- The **LOCALTIME** function returns only time without any timezone.  
\- The **CURRENT_TIME** retrieves the current/system time with the timezone.  
\- The **CURRENT_DATE** function retrieves only the system’s date.

Let’s implement each of the functions mentioned above practically to get more clarity about the SYSDATE equivalent in Postgres.

 **Example 1: How to Get System Date and Time Using NOW() Function in Postgres?**

Execute the NOW() function without passing any argument to it:
    
    
    SELECT NOW();

The output proves that the NOW() function retrieves the system’s date, time, and time zone.

 **Example 2: How to Get System Date and Time Using CURRENT_TIMESTAMP Function in**

 **Postgres?**

Run the CURRENT_TIMESTAMP function with the help of the SELECT statement to get the system’s date and time:
    
    
    SELECT CURRENT_TIMESTAMP;

The above snippet shows that the CURRENT_TIMESTAMP function retrieves the system’s date, time, and time zone.

 **Example 3: How to Get System Date and Time Using TIMEOFDAY() Function in Postgres?**

In Postgres, executing the TIMEOFDAY() function retrieves the system’s date and time:
    
    
    SELECT TIMEOFDAY();

The output snippet authenticates that the TIMEOFDAY() function retrieves the current/system date, day, time, and time zone.

 **Example 4: How to Get System Date and Time Using CLOCK_TIMESTAMP() Function in Postgres?**

The CLOCK_TIMESTAMP() can also be used as the SYSDATE equivalent:
    
    
    SELECT CLOCK_TIMESTAMP();

The output proves that the CLOCK_TIMESTAMP() function returns the system’s date, time, and time zone.

 **Example 5: How to Get System Date and Time Using LOCALTIMESTAMP Function in Postgres?**

The LOCALTIMESTAMP can also be used to get the system’s date and time, but it doesn’t retrieve the time zone:
    
    
    SELECT LOCALTIMESTAMP;

The above snippet shows that the LOCALTIMESTAMP function returns the system’s current date and time.

 **Example 6: How to Get System Time Using LOCALTIME Function in Postgres?**

In Postgres, use the LOCALTIME function to get only the system’s time without date and time zone:
    
    
    SELECT LOCALTIME;

As can be seen from the output, the LOCALTIME function retrieves the system’s time.

 **Example 7: How to Get System Time Using CURRENT_TIME Function in Postgres?**

Executing the below line of code will retrieve the system’s time with the time zone:
    
    
    SELECT CURRENT_TIME;

The above snippet validates the working of the CURRENT_TIME function.

 **Example 8: How to Get System Date Using CURRENT_DATE Function in Postgres?**

To get only the system date without time and time zone, use the CURRENT_DATE function:
    
    
    SELECT CURRENT_DATE;

This is how the CURRENT_DATE function works in Postgres.

 **Conclusion**

In PostgreSQL, there is no SYSDATE function. However, PostgreSQL provides different functions that are equivalent to the SYSDATE function. For instance, the NOW() function, CLOCK_TIMESTAMP function, etc. This blog post has covered various SYSDATE equivalent functions in PostgreSQL using practical examples.

---
[View this page online](https://www.commandprompt.com/education/sysdate-equivalent-in-postgresql/)

---

# How to Uninstall PostgreSQL From Ubuntu

> To uninstall Postgres from your Ubuntu operating system, open the terminal and run the “sudo apt remove postgresql postgresql-contrib” command.

PostgreSQL is among the most popular open-source relational databases that provide a wide range of advantages, including security, stability, extensibility, etc. Users can safely store vast amount of complex data using Postgres. However, when PostgreSQL is no longer needed, you can uninstall it from your Ubuntu operating system.

This blog post will demonstrate how to uninstall Postgres completely from the ubuntu operating system. So, let’s get started!

 **How to Uninstall Postgres From Ubuntu?**

PostgreSQL may need to be uninstalled from a system at some point for various reasons, such as cleaning up the disk space, not needing it anymore, etc. So it's crucial to understand how to uninstall the PostgreSQL database completely(along with its dependent packages) from your system.

Uninstalling Postgres from Ubuntu can be done using various ways. In this write-up, we are going to discuss a couple of them!

> [ ** _Contact us_**](<https://commandprompt.com/contact-us/>) **today for all your Postgres and Open Source consulting and support needs.**

 **Method 1: Using ‘sudo apt remove postgresql’**

This section describes the simplest way of uninstalling Postgres from ubuntu. For that purpose, follow the steps provided below:

 **Step 1: Uninstall Postgres**

To uninstall Postgres from your Ubuntu operating system, open the terminal and run the command below:
    
    
    sudo apt remove postgresql postgresql-contrib

The above snippet demonstrates that Postgres has been removed from Ubuntu.

 **Step 2: Uninstall Dependent Packages**

Some additional(dependent) packages are automatically installed on Ubuntu when you install Postgres. However, when you remove Postgres from ubuntu, these dependent/additional packages are no longer needed. So, to uninstall these dependent packages, the below-mentioned command is used in ubuntu:
    
    
    sudo apt autoremove

Type “y” and hit the “Enter” button to remove Postgres from Ubuntu:

The whole process will take some time to remove Postgres and its dependent packages completely from ubuntu.

 **Method 2: Using ‘purge remove postgresql’**

If the above method is not working for some reasons, then nothing to worry about! We have explained another very convenient method to uninstall Postgres from your Ubuntu operating system.

 **Step 1: List Postgres Packages**

Run the below-provided command to see the list of Postgres packages currently installed on your ubuntu operating system:
    
    
    dpkg -l |grep postgres;

The above snippet shows the list of Postgres packages installed on our machine.

 **Step 2: Uninstall Postgres**

Remove Postgres from your system by running the remove purge command followed by the name of all the packages related to Postgres:
    
    
    sudo apt-get –purge remove postgresql postgresql-14 postgresql-client-common postgresql-common postgresql-contrib

Type “y” and hit the “Enter” button to continue the uninstallation process of Postgres:

The following window will appear during the uninstallation, asking you to remove Postgres directories when the package is purged:

Hit the “Yes” button, and it will take a few minutes to complete the uninstallation.

 **Step 3: Verify Uninstallation**

Let’s execute the below statement one more time to verify the uninstallation of Postgres from ubuntu:
    
    
    dpkg -l | grep postgres

The above snippet proves that postgres has been uninstalled completely from Ubuntu.

That's all from this Postgres guide!

 **Conclusion**

To uninstall Postgres from your Ubuntu operating system, open the terminal and run the “sudo apt remove postgresql postgresql-contrib” command. To uninstall the dependent packages from the ubuntu operating system, use the “sudo apt autoremove” command. Another way of removing postgres from ubuntu is by using the “sudo apt-get –purge remove” command followed by the name of packages to be removed. Through practical demonstration, this Postgres blog has explained how to uninstall PostgreSQL from the ubuntu operating system.

---
[View this page online](https://www.commandprompt.com/education/how-to-uninstall-postgresql-from-ubuntu/)

---

# How to Check Column Types in PostgreSQL

> In PostgreSQL, the SELECT statement, information_schema, \d command, and pg_typeof() function are used to check the data type of a column.

PostgreSQL provides several ways to check the data type of the table’s columns. For example, the **\d** command, **information_schema** , **pg_typeof()** function, and **SELECT** query. To check/find the data type of a particular column, use the information_schema or pg_typeof() function. The “\d” command and SELECT statement retrieve the data types of all columns.

This blog post will teach you how to check the column type of a table in PostgreSQL. In this regard, the below-listed concepts will be explained with practical examples:

  * How to Check Column Type Using pg_typeof() Function?
  * How to Check Column Type Using \d Command?
  * How to Check Column Type Using SELECT Statement?
  * How to Check Column Type Using information_schema?



So, let’s begin!

 **How to Check Column Type Using pg_typeof() Function?**

pg_typeof() is a built-in function in Postgres that can accept a column as an argument and retrieves the data type of the specified column:
    
    
    SELECT pg_typeof(bike_launch_date)
    FROM public.bike_details
    LIMIT 1;

In the above snippet, “LIMIT 1” is used to avoid fluff/repetition. Omitting the LIMIT clause will retrieve the data type as many times as the column values.

The output shows that the “ **bike_launch_date** ” column has a “ **TEXT** ” data type.

 **How to Check Column Type Using \d Command?**

From SQL Shell, run the “\d” command followed by the table name to check the column types of a specific table:
    
    
    \d bike_details;

The “Type” column shows the data type of each column of the targeted table.

 **How to Check Column Type Using SELECT Statement?**

Another very convenient way to retrieve column types is to execute the SELECT query from the pgAdmin:
    
    
    SELECT * FROM bike_details;

The above query will fetch all the data of the bike_details table along with column types:

The above snippet shows the data type of each column.

 **How to Check Column Type Using information_schema?**

The information_schema can be used to check the data type of a single or all columns.

 **How to Check/Find Column Types of a Table?**

The output verifhjjies that the information schema retrieves the column names and trespective data types of the bike_details table.
    
    
    SELECT column_name, data_type
    FROM information_schema.columns
    WHERE table_schema = 'public' AND 
    table_name = 'bike_details';

The output verifies that the information schema retrieves the column names and their respective data types for the bike_details table.

 **How to Check/Find the Type of a Particular Column?**

To check the data type of only a specific column, you must specify the name of that particular column in the WHERE clause:
    
    
    SELECT column_name, data_type
    FROM information_schema.columns
    WHERE table_schema = 'public' AND 
    table_name = 'bike_details' AND
    column_name = 'bike_color';

The above query will retrieve the data type of the column named “bike_color”:

The output proves that this time, the information schema retrieves the data type of only a specific column.

 **Conclusion**

In PostgreSQL, the **SELECT** statement, **information_schema** , **\d** command, and **pg_typeof()** function are used to check the data type of a column. To check/find the data type of a particular column, use the information_schema or pg_typeof() function. The “\d” command and SELECT statement retrieve the data types of all columns. This write-up has demonstrated four different ways to check the data type of the table’s columns.

---
[View this page online](https://www.commandprompt.com/education/how-to-check-column-types-in-postgresql/)

---

# How to Add or Drop NOT NULL Constraints in PostgreSQL

> In PostgreSQL, a table column created with a NOT NULL constraint accepts only non-null values. It can be added when creating a new or altering an existing tabl…

In PostgreSQL, the constraints are used to apply some rules on the table’s column. In Postgres, the **NOT NULL** constraint prevents NULL entries from being inserted into a column. In simple terms, the table columns declared with a **NOT NULL** constraint take only non-null entries. In Postgres, the **NOT NULL** constraint can be added while creating a new or altering/modifying an existing table.

In this article, we will show you how to add or drop a NOT NULL constraint in Postgres. For this purpose, the below-listed concepts will be covered in this write-up:

\- Adding NOT NULL Constraint to New Table  
\- Adding NOT NULL Constraint to Existing Table  
\- Dropping NOT NULL Constraint From a Table

So, let’s begin!

 **Adding NOT NULL Constraint to New Table**

CREATE TABLE statement allows you to add the NOT NULL constraint to any column while table creation. To add a NOT NULL constraint to a table’s column, you need to follow the below syntax:
    
    
    col_name data_type NOT NULL;

The above snippet shows that to add a not-null constraint, write the column name followed by the data type and then specify the NOT NULL constraint.

 **Example: How to Add a NOT NULL Constraint During Table Creation?**

Let’s learn how to create a NOT NULL column during table creation:
    
    
    CREATE TABLE student_information(
    first_name TEXT NOT NULL,
    last_name TEXT,
    age INT NOT NULL
    );

In the above snippet, the NOT NULL constraint is added to the "first_name" and "age" columns:

The “student_information” table has been created with three columns. Execute the “INSERT INTO” statement to insert some records into the student_information table:
    
    
    INSERT INTO student_information(first_name, last_name, age)
    VALUES ('Joe', 'Smith', 23),
    ('Tim', 'Root', 25);

Execute the “SELECT *” command to verify the newly inserted data:
    
    
    SELECT * FROM student_information;

The output indicates that two records have been inserted into the student_information table successfully. Let’s insert one more record into the student_information table:
    
    
    INSERT INTO student_information(first_name, last_name, age)
    VALUES ('Joe', 'Ambrose', NULL);

The output snippet shows that an error occurred when we tried to insert a null value into a column that is declared with a **NOT NULL** constraint.

 **Adding NOT NULL Constraint to Existing Table**

ALTER TABLE statement with ALTER COLUMN clause is used in Postgres to add NOT NULL constraints to the columns of any existing table:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN clm_name SET NOT NULL;

 **Example: How Do I Add NOT NULL Constraint to an Existing Table in Postgres?**

The previous example shows that the “last_name” column of the student_information table is created without a NOT NULL constraint. Hence, you can insert NULL values into that column. For instance, the “last_name” column needs to be altered, i.e., we want to add the NOT NULL constraint on that particular column. For this purpose, we will use the ALTER TABLE command as follows:
    
    
    ALTER TABLE student_information
    ALTER COLUMN last_name SET NOT NULL;

The output snippet verifies that the table has been altered successfully. Now the last_name column would not accept the null values:
    
    
    INSERT INTO student_information(first_name, last_name, age)
    VALUES ('Joe', NULL, 26);

The output proves that a null value can’t be inserted into a column declared with a NOT NULL constraint.

 **Dropping NOT NULL Constraint From a Table**

A NOT NULL constraint can be dropped from a column using the ALTER TABLE command alongside the ALTER COLUMN clause:
    
    
    ALTER TABLE tbl_name
    ALTER COLUMN col_name DROP NOT NULL;

 **Example: How Do I Drop a NOT NULL Constraint From a Postgres Table?**

We will use the ALTER TABLE command to remove the NOT NULL constraint from the "last_name" column:
    
    
    ALTER TABLE student_information
    ALTER COLUMN last_name DROP NOT NULL;

The student_information table has been altered successfully. Now last_name column can accept the null values, as shown in the below snippet:
    
    
    INSERT INTO student_information(first_name, last_name, age)
    VALUES ('Joe', NULL, 26);

Execute the “SELECT *” command to see the table’s data:
    
    
    SELECT * FROM student_information;

The output shows that a NULL value has been inserted into the last_name column. It proves that the NOT NULL constraint has been dropped successfully.

 **Conclusion**

In PostgreSQL, a table column created with a **NOT NULL** constraint accepts only non-null values. The **NOT NULL** constraint can be added when creating a new or altering/modifying an existing table. A NOT NULL constraint can be dropped from a column using the ALTER TABLE command alongside the ALTER COLUMN clause. This Postgres blog has presented a detailed overview of the NOT NULL constraint using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-add-or-drop-not-null-constraints-in-postgresql/)

---

# How to Change Database OWNER in PostgreSQL

> In PostgreSQL, the ALTER DATABASE command is used with the collaboration of the OWNER TO clause to change the database owner.

PostgreSQL provides an **ALTER DATABASE** command that allows us to modify a database. For instance, using ALTER DATABASE command, you can alter the database name, attributes, **owner** , etc. In Postgres, the **ALTER DATABASE** command uses the **OWNER TO** clause to change/modify the database owner.

Using practical examples, this Postgres tutorial will show you how to change/alter the database owner. So, let’s get started!

 **How to Change Database OWNER in Postgres?**

To change/modify the database owner, users must follow the below syntax:
    
    
    ALTER DATABASE db_name
    OWNER TO new_owner_name;

To change the database owner:

\- Specify the ALTER DATABASE command followed by the database name.  
\- After that, specify the new owner's name in the OWNER TO clause.

 **Example: How Do I Change the Database Owner in PostgreSQL?**

In this example, we will guide you step-by-step on how to change the database owner:

 **Step 1: Check Database Owners**

Firstly, execute the “\l” command from SQL Shell to check the list of databases along with their respective owners:
    
    
    \l

The above snippet shows that the owner of the **“emp_db”** is “ **command_prompt** ”.

 **Step 2: Change Database Owner**

Execute the below command to change/modify the database owner from “ **command_prompt** ” to “ **postgres** ”:
    
    
    ALTER DATABASE emp_db
    OWNER TO postgres;

In the above snippet:

\- ALTER DATABASE is used to modify the “emp_db” database.  
\- The OWNER TO clause is used to specify the name of the new database owner, i.e., “postgres”:

The output clarifies that the database owner has been changed successfully.

 **Step 3: Verify Database Owner**

To verify the database owner, we will execute the “\l” command one more time:
    
    
    \l

The output proves that the owner of the “exp_db” database has been changed from “command_prompt” to “postgres”.

 **Note:** Only superusers can change the owner of the Postgres database.

That’s it from this Postgres guide.

 **Conclusion**

PostgreSQL's ALTER DATABASE command is used in conjunction with the OWNER TO clause to change the database owner. For this purpose, specify the ALTER DATABASE command followed by the database name and after that, specify the OWNER TO clause followed by the name of the new owner. This blog post has explained how to change the database owner in PostgreSQL using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-change-database-owner-in-postgresql/)

---

# How to Install PostgreSQL on macOS

> Postgres is becoming increasingly popular every day due to its stunning features. This post explained how to download, install, and use Postgres on macOS.

**PostgreSQL** is a popular open-source relational database that offers many features such as security, object-oriented database features, reliability, etc. It allows the developers to build the applications, administrators to protect data integrity, users to store immense and sophisticated data securely, and so on.

Postgres is becoming increasingly popular every day due to its stunning features. However, it must be installed on your system to access any of its functionality/features. You can install Postgres on any platform, such as Windows, macOS, etc.

This blog post will teach you how to **download** and **install** the Postgres database on **macOS**. So, let's begin.

 **How to Download Postgres on macOS?**

Visit the [official link](<https://www.enterprisedb.com/downloads/postgres-postgresql-downloads>) to download the Postgres database on your mac operating system. Once you click on the provided link, the following window will appear:

You can download the Postgres database for Mac by clicking on the download button:

As seen in the above snippet, the download process has begun, and will take several minutes to complete it.

 **How to Install Postgres on macOS?**

Once the PostgreSQL is downloaded, you can install it on your macOS. To do so, follow the below-mentioned stepwise instructions:

 **Step 1: Launch the Setup Wizard**

Visit the directory where you downloaded the Postgres:

Clicking on the “.dmg” file will lead you to the following window:

Clicking on the desired file will pop up the below window:

Click on the “Open” button to open the downloaded Postgres file.

Provide the password and hit the OK button to launch the Setup wizard:

Hit the “ **Next** ” button to move on to the next step.

 **Step 2: Select Installation Directory**

Specify the installation directory where you want to install the PostgreSQL on your macOS:

Hit the “ **Next** ” button to move on to the next step.

 **Step 3: Select Components to be Installed**

Tick the box to select the components that you want to install, and leave the box unticked if you don’t want to install a specific component:

Hit the “Next” button to continue the installation setup.

 **Step 4: Select Data Directory**

Specify a directory where you want to store your data:

Click on the **“Next”** button to move on to the next step.

 **Step 5: Set Super User Password**

Specify the password for the database superuser and must remember it for later use:

Hit the “Next” button to continue the installation setup.

 **Step 6: Set Port Number**

Specify the port number of your choice, or select the default port number:

Clicking on the “Next” button will lead you to the next step.

 **Step 7: Select Locale**

Select a locale under the “advanced options” window:

Clicking on the “Next” button will move you to the pre-installation summary.

 **Step 8: Review Pre-Installation Summary**

Review the pre-installation summary and hit the next button:

As soon as you click the next button, you will be one step closer to starting the installation.

 **Step 9: Install Postgres on macOS**

Now the setup is ready to start the Postgres installation on your macOS:

Clicking on the Next button will start the Postgres installation:

The installation process will take some time to finish and will finally lead you to the following window:

Hit the “Finish” button to complete the Postgres installation on your macOS.

 **Note:** Once the installation is done, you can perform any Postgres operation using pgAdmin, or command line tools. For instance, the following steps will help you determine the Postgres version via pgAdmin:

 **Step 10: Launch pgAdmin**

Open the “pgAdmin 4” from the launch pad:

Provide the superuser password that you specify during the installation process:

Hit the “OK” button to log in to the pgAdmin.

 **Step 11: Check Postgres Version**

Now, expand the “Servers” tree > Left-click on “PostgreSQL” and then click on the “Properties” tab to check the Postgres Version:

The above snippet shows that “ **PostgreSQL 15.1** ” is running on your macOS.

 **Conclusion**

To install Postgres on macOS, firstly download Postgres for macOS> launch the setup wizard > specify installation directory> select components to be installed > specify data directory, superuser password, port number, and locale> review the pre-installation summary and hit the next button to start Postgres installation. The entire installation process will take several minutes to install the Postgres database on your macOS. This blog post explained how to download, install, and use the Postgres database via practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-postgresql-on-macos/)

---

# How to Install PostgreSQL Database on Ubuntu

> To install PostgreSQL on your Ubuntu operating system, run the “sudo apt install postgresql postgresql -contrib” command.

One of the most popular open-source relational databases is PostgreSQL which offers numerous features such as security, reliability, extensibility, etc. Postgres assists the developers in building the applications, administrators in protecting data integrity, builts fault tolerance environments, etc. It allows users to store immense and sophisticated data securely. Postgres is becoming increasingly popular due to its enormous features. However, it must be installed on your system in order to access any of its functionality/features.

This blog will teach you how to install, use and uninstall the Postgres database from Ubuntu. So, let's begin.

 **How to Install PostgreSQL Database on Ubuntu?**

Firstly, open the terminal and perform the following steps to install Postgres on Ubuntu.

 **Step1: Update Packages**

Let’s update the system packages via the below command:
    
    
    sudo apt update

The above snippet shows that the system packages are being updated.

 **Step 2: Install Postgres**

To start Postgres installation on ubuntu, run the below “sudo apt install” command:
    
    
    sudo apt install postgresql postgresql-contrib

Type “Y” and hit the “Enter” button to continue the installation:

It will take some time to complete the installation process:

Finally, Postgres has been installed on our system successfully.

 **Step 3: Start the PostgreSQL Services**

Once Postgres is installed on your ubuntu operating system, execute the below command to start the Postgres Services:
    
    
    sudo systemctl start postgresql.service

Specify the password and hit the “enter” button to start the Postgres services.

 **Getting Started With Postgres**

Installing Postgres will automatically install the SQL Shell on your system. So, you can perform any Postgres task via SQL Shell.

 **Step 1: Switch to Postgres Account**

Firstly, you need to switch to the Postgres account. To do so, run the below command:
    
    
    sudo -i -u postgres

Specify the password and hit the “Enter” button to switch the account.

 **Step 2: Switch to SQL Shell**

To use any Postgres query/command, you need to switch to SQL Shell(psql).
    
    
    psql

 **Step 3: List Databases**

Now, execute the “\l” command to see the list of available databases:
    
    
    \l

 **Step 4: Create New Database**

Let’s create a new database named “example_db” using the following command:
    
    
    CREATE DATABASE example_db;

The output indicates that a database named “example_db” has been created.

 **Step 5: Verify Database Creation**

You can verify the database’s creation through the following command:
    
    
    \l

The database list proves that the database “example_db” has been created.

 **Step 6: Access New Database**

To establish a connection with the newly created database, you can utilize the “\c” command as follows:
    
    
    \c example_db

The output verifies that the connection has been established with the new database successfully.

This way, you can install Postgres and perform all the Postgres tasks on ubuntu.

 **How to Uninstall Postgres From Ubuntu?**

Uninstalling Postgres from Ubuntu can be done using various ways. We are going to discuss one of them in this write-up.

 **Step 1: Uninstall Postgres**

To uninstall Postgres from your Ubuntu operating system, open the terminal and run the command below:
    
    
    sudo apt remove postgresql postgresql-contrib

The above snippet demonstrates that Postgres has been removed from Ubuntu.

 **Step 2: Uninstall Dependent Packages**

Some additional(dependent) packages are automatically installed on Ubuntu when you install Postgres. However, when you remove Postgres from ubuntu, these dependent/additional packages are no longer needed. So, to uninstall these dependent packages, the below-mentioned command is used in ubuntu:
    
    
    sudo apt autoremove

Type “y” and hit the “Enter” button to remove Postgres from Ubuntu:

The whole process will take some time to remove Postgres and its dependent packages completely from ubuntu.

That's all from this Postgres guide!

 **Conclusion**

To install Postgres on your Ubuntu operating system, run the “sudo apt install postgresql postgresql -contrib” command. Installing Postgres will automatically install the SQL Shell on your system. So, use the SQL Shell to perform any Postgres task. This blog post explained how to install, use, and uninstall the Postgres database on Ubuntu via practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/how-to-install-postgresql-database-on-ubuntu/)

---

# psycopg: PostgreSQL Python Connector

> psycopg is a Postgres Python connector that allows Python programs to access Postgres databases. It is used to perform various operations on Postgres database …

Numerous Postgres database connectors/adapters are available for Python, such as **psycopg** , py-postgresql, PyGreSQL, etc. Among them, the most frequently used connector/adapter is **psycopg**. But why is it so? Well! One reason is that it implements the entire Python DB API 2.0 specifications, along with thread safety. Moreover, it offers various features, including security, efficiency, allowing users to perform heavily multithreaded operations, etc.

This write-up will present a detailed overview of the psycopg: one of the most frequently used Postgres Python connectors. So, let’s begin.

 **Introduction to psycopg: PostgreSQL Python Connector**

psycopg is a Postgres Python connector/adapter/driver that allows Python programs to access Postgres databases. It is the most widely used connector to perform various operations on the Postgres database via python programming. It offers numerous features, some of which are listed below:

\- psycopg is fast and secure.  
\- It implements the entire Python DB API 2.0 specifications.  
\- The current psycopg 2 supports Python versions from 3.6 to 3.11.  
\- The current psycopg 2 supports Postgres versions 7.4 to 15.  
\- It offers thread safety, which means multiple threads can share the one/same connection.  
\- It can send/receive asynchronous notifications.  
\- Many Python objects can be adapted to database types, including lists-arrays, tuples-records, and dictionaries-hstores.  
\- Python objects can be adapted to and from Postgres json and jsonb data types via Pycopg2.  
\- It is extensible with new adapters for converting a Python object to SQL syntax.  
\- It supports COPY commands, two-phase commit commands, and large objects.  
\- It provides a nice interface to work with the Server-side cursors.  
\- Asynchronous communication.

psycopg provides a connect() function that helps us connect with the Postgres database. To access any feature of psycopg2, users must install psycopg2 on their operating system. You can install psycopg2 on any platform, such as Windows, Linux, or macOS. This blog post will teach you how to install psycopg2 on the Windows operating system.

 **How to Install psycopg on Windows?**

Following are the prerequisites to install psycopg on Windows:

\- Administrator/root privileges are required before installation.  
\- Enable “python.exe” from the Windows “PATH” settings.

 **Step 1: Open CMD**

Go to the Windows search bar and search for "Command Prompt":

Click on the “CMD” app to launch it.

 **Step 2: Install psycopg2**

Let’s run the following command from the CMD to install the “psycopg2” module:
    
    
    pip install psycopg2

The “psycopg2” module has been installed successfully.

 **Step 3: Connect to Postgre Database Via Python**

To establish a connection with the Postgres database via Python, firstly, the “psycopg2” module must be imported at the start of the project/program. After that, utilize the connect() function of the “psycopg2” module to establish a connection with Postgres:
    
    
    con = psycopg2.connect(
    database="example",
    user="postgres",
    password="cp12345",
    host="localhost",
    port= '5432'
    )

In the above snippet, we utilized the following connection parameters:

\- **database** : specify the database name to which you want to connect. For example, “example”.  
\- **user:** specify a user for authentication, e.g., “postgres”.  
\- **password:** provide the password of the respective database for establishing a connection.  
\- **host:** specify the localhost/IP address.  
\- **port:** provide the port number, or use the default port number, i.e., “5432”.

This way, you can connect with the Postgres database using Python programming.

 **Step 4: Perform Postgres Operations**

To perform any Postgres operations, users must create a cursor object. After that, utilize the execute() function to perform any Postgres operation:
    
    
    cursor_obj = con.cursor()
    cursor_obj.execute("CREATE TABLE cp_tbl(article_id SERIAL PRIMARY KEY, article_name TEXT")
    print("Table Created Successfully!!")
    con.commit()
    con.close()

In the above snippet:

\- Firstly, a cursor object is created using the cursor() method.  
\- Next, the execute() function is used to create a Postgres table using Python.  
\- A message is printed on the output terminal via the print() function.  
\- Next, the commit() function is used to save the transaction changes/modifications.  
\- Lastly, the cursor is closed using the close() function.

The output clarifies that a table named “cp_tbl” has been created successfully. Now, we will execute the Postgres **INSERT** query using the execute() function to insert a row into the “cp_tbl” table via python:
    
    
    cursor_obj.execute("INSERT INTO cp_tbl (article_id, article_name) \
    VALUES (1, 'How to Use IN Operator in Postgres');")
    print("Record Inserted Successfully!!")
    con.commit()
    con.close()

One record has been inserted into the cp_tbl table. Let’s fetch the “ **cp_tbl** ” data via the SELECT query:
    
    
    cursor_obj = con.cursor()
    cursor_obj.execute("SELECT * FROM cp_tbl")
    result = cursor_obj.fetchall()
    print("Resultant Data:", "\n", result)
    con.commit()
    con.close()

In the above code snippet, we utilized the fetchall() method of the cursor class to fetch all the records retrieved by the SELECT query:

This way, you can perform any Postgres operation using the psycopg adapter.

 **Conclusion**

psycopg is a Postgres Python connector/adapter/driver that allows Python programs to access Postgres databases. It is the most widely used connector to perform various operations on the Postgres database via python programming. It offers various features, including security, efficiency, allowing users to perform heavily multithreaded operations, etc. To access any feature of psycopg2, users must install psycopg2 on their operating system. After installing psycopg, users can utilize the connect() function to make a connection with the Postgres database. This blog post presented an in-depth overview of the psycopg connector.

---
[View this page online](https://www.commandprompt.com/education/psycopg-postgresql-python-connector/)

---

# What Does ILIKE Operator Do in PostgreSQL?

> In PostgreSQL, the “ILIKE” operator is used to fetch/query the data based on pattern matching. The ILIKE operator queries the data case-insensitively.

PostgreSQL offers an “ **ILIKE** ” operator that is used to fetch/query the data based on pattern matching. The “ **ILIKE** ” operator works the same as the “[LIKE](<https://commandprompt.com/education/how-to-use-like-operator-in-postgresql/>)” operator; the only difference is that the ILIKE operator queries the data irrespective of the letter case.

This Postgres blog will give you a detailed knowledge of the ILIKE operator with practical examples. So, let’s begin!

 **What Does ILIKE Operator Do in Postgres?**

The **ILIKE** operator in Postgres performs case-insensitive pattern matching. For this purpose, Postgres offers a couple of wildcards denoted by a percent sign **“%”** and an underscore **“_”** :  
\- The percent wildcard **“%”** is used to match the sequences of characters.  
\- The underscore wildcard **“_”** is used to match only a single character.  
\- Both these wildcards can be used together to maximize functionality.

 **Syntax**

The below syntax will be used to perform string matching using the **ILIKE** operator:
    
    
    SELECT FROM tbl_name
    WHERE col_name ILIKE pattern;

In place of a pattern, you can specify any pattern of your choice using wildcards.

 **Example 1: How to Perform String Matching in Postgres Using Percent Wild Card?**

Firstly, we will utilize the SELECT statement to fetch the details about the “bike_details” table:
    
    
    SELECT * FROM bike_detials;

From the bike_details table, we need to retrieve the bikes whose color starts with "bl" letter regardless of the letter case. To do so, we will utilize the **ILIKE** operator with the “%” wildcard as follows:
    
    
    SELECT bike_model, bike_color
    FROM bike_details
    WHERE bike_color ILIKE 'bl%';

The output snippet proves that the “ILIKE” operator fetches the data irrespective of the letter case.

 **Example 2: How to Perform String Matching in Postgres Using Underscore Wildcard?**

Suppose we need to check the bike number that starts with any letter/number, but the second letter must be a “y”:
    
    
    SELECT bike_model, bike_number
    FROM bike_details
    WHERE bike_number ILIKE '_y%';

Here, in the above example:

\- The underscore wildcard shows that the first letter can be anything, i.e., a number, character, etc.  
\- The second letter must be a “y”(irrespective of the case).  
\- The percent wildcard at the end shows that the “y” letter can be followed by any number/letter.

The ILIKE operator fetched all those bike_numbers that contain a “y” letter at the second position.

Alright, folks! That’s all from this Postgres guide!

 **Conclusion**

In PostgreSQL, the “ **ILIKE** ” operator is used to fetch/query the data based on pattern matching. The “ **ILIKE** ” operator works exactly the same as the “ **LIKE** ” operator; the only difference is that the ILIKE operator queries the data case-insensitively. In Postgres, the percent and underscore wildcards are used to create a pattern based on which the ILIKE operator queries the data from a string. This blog post has explained the working of the Postgres ILIKE operator via practical examples

---
[View this page online](https://www.commandprompt.com/education/what-does-ilike-operator-do-in-postgresql/)

---

# How to Delete/Drop a User in PostgreSQL

> In Postgres, the DROP USER statement is used to drop a single user or multiple users simultaneously. Use IF EXISTS option to check the existence of a user.

When a Postgres user is no longer needed, you can delete/drop it via the **DROP USER** command. In Postgres, the **DROP USER** command allows us to delete or drop a single user or multiple users simultaneously. The **DROP USER** command can accept the IF EXISTS option to check the user’s existence before performing any action.

This blog post will present a step-by-step guide on deleting a user in Postgres via practical examples. This post will cover the below-listed aspects of the **DROP USER** command in Postgres:

  * How to Delete/Drop a Single User in Postgres?
  * How to Delete/Drop Multiple Users in Postgres?



So, let’s start!

 **How to Delete/Drop a Single User in Postgres?**

To drop a single user in Postgres, use the DROP USER command as follows:
    
    
    DROP USER [IF EXISTS] user_name;

In the above syntax:

\- DROP USER is a command used to delete a Postgres user.  
\- IF EXISTS is an option that checks the existence of a user.  
\- User_name is a user to be deleted.

 **Example 1: How Do I Delete a User in Postgres?**

Let’s learn how to delete a user in Postgres via the below-given stepwise instructions:

 **Step 1: Launch SQL Shell**

Firstly, open the SQL Shell(psql), and provide the login details, such as user name, superuser password, etc.

The above snippet shows that we have successfully logged into Postgres.

 **Step 2: List Users**

To get the list of Postgres users, execute the below-mentioned command:
    
    
    \du

The output shows the list of all Postgres users.

 **Step 3: DROP USER**

Suppose a user named “manager” is no longer needed. So to delete the manager, we will run the **DROP USER** command as follows:
    
    
    DROP USER IF EXISTS manager;

A user named “manager” has been dropped successfully.

 **Step 4: Verify User Deletion**

Let’s execute the \du command one more time to verify if the specified user has been dropped or not:
    
    
    \du

The above snippet proves that the targeted user has been deleted successfully.

 **Step 5: Deleting Non-Existing User**

If you try to delete a user that doesn't exist will result in an error. However, instead of throwing an error, a notice will be displayed if you specify the IF EXISTS option with the DROP USER statement:
    
    
    DROP USER IF EXISTS manager;

In the above statement, we tried to delete a user named manager:

The output proves that Postgres shows a notice instead of throwing an error.

 **How to Delete/Drop Multiple Users in Postgres?**

Follow the comma-separated syntax for the DROP USER command to delete multiple users in one go:
    
    
    DROP USER IF EXISTS user_1, user_2, …, user_n;

 **Example: How Do I Delete Multiple Users in Postgres?**

Let’s learn how to delete multiple users in Postgres via the below-given stepwise instructions:

 **Step 1: List Users**

You can get the list of Postgres users by executing the following command:
    
    
    \du

The output shows the list of all Postgres users.

 **Step 2: DROP Multiple USERS**

Suppose we need to delete three users: “std_role”, “teach_role”, and “teacher_role”. To do so, we will run the **DROP USER** command as follows:
    
    
    DROP USER IF EXISTS std_role, teach_role, teacher_role;

The “DROP ROLE” message in the output proves that the selected users have been deleted successfully.

 **Step 3: Verify User Deletion**

Let’s execute the \du command one more time to verify if the targeted users have been deleted or not:
    
    
    \du

The output snippet authenticates that the selected users have been deleted successfully.

That’s it from this Postgres tutorial!

 **Conclusion**

In Postgres, the **DROP USER** command is used to delete or drop a single user or multiple users simultaneously. To delete a single user, specify the DROP USER statement followed by the user name to be deleted. To delete multiple users simultaneously, use the comma-separated syntax for the DROP USER command. The **DROP USER** command can accept the IF EXISTS option to check the user’s existence before performing any action. This blog post has explained how to delete single or multiple users in Postgres through practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-deletedrop-a-user-in-postgresql/)

---

# How to Change the Password of a User in PostgreSQL

> Use the ALTER USER or ALTER ROLE statement to change/modify the password of a Postgres user. You can use the VALID UNTIL clause to specify the password’s expir…

Postgres' **ALTER USER** and **ALTER ROLE** statements are used to change/modify a user's password. To change the user password in Postgres, all you need to do is, use the **ALTER USER** or **ALTER ROLE** command and provide the new password within the single quotations.

This blog post will present detailed knowledge about how to change the user password in Postgres. So, let’s begin!

 **How to Change/Modify the User’s Password in Postgres?**

Use one of the below-given syntaxes to change the password of the Postgres user.

 **Syntax 1:**

Use the ALTER ROLE statement with PASSWORD attribute and specify the new password within the single quotation:
    
    
    ALTER ROLE user_name 
    WITH PASSWORD 'modified_password'
    VALID UNTIL ‘expiry_date_time’;

 **Syntax 2:**

Use the ALTER USER statement with PASSWORD attribute and specify the modified password within the single quotation:
    
    
    ALTER USER user_name
    WITH PASSWORD 'modified_password'
    VALID UNTIL 'expiry_date_time';

In the above-given syntaxes:

\- ALTER ROLE and ALTER USER are the Postgres statements that modify the role/user.  
\- User_name is a user to be modified.  
\- Specify the modified password of your choice in place of the modified_password.  
\- VALID UNTIL is optional and used to specify the password validation until a specific date and time.

 **Note:** ALTER ROLE and ALTER USER statements are used to alter the attributes of a user's account. Only superusers can change the privileges and passwords of the user’s account.

 **Example 1: How to Change User Password Using ALTER USER command?**

To get the list of Postgres users, firstly, execute the below-mentioned command:
    
    
    \du

Suppose we need to change the password of a user named “command_prompt”. To do so, we will execute the ALTER USER Command as follows:
    
    
    ALTER USER command_prompt
    WITH PASSWORD 'cp@54321'
    VALID UNTIL '2022-12-31 11:59:59';

In the above snippet, we utilized the ALTER USER command to change the password for the “command_prompt” user. The specified password will be valid until “2022-12-31 11:59:59”:

The ALTER ROLE message in the output proves that the password has been changed successfully. Let’s run the “\du” command followed by the user name to see the user details:
    
    
    \du command_prompt

The output proves that the password has been changed successfully, and it will be valid until the specified date and time.

 **Example 2: How to Change User Password Using ALTER ROLE command?**

Let’s change the Password of the “command_prompt” user one more time using the ALTER ROLE statement:
    
    
    ALTER ROLE command_prompt
    WITH PASSWORD 'cp12345678'
    VALID UNTIL 'infinity';

In the above statement,

\- We changed the user’s password via the ALTER ROLE statement.  
\- Next, we specified “infinity” in the VALID UNTIL clause, so the specified password will never expire:

From the output, it can be seen that the password has been changed successfully. Let’s explore the user’s details via the below command:
    
    
    \du command_prompt

If you are a superuser in PostgreSQL, you can change a user's password this way.

 **Conclusion**

Use the **ALTER USER** or **ALTER ROLE** statement to change/modify the password of a Postgres user. To do so, use the **ALTER USER** or **ALTER ROLE** command and provide the new/modified password within the single quotations. Additionally, you can use the VALID UNTIL clause to specify the password’s expiry date and time. In such a case, the password will be valid until the defined date/time. This blog post has explained how to change the user’s password in PostgreSQL via the ALTER ROLE and ALTER USER statements.

---
[View this page online](https://www.commandprompt.com/education/how-to-change-the-password-of-a-user-in-postgresql/)

---

# How to Add or Drop Primary Key Constraints in PostgreSQL

> Use the ADD CONSTRAINT or DROP CONSTRAINT clause with the ALTER TABLE command to add or drop a primary key constraint from a Postgres table.

In Postgres, Primary keys are used to uniquely identify a table’s record. Users can add/set a primary key at the time of table creation or to an existing table. In Postgres, tables can be created with a primary key constraint using the CREATE TABLE command or altered using the ALTER TABLE command. For dropping a primary key constraint, the DROP CONSTRAINT is used with the ALTER TABLE command.

This Postgres blog will cover the below-listed aspects of the Primary key constraint:

\- Adding PRIMARY KEY While Table Creation  
\- Adding PRIMARY KEY Using ALTER TABLE Command  
\- Dropping PRIMARY KEY CONSTRAINT

So, let's begin!

 **Adding PRIMARY KEY While Table Creation**

Let’s add a primary constraint during table creation. To do so, we will add a primary key constraint in the staff_information table using the CREATE TABLE command. We will create a sample table with the following columns: st_id, st_name, st_department, and st_age:
    
    
    CREATE TABLE staff_information(
    st_id INT CONSTRAINT st_id_pk PRIMARY KEY,
    st_name TEXT,
    st_department TEXT,
    st_age SMALLINT
    );

The “ **CREATE TABLE** ” message in the output window indicates that the “staff_information” table has been created. You can verify the table’s creation via the below command:
    
    
    SELECT * FROM staff_information;

From the table’s structure, you can clearly observe that a primary key constraint has been added to the staff_information table.

 **Adding PRIMARY KEY Using ALTER TABLE Command**

"ALTER TABLE" lets you add primary key constraints to existing Postgres tables. For better understanding, firstly, we will create a table without any constraint:
    
    
    CREATE TABLE staff_bio(
    st_id INT,
    st_name TEXT,
    st_department TEXT,
    st_age SMALLINT
    );

Executing the SELECT command will show you the structure of the staff_bio table:
    
    
    SELECT * FROM staff_bio;

The output snippet proves that the “staff_bio” table has no primary key constraint. Let’s run the ALTER TABLE command to add a PRIMARY KEY constraint in the staff_bio table:
    
    
    ALTER TABLE staff_bio
    ADD CONSTRAINT st_id_pk 
    PRIMARY KEY (st_id);

In the above snippet,

-ALTER TABLE is a command used to modify the staff_bio table.  
-ADD CONSTRAINT adds a primary key constraint in Postgres, such as “st_id_pk”.

The “ALTER TABLE” message in the output window proves that the “staff_bio” table has been modified successfully. Let’s validate the table’s structure via the following command:
    
    
    SELECT * FROM staff_bio;

The output shows that a primary key has been added to an existing table: st_id column.

 **Dropping PRIMARY KEY CONSTRAINT**

To drop a primary key constraint, use the ALTER TABLE command with DROP CONSTRAINT as follows:
    
    
    ALTER TABLE staff_bio
    DROP CONSTRAINT st_id_pk

Let’s verify the constraint deletion via the below command:
    
    
    SELECT * FROM staff_bio;

The output clarifies that the primary key constraint has been removed successfully.

This way, a primary key constraint can be added or deleted from a table in Postgres.

 **Conclusion**

Tables can be created with a primary key constraint using the CREATE TABLE statement. You can add the primary key to an existing table using the Postgres ALTER TABLE command. For dropping a primary key constraint, the DROP CONSTRAINT is used with the ALTER TABLE command. This blog post has explained how to add or drop a primary key constraint in Postgres via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-add-or-drop-primary-key-constraints-in-postgresql/)

---

# How Do I Backup a PostgreSQL Database

> Postgres offers a couple of standard tools/utilities, such as pg_dump and pg_dumpall, to back up a single or all databases.

It is essential to **back up** your PostgreSQL database regularly, regardless of how large or small it is. For this purpose, Postgres offers a couple of standard tools, such as **pg_dump** and **pg_dumpall**. Using these utilities, users can **back up** single or all databases.

This post will guide you on how to back up a PostgreSQL database via pg_dump and pg_dumpall tools. This blog post will cover the below-listed learning outcomes:

  * What is pg_dump, and How to Use it in Postgres?
  * How Do I Back up a Single Database?
  * What is pg_dumpall, and How to Use it in Postgres?
  * How to Back up All Databases in Postgres?



So, let's start!

 **What is pg_dump, and How to Use it in Postgres?**

pg_dump is a standard tool/utility in Postgres that assists users in backing up the content of a database into a single file. Follow the below syntax to dump a database into a plain text file:
    
    
    pg_dump db_name > file_name.sql

 **How Do I Back up a Single Database?**

Step-by-step guidelines for backing up a database are listed in this section:

 **Step1: Access Bin Directory**

Firstly, open the command prompt and run the following command to navigate to the Postgres bin folder:
    
    
    cd C:\Program Files\PostgreSQL\14\bin

Hit the “ **Enter** ” button to access the desired directory/path:

The above snippet indicates the successful entry into the “bin” directory.

 **Step2: Backup the Database**

Now, execute the below-mentioned command to back up the desired database, in our case, its **“example”** database:
    
    
    pg_dump -U postgres -F t example > c:\backupFiles\example.tar

In the command mentioned above:

  * pg_dump is a command used to back up a particular database.
  * U specifies a user; in our case, the user is “postgres”.
  * F option is used to specify the file format in which the database will be backed up.
  * t represents that the desired database will be backed up in “tar” format. However, you can specify any other format of your choice, such as “custom format”, “directory format”, or plain text.
  * “example” is a database to be backed up.
  * “backupFiles” is a directory in which the desired database will be backed up:



Executing the above command will ask for a password, provide the password, and hit the “Enter” button. As a result, the desired database will be restored/backed up.

 **Step3: Check/Verify the Backed Up Database**

Now access the directory where you backed up the database; in our case, it’s “C:\backupFiles”:

The above snippet shows that the desired database has been successfully backed up in the destination folder.

 **What is pg_dumpall, and How to Use it in Postgres?**

The pg_dump tool allows you to back up all databases one by one; however, PostgreSQL offers a tool called pg_dumpall that allows you to back up all databases simultaneously:
    
    
    pg_dumpall user_name> file_name.format

 **Note:** Database experts prefer backing up databases sequentially(using pg_dump) instead of simultaneously(using pg_dumpall). This is because the pg_dumpall toll takes more time as compared to pg_dump.

 **How to Back up All Databases in Postgres?**

This section presents step-by-step guidelines to backup all the databases using pg_dumpall:

 **Step1: Access Bin Directory**

First, open the CMD and run the below command to navigate to the Postgres bin folder:
    
    
    cd C:\Program Files\PostgreSQL\14\bin

Press the “ **Enter** ” button to reach the specified path:

The above snippet indicates the successful entry into the “bin” directory.

 **Step2: Back Up All the Database**

Now utilize the pg_dumpall utility to back up all the databases:
    
    
    pg_dumpall -U postgres > c:\backupFiles\allFiles.tar

Provide the password for each database and hit the enter button. Consequently, all the databases will be backed up in the destination directory.

 **Conclusion**

Postgres offers a couple of standard tools/utilities, such as **pg_dump** and **pg_dumpall,** to back up a single or all databases. Using these utilities, users can back a database into any format of their choice, such as “custom format”, “tar format”, “directory format”, or “plain text SQL format”. This blog post presented an in-depth overview of backing up a Postgres database using pg_dump and pg_dumpall utilities.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-backup-a-postgresql-database/)

---

# How to Connect To PostgreSQL Database Server Using Python

> Install “psycopg2” module, import it into your python program, and use the connect() function of “psycopg2” module to connect to the Postgres database server v…

PostgreSQL is an advanced and open-source relational database that assists users in storing and managing data efficiently. Over the past few years, it has been noticed that developers prefer to use the PostgreSQL database with all the popular languages, including Java, Python, C++, etc.

You will find this write-up useful if you are a Python user looking to connect to a PostgreSQL database server using Python. So, let’s start!

 **How to Connect to Postgres Database Using Python?**

To establish a connection with the Postgres database via python, we will utilize one of the most frequently used adapters named “psycopg2”. The psycopg2 is a Postgres database adapter/driver that is used to perform various operations on the Postgres database via python programming.

The psycopg2 module offers a connect() function that assists us in connecting with the suppliers' databases.

Users must follow the below listed stepwise guidelines for connecting to a Postgres database through python programming:

 **Step 1: Open Command Prompt**

Firstly, search for the CMD from the Windows search bar:

Clicking on the “CMD” app will open the command prompt.

 **Step 2: Install psycopg2**

Let’s execute the below command to install the “psycopg2” module from the CMD:
    
    
    pip install psycopg2

From the above snippet, you can clearly observe that the “psycopg2” module has been installed successfully.

 **Step 3: Connect to Postgre Database Via Python**

First, you must import the “psycopg2” at the start of your project/program. After that, utilize the connect() function of the “psycopg2” module to establish a connection with Postgres:
    
    
    con = psycopg2.connect(
    database="example",
    user="postgres",
    password="cp12345",
    host="localhost",
    port= '5432'
    )

In the above snippet, we utilized the following connection parameters:

\- **database** : specify the database name to which you want to connect.  
\- **user:** specify a user for authentication.  
\- **password:** specify the password to connect to the respective database.  
\- **host:** specify the localhost or IP address.  
\- **port:** specify the port number, “5432” is the default port number.

The error-free output shows that the connection has been established successfully.

 **Step 4: Create Cursor Object**

The cursor() method assists us in executing the Postgres commands from Python. To do so, firstly, create a cursor object:
    
    
    cursor_obj = con.cursor()

Once the cursor object is created, you can utilize any function of the Cursor class/object.

 **Step 5: Execute Postgres Query**

To execute any Postgres query, command, function, etc., we will utilize the execute() function of the cursor class:
    
    
    cursor_obj.execute("SELECT * FROM bike_details")

In the above snippet, we utilized the execute() function. Within the execute() function, we utilized the SELECT query to fetch the data of the bike_details table:

The output shows that the execute() function successfully executed the SELECT query.

 **Step 6: Fetch All Records**

To fetch all the records retrieved by the SELECT query, we will utilize the fetchall() method of the cursor class as follows:
    
    
    result = cursor_obj.fetchall()

In the above code snippet, we fetched all the rows of the bike_details table and stored the result set into the “result” variable.

 **Step 7: Print Result**

Finally, we will utilize the print() function to print the result set retrieved by the SELECT statement:

This is how you can connect to the Postgres database and perform various operations using Python programming.

 **Conclusion**

In order to connect to the Postgres database server via python, an adapter/module named “psycopg2”, is used. To do so, firstly, install the “psycopg2” module, import it into your python program, and utilize the connect() function of the “psycopg2” module to establish a connection with Postgres. Through practical demonstration, this blog post explained how to connect to the Postgres database using Python and execute Postgres commands from Python.

---
[View this page online](https://www.commandprompt.com/education/how-to-connect-to-postgresql-database-server-using-python/)

---

# PostgreSQL ARRAY_APPEND() Function With Examples

> Postgres provides an ARRAY_APPEND() function that is used to append/add elements at the end of the array. It accepts two parameters: an array and an element to…

PostgreSQL offers various built-in functions to deal with the arrays. For instance, the **ARRAY_LENGTH()** function retrieves the array’s length, the **ARRAY_REPLACE()** function replaces an array element with some other element, the **ARRAY_REMOVE()** function removes the array elements, and so on.

Similarly, Postgres provides an **ARRAY_APPEND()** function that is used to append/add elements at the end of the array.

This blog post will present an in-depth overview of the **ARRAY_APPEND()** function via practical examples. So, let’s get started.

 **How to Use ARRAY_APPEND() Function in Postgres?**

In PostgreSQL, the **ARRAY_APPEND()** function accepts two parameters an array and an element to be appended:
    
    
    ARRAY_APPEND(arr, arr_element);

In the above syntax, arr is an array to be modified, while arr_element represents an element to be appended at the end of the selected array.

 **Example 1: How Does ARRAY_APPEND() Function Work in Postgres?**

Use the below piece of code to append/add an element at the end of the array:
    
    
    SELECT ARRAY_APPEND(ARRAY['John','Mike', 'AMBROSE'], 'SETH');

The output proves that a new element has been appended at the end of the given array.

 **How to Append Elements in an Array Using ARRAY_APPEND() Function?**

Following is the syntax for appending elements to an array-type column:
    
    
    UPDATE tbl_name 
    SET col_name = ARRAY_APPEND(col_name, arr_element) 
    WHERE condition;

Here, the UPDATE statement and SET clause are used with the ARRAY_APPEND() function to append elements to an existing array-type column.

 **Example: How to Use ARRAY_APPEND() Function on Table’s Data?**

Let’s create a sample table named staff_data with four columns: st_id, st_name, st_phone, st_email:
    
    
    CREATE TABLE staff_data(
    st_id INT PRIMARY KEY,
    st_name TEXT,
    st_phone INT[],
    st_email VARCHAR[]
    );

The table named staff_data has been created successfully. Let’s insert the below-listed records into the “staff_data” table:
    
    
    INSERT INTO staff_data(st_id, st_name, st_phone, st_email)
    VALUES
    (1, 'Mike', '{1234567811, 1112223312}', '{"mike123@gmail.com", "mike123@hotmail.com"}'),
    (2, 'Tim', '{1899872311, 2123124551}', '{"tim123@gmail.com", "tim123@hotmail.com"}');

To verify the newly inserted data, execute the SELECT statement as follows:
    
    
    SELECT * FROM staff_data;

The output shows that the “staff_data” table has been created successfully. Suppose Tim wants to add one more email; for this purpose, the ARRAY_APPEND() function will be used as follows:
    
    
    UPDATE staff_data 
    SET st_email = ARRAY_APPEND(st_email, 'tim@asdf.com') 
    WHERE st_id = 2;

The output shows that modifications have been made to the selected table. Let’s verify the updated record via the SELECT statement:
    
    
    SELECT * FROM staff_data;

The output shows that an email address has been appended at the end of the array.

 **Conclusion**

Postgres provides an **ARRAY_APPEND()** function that is used to append/add elements at the end of the array. It accepts two parameters: an array and an element to be appended, and consequently, adds/appends the given element at the end of the array. This blog post explained various use cases of the **ARRAY_APPEND()** function via appropriate examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-array_append-function-with-examples/)

---

# How to Get First Non-Null Value in PostgreSQL

> To get the first non-null value in Postgres, an inbuilt function named COALESCE() is used. It accepts the “n” number of arguments and retrieves the first non-n…

Postgres offers an inbuilt **COALESCE()** function that deals with the null values. It takes n arguments and retrieves the first non-null value. The **COALESCE()** function accepts the “n” number of arguments and retrieves the first non-null value. If all the passed values are NULL, then the COALESCE() function will retrieve a null value.

This blog post will provide a detailed overview of how to get the first non-null value in PostgreSQL. So, let’s get started.

 **How to Get the First Non-Null Value in Postgres?**

To get the first non-null value in Postgres, an inbuilt function named **COALESCE()** is used:
    
    
    COALESCE (val_1, val_2, ...);

  * Here, val_1, val_2, etc. are the arguments that can be null or non-null.
  * The COALESCE() function starts the argument’s evaluation from the left side(first value) and searches for the first non-null value.
  * Once the **COALESCE()** function finds a non-null value, immediately, it will stop the evaluation. Consequently, It retrieves only the first non-null value.



Let’s comprehend the functionality of the Postgres **COALESCE()** function via practical examples.

 **Example #1: Passing String Values**

In this example, we will assign five non-null arguments to the COALESCE() function as follows:
    
    
    SELECT COALESCE('Mike', 'Joe', 'Seth', 'Ambrose', 'Joseph');

The **COALESCE()** function found a non-null string at the very first index, so it stopped evaluation immediately and retrieved that non-null string, i.e., “Mike”.

 **Example #2: Passing Null and Non-Null Strings**

In the below example, we will pass null as well as non-null strings to the COALESCE function:
    
    
    SELECT COALESCE(NULL, NULL, 'Joe', 'Seth', 'Mike', NULL, 'Ambrose', 'Joseph');

The output snippet proves that the **COALESCE()** function skipped the first two NULL strings, and retrieved the first non-null string, i.e., ‘Joe’.

 **Example #3: How Does COALESCE() Function Work in Postgres?**

Let’s create a sample table named product_details with four columns: pro_id, pro_name, pro_price, pro_tax:
    
    
    CREATE TABLE product_details(
    pro_id SERIAL,
    pro_name TEXT,
    pro_price INT,
    pro_tax INT
    );

The table named product_details has been created successfully. Let’s insert the below-listed records into the newly created table:
    
    
    INSERT INTO product_details(pro_name, pro_price, pro_tax)
    VALUES ('Laptop', 50000, 5000),
    ('Mobile', 50000, NULL),
    ('Bike', 50000, 1000);

Three records have been inserted into the product_details table. To verify the newly inserted data, execute the SELECT statement as follows:
    
    
    SELECT * FROM product_details;

Let’s find out the total price of a product:
    
    
    SELECT pro_price + pro_tax AS grand_total
    FROM product_details;

We performed additions on the “pro_price” and “pro_tax” columns. As a result, we got erroneous results in the case of a NULL value. To resolve such an issue, we can utilize the COALESCE() function as follows:
    
    
    SELECT pro_name, pro_price, pro_tax, pro_price + COALESCE(pro_tax, 0) 
    FROM product_details;

This is how the **COALESCE()** function deals with the null values.

 **Conclusion**

To get the first non-null value in Postgres, an inbuilt function named **COALESCE()** is used. **COALESCE()** is an inbuilt function that deals with the null values. The **COALESCE()** function accepts the “n” number of arguments and retrieves the first non-null value. If all the passed values are NULL, then the **COALESCE()** function will retrieve a null value. This blog post explained how to get the first non-null value in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-first-non-null-value-in-postgresql/)

---

# PostgreSQL OFFSET Clause With Practical Examples

> In PostgreSQL, the OFFSET clause is used to skip some records before returning the result set of a query. By default, the OFFSET clause skipped the records fro…

In PostgreSQL, the **OFFSET** clause is used to skip some records before returning the result set of a query. Mostly, **OFFSET** clauses are used in conjunction with **LIMIT** clauses to skip a subset of records before returning the result set of the LIMIT query.

This blog post will demonstrate various use cases of the OFFSET clause in Postgres via practical examples. So, let’s get started.

 **How Does OFFSET Clause Work in Postgres?**

To use the OFFSET clause in Postgres, users must follow the below-given syntax:
    
    
    SELECT col_list
    FROM tbl_name
    OFFSET num;

Let’s comprehend the above syntax stepwise:

  * col_list represents the columns to be fetched.
  * tbl_name is a table from which the records will be fetched.
  * OFFSET is a clause that will skip a subset of records.
  * num represents the number of records to be skipped.



 **Example 1: Understanding Basics of the OFFSET Clause**

We have created an “article_details” table whose content is shown below:
    
    
    SELECT * FROM article_details;

The **article_details** table has twelve records. Suppose the user wants to skip the first five records from the selected table, i.e., “article_details”. For this purpose, the user can utilize the **OFFSET** clause as follows:
    
    
    SELECT * FROM article_details
    OFFSET 5;

The output shows that the **OFFSET** clause has skipped the five records and retrieves the remaining records from the **“article_details”** table.

 **Example 2: OFFSET With ORDER BY Clause in Postgres**

What if the user wants to skip the last five records? Well! In such scenarios, users can use the ORDER BY clause with the DESC order:
    
    
    SELECT * FROM article_detail
    ORDER BY article_id DESC
    OFFSET 5;

The output proves that the OFFSET clause skipped the last five records and retrieved the remaining records.

 **Example 3: How to Use OFFSET Clause With LIMIT Clause in Postgres?**

Use the **LIMIT** clause in conjunction with the **OFFSET** clause to skip a subset of records before returning the LIMIT query:
    
    
    SELECT * FROM article_detail
    ORDER BY article_id
    LIMIT 5 OFFSET 2;

In the above query:

  * The **“LIMIT 5”** clause is used to fetch only five records.
  * The **“OFFSET 2”** clause is used to skip the first two records before retrieving the result set of the limit clause:



The output proves that the **OFFSET** clause skipped the first two records and the **LIMIT** clause fetched the next five records from the targeted table.

That’s all from this Postgres guide!

 **Conclusion**

In PostgreSQL, the **OFFSET** clause is used to skip some records before returning the result set of a query. By default, the **OFFSET** clause skipped the records from the top; however, if you have to skip the records from the bottom, you must use the WHERE clause with the DESC option. This blog post demonstrated various use cases of the OFFSET clause via practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-offset-clause-with-practical-examples/)

---

# How to Compare Two Tables Using EXCEPT Operator in PostgreSQL

> In PostgreSQL, the EXCEPT operator is used to compare multiple tables. It executes two SELECT queries and retrieves only those records that are not available i…

Postgres offers multiple ways of comparing two tables, such as using **EXCEPT** Operator, **UNION** operator, **OUTER JOIN** , and so on. Among them, the **EXCEPT** operator is the most widely used approach, which retrieves the filtered result set of various queries based on the comparison.

Through practical examples, this blog post will explain how to compare tables using the **EXCEPT** operator in Postgres. So, let’s get started!

 **How to Compare Tables Using EXCEPT Operators in PostgreSQL?**

The **EXCEPT** operator executes two SELECT queries and retrieves only those records that are not available in the second SELECT query.

Let’s dive into the practical implementation of the **EXCEPT** operator.

 **Example: Table Comparison Using EXCEPT Operator**

First, we will create two tables, and then we will utilize the **EXCEPT** operator to perform a comparison:
    
    
    CREATE TABLE books_info(
    book_id SERIAL PRIMARY KEY,
    book_name TEXT,
    is_available BOOLEAN
    );

The “book_details” table has been created successfully. Let’s utilize the INSERT command to insert the records into the targeted table:
    
    
    INSERT INTO books_info(book_name, is_available)
    VALUES ('Great Expectations', 't'),
    ('Wuthering Heights', 'f'),
    ('The Kite Runner', 't'),
    ('The Catcher in the Rye', 't'),
    ('The Lord of the Rings', 'f'),
    ('His Dark Materials', 't'),
    ('Think and Grow Rich', 't');

The desired records have been inserted into the “books_info” table. Use the SELECT command to fetch the content of the newly created table:
    
    
    SELECT * FROM books_info;

Now create another sample table, let’s say “ **top_selling_books** ” with three columns: book_id, book_name, and is_available:
    
    
    CREATE TABLE top_selling_books(
    book_id INT PRIMARY KEY,
    book_name TEXT,
    is_available BOOLEAN
    );

The table “top_selling_books” was created successfully. Use the INSERT INTO statement to add some data to the selected table:
    
    
    INSERT INTO top_selling_books(book_id, book_name, is_available)
    VALUES (2, 'Wuthering Heights', 't'),
    (3, 'The Lord of the Rings', 't'),
    (4, 'Think and Grow Rich', 't'),
    (1, 'The Great Gatsby', 't'),
    (5, 'To Kill a Mockingbird', 'f'),
    (6, 'The Grapes of Wrath', 't'),
    (7, 'Frankenstein', 'f');

The output shows that the desired records have been inserted into the “top_selling_books” table. Use the SELECT command to fetch the content of the targeted table:
    
    
    SELECT * FROM top_selling_books;

Let’s utilize the **EXCEPT** operator to compare the **“books_info”** and **“top_selling_books”** tables:
    
    
    SELECT book_name
    FROM top_selling_books
    EXCEPT
     SELECT book_name
     FROM books_info;

In this example program, we utilized the EXCEPT operator to compare the two tables: “books_info” and “top_selling_books”. As a result, the EXCEPT operator will retrieve only those records that are not present in the book_info table:

The **EXCEPT** operator retrieves those books that are not available in the books_info table.

That’s all from this Postgres guide.

 **Conclusion**

In PostgreSQL, the **EXCEPT** operator is used to compare multiple tables. The **EXCEPT** operator executes two SELECT queries and retrieves only those records that are not available in the second SELECT query. This blog post has considered a practical example to compare two different tables using EXCEPT operators.

---
[View this page online](https://www.commandprompt.com/education/how-to-compare-two-tables-using-except-operator-in-postgresql/)

---

# PostgreSQL NOW() Function With Practical Examples

> In Postgres, the NOW() function retrieves the current date and time along with the time zone(based on the database server’s setting).

PostgreSQL provides a variety of built-in date and time functions that finds the date and time with or without timezone. For instance, an inbuilt function named **NOW()** is used to get today’s date and time with the time zone.

The purpose of this blog post is to demonstrate how to get the current/present date and time in Postgres using the **NOW()** function. So, let’s start!

 **How to Use the NOW() Function in PostgreSQL?**

In Postgres, the **NOW()** retrieves the current time and date along with the time zone(based on the database server’s setting). It doesn’t require any argument, as shown in the following syntax:
    
    
    NOW();

For a deeper understanding of the NOW() function, let's implement it practically.

 **Example 1: How Does the NOW() Function Work in Postgres?**

This particular example will show you the basic usage of the NOW() function in Postgres:
    
    
    SELECT NOW();

The output proves that the stated function retrieves the current date, time, and timezone.

 **Example 2: How to Use the NOW() Function to Get Today’s Date and Time Without Timezone?**

Use the typecast operator “::” to get the current/present date and time using the NOW() function but without a timezone:
    
    
    SELECT NOW() :: TIMESTAMP;

The output proves that this time, the stated function retrieves the current date, and time, without a timezone.

 **Example 3: How Do I Set Today’s Date as the Default Value of a Column?**

Firstly create a new sample table, let’s say “submit_articles”. We will create three columns within that table: article_id, article_title, and submission_date. Suppose we want to set today’s date as the default submission date. To do so, we will set the NOW() function as a default value of the submission_date column:
    
    
    CREATE TABLE submit_articles(
    article_id INTEGER PRIMARY KEY, 
    article_title TEXT, 
    submission_date DATE DEFAULT NOW());

The submit_articles table has been created. Let’s validate the table’s creation via the below command:
    
    
    SELECT * FROM submit_articles;

Let’s insert some records into the submit_articles table via the INSERT INTO statement:
    
    
    INSERT INTO submit_articles(article_id, article_title)
    VALUES(1, 'Postgres DROP CASCADE'),
    (2, 'Postgres DROP TABLE'),
    (3, 'Postgres DROP DATABASE');

The specified records have been inserted into the submit_articles table. In the insert query, you can see that no record was inserted in the submission_date column. Executing the SELECT command will fetch the newly inserted records:
    
    
    SELECT * FROM submit_articles;

The output depicts that Postgres specifies the current date as a default value in the submission_date column. This way, you can specify the current/today’s date as a default value of any table’s column using the **NOW()** function.

 **Conclusion**

PostgreSQL provides an inbuilt function named **NOW()** that is used to get today’s date and time along with the time zone. In Postgres, the **NOW()** function retrieves the current time and date along with the time zone(based on the database server’s setting). This function doesn’t require any argument/parameter. This blog post demonstrated the working of the NOW() function via practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-now-function-with-practical-examples/)

---

# How to Get Table Size in PostgreSQL

> PostgreSQL provides a pg_relation_size() function to get the size of a particular table. The “pg_size_pretty()” function is used to get the table’s size in a h…

PostgreSQL offers several built-in functions to get the size of databases, tablespaces, tables, etc. If we talk about the table’s size, it can be calculated using the inbuilt **pg_relation_size()** function. In addition to this, PostgreSQL offers another handy built-in function named **pg_size_pretty()** that retrieves the table size in an easily understandable format.

This blog post will demonstrate a couple of functions to calculate the table’s size using practical examples. So, let’s get started!

 **How to Get Table Size in Postgres?**

The below syntax is exercised in Postgres to calculate the size of a particular table:
    
    
    pg_relation_size(tab_name);

Here, tab_name is the targeted table whose size needs to be calculated.

 **Example: How to Find the Table’s Size in Postgres Using pg_relation_size()?**

This particular example is going to elaborate the basic concept of the pg_relation_size() function via stepwise instructions:

 **Step 1: Make a Connection With Database**

Execute the “\l” command from SQL Shell to get the list of all the databases:
    
    
    \l;

Let’s make a connection with a specific database from the available list:
    
    
    \c example;

We are successfully connected to the “example” database.

 **Step 2: Select a Table**

Once you are connected to a database of your choice, run the “\dt” command to describe the list of relations:
    
    
    \dt;

Suppose we need to calculate the size of the “article_details” table.

 **Step 3: Get Table Size**

To get the size of the selected table, you must use the “pg_relation_size()” function as follows:
    
    
    SELECT pg_relation_size('article_details');

The output snippet shows that the pg_relation_size retrieves the size of the “article_details” table.

 **Step 4: Get Table in User-friendly Format**

Use the **pg_size_pretty()** with the **pg_relation_size()** function to get the table size in user-friendly formats, such as KBs, MBs, etc.
    
    
    SELECT pg_size_pretty(pg_relation_size('article_details'));

This way, users can get the table’s size in a more clear way.

 **Step 5: Get Total Size**

Use the **pg_total_relation_size** instead of **pg_relation_size** to get total size of the table including indexes and some other additional objects:
    
    
    SELECT pg_size_pretty (pg_total_relation_size ('article_details'));

This clearly shows that the **pg_total_relation_size()** retrieves the total table size, including indexes and other additional objects.

 **Conclusion**

PostgreSQL provides a **pg_relation_size()** function to get the size of a particular table. Postgres offers another convenient function named **“pg_size_pretty()”** to get the table’s size in a human-readable format, such as bytes, KBs, MBs, and so on. The pg_relation_size() function retrieves only the table’s size without any additional object. However, to get the total size of a table, including indexes and some other additional objects, the pg_total_relation_size() is used in Postgres. This blog post demonstrated various functions that assist the users in getting the table size in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-table-size-in-postgresql/)

---

# PostgreSQL CURRENT_DATE Function With Practical Examples

> CURRENT_DATE is one of the Postgres built-in date functions that retrieve the current/today’s date. It doesn’t take any argument.

PostgreSQL offers a wide range of data and time functions such as **CURRENT_DATE, TO_DATE(), NOW(), CURRENT_TIME** , and so on. Among them, the most widely used function is the **CURRENT_DATE** function which retrieves today’s date.

So, the **CURRENT_DATE** function will be the topic of discussion in this blog post, where we will examine various use cases of the targeted function.

 **How Does the CURRENT_DATE Function Work in Postgres?**

In PostgreSQL, the **CURRENT_DATE** function doesn’t take any argument, as shown in the below-stated syntax:
    
    
    CURRENT_DATE;

Unlike any other traditional function, it doesn't require any parenthesis. It retrieves a **DATE** value representing today’s date.

The best way to comprehend a concept is to implement it practically! So, let’s do it!

 **Example 1: Basic Usage of the CURRENT_DATE Function**

The following snippet will show you the basic usage of the CURRENT_DATE function in Postgres:
    
    
    SELECT CURRENT_DATE;

The output snippet shows that the stated function retrieves today’s date.

 **Example 2: Use the CURRENT_DATE Function as a Default Value of a Table’s Column**

Firstly, we will create a new sample table, let’s say “submit_articles”. The table consists of three columns article_id, article_title, and submission_date. Suppose we want to set the CURRENT_DATE as the default submission date. To do so, we will set the CURRENT_DATE function as a default value of the submission_date column:
    
    
    CREATE TABLE submit_articles(
    article_id INTEGER PRIMARY KEY, 
    article_title TEXT, 
    submission_date DATE DEFAULT CURRENT_DATE);

The submit_articles table has been created. Let’s validate the table’s creation via the below command:
    
    
    SELECT * FROM submit_articles;

Let’s insert some records into the submit_articles table via the INSERT INTO statement:
    
    
    INSERT INTO submit_articles(article_id, article_title)
    VALUES(1, 'Postgres DROP CASCADE'),
    (2, 'Postgres DROP TABLE'),
    (3, 'Postgres CREATE TABLE'),
    (4, 'Postgres DROP DATABASE'),
    (5, 'Postgres CREATE DATABASE');

Five records have been inserted into the submit_articles table. From the above snippet, you can clearly observe that we didn’t insert any value in the submission_date column. Let’s execute the SELECT statement one more time and see what the output says:
    
    
    SELECT * FROM submit_articles;

The output depicts that Postgres specifies the current date as a default value in the submission_date column. This way, you can specify the current/today’s date as a default value in any particular column using the CURRENT_DATE function.

That’s all from this Postgres guide!

 **Conclusion**

 **CURRENT_DATE** is one of the Postgres built-in date functions that retrieve the current/today’s date. It doesn’t take any argument. You can set the current date as a default value of any table’s columns using the CURRENT_DATE function. Through practical examples, this blog post demonstrated how to get today’s date using the CURRENT_DATE function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-current_date-function-with-practical-examples/)

---

# How to Grant All Privileges to Users in PostgreSQL

> PostgreSQL offers a GRANT statement that is used to assign privileges to the database objects. In Postgres, you can grant all privileges to a user via the &quot;GRA…

PostgreSQL offers a **GRANT** statement that is used to assign privileges to the database objects. The database object can be a schema, a table, a function, and so on. In Postgres, the GRANT statement assists the users in accessing and overriding the specific role. In Postgres, you can grant all privileges to a user via the **" GRANT ALL"** statement.

> Try the latest PgManage (Open Source) and get rid of PgAdmin!

This blog post will present a comprehensive guide on granting all privileges to the users in Postgres via practical demonstration. So, let’s start.

 **How to Grant All Privileges to Users in Postgres?**

When a role with the LOGIN attribute is created, it can log into the PostgreSQL database server. However, it cannot interact with the database objects until privileges are granted to that role. To grant all privileges to a user, follow the below syntax:
    
    
    GRANT ALL 
    ON tbl_name
    TO rol_name;

In the above syntax:

  * GRANT is a statement that assigns privileges to the users.
  * ALL is an option used with the GRANT statement to give all the privileges to the users.
  * tbl_name represents a table.
  * rol_name specifies which role should be granted privileges.



> [ ** _Contact us_**](<https://commandprompt.com/contact-us/>) **today for all your Postgres and Open Source consulting and support needs.**

Let’s understand it via practical examples.

 **Example: Grant All Privileges to User**

This example presents a step-by-step procedure to grant all the privileges to the users in Postgres:

 **Step 1: Create a Role**

Let’s create a role named “admin” with LOGIN privileges:
    
    
    CREATE ROLE admin LOGIN PASSWORD 'cp12345';

From the output snippet, you can observe that a role has been created.

 **Step 2: Verify Roles**

To verify the role’s creation, run the “\du” command as follows:
    
    
    \du;

A role named “admin” has been created.

 **Step 3: Create Table**

Now, let’s create a new table named “shortlisted_students” with three columns:
    
    
    CREATE TABLE shortlisted_students(
    student_id INT PRIMARY KEY,
    student_name VARCHAR(50),
    student_email VARCHAR(100)
    );

The table named “shortlisted_students” has been created successfully.

 **Step 4: Login as New User**

Log in as an “admin” user from a new separate session:

Now, we are logged in as an “admin” user.

 **Step 5: Insert Data**

Now try to insert data into the “shortlisted_students” table from the “admin” session:
    
    
    INSERT INTO shortlisted_students(student_id, student_name, student_email) 
    VALUES (1, 'Joseph', 'joseph@12345');

The above snippet shows that the user “admin” doesn’t have privileges to edit the shortlisted_students.

 **Step 6: Grant All Privileges**

Now, log in as a superuser and grant all the privileges on the shortlisted_students table to the “admin” role. To do so, run the GRANT statement with the ALL option:
    
    
    GRANT ALL ON shortlisted_students TO admin;

The output snippet shows that all the privileges have been granted to the **admin** role.

 **Step 7: Insert Data**

Now run the insert query one more time:
    
    
    INSERT INTO shortlisted_students(student_id, student_name, student_email) 
    VALUES (1, 'Joseph', 'joseph@12345');

The output clarifies that one record has been inserted into the shortlisted_students table.

 **Step 8: Fetch Data**

To get the data from the shortlisted_students table, we will execute the SELECT command as follows:
    
    
    SELECT * FROM shortlisted_students;

The output proves that all the privileges have been granted to the user.

 **Conclusion**

PostgreSQL offers a **GRANT** statement that is used to assign privileges to the database objects. In Postgres, you can grant all privileges to a user via the **" GRANT ALL"** statement. When a role with the LOGIN attribute is created, it can log into the PostgreSQL database server. However, it cannot interact with the database objects until privileges are granted to that role. This blog post demonstrated the working of the GRANT statement via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-grant-all-privileges-to-users-in-postgresql/)

---

# How to DROP UNIQUE CONSTRAINT in PostgreSQL

> UNIQUE constraints can be dropped by running the ALTER TABLE command with the &quot;DROP CONSTRAINT&quot; clause followed by the constraint’s name.

In PostgreSQL, the “ **DROP CONSTRAINT** ” clause is used with the ALTER TABLE statement to drop any specific constraint from a table. Using the DROP CONSTRAINT clause, users can drop any specific constraint, such as **UNIQUE CONSTRAINT,** FOREIGN KEY CONSTRAINT, CHECK CONSTRAINT, and so on.

PostgreSQL's "DROP CONSTRAINT" clause with UNIQUE constraint is explained in this article. The content that illustrates the demonstration is as follows:

  * How to DROP UNIQUE CONSTRAINT in PostgreSQL?
  * Step 1: Create Table in PostgreSQL
  * Step 2: ADD UNIQUE CONSTRAINT in PostgreSQL
  * Step 3: DROP UNIQUE CONSTRAINT in PostgreSQL



Let's start with the syntax.

 **How to DROP UNIQUE CONSTRAINT in PostgreSQL?**

In the PostgreSQL database, the “ **DROP CONSTRAINT** ” clause removes the rule or policy that is already set using the “ **ADD CONSTRAINT** ” clause. To drop unique constraints from a table, users must follow the syntax stated below:
    
    
    ALTER TABLE tbl_name
    DROP CONSTRAINT constraint_name UNIQUE (col_name);

ALTER TABLE is a command in Postgres used to alter/modify a table, while “ **DROP CONSTRAINT** ” is a clause that drops the existing unique constraint from the table.

 **Step 1: Create Table in PostgreSQL**

First, create a " college " table with the “ **CREATE TABLE** ” statement. Add columns such as **std_id, teach_id, sport_date,** and **notes** in this table:
    
    
    CREATE TABLE college( 
    std_id INTEGER NOT NULL,
    teach_id INTEGER NOT NULL,
    sport_date DATE,
    notes VARCHAR(200)
    );

The “ **CREATE TABLE** ” message verifies that the “ **college** ” table has been successfully created.

 **Step 2: ADD UNIQUE CONSTRAINT in PostgreSQL**

In any existing table, such as “college”, a unique constraint can be added using the “ **ALTER TABLE** ” statement. For this purpose, write the “ **ADD CONSTRAINT** ” clause with a **UNIQUE** constraint and specify the constraint's name, such as “ **running** ”. For this purpose, the statement is as follows:
    
    
    ALTER TABLE college
    ADD CONSTRAINT running UNIQUE   (teach_id);

The **" ALTER TABLE"** message in the output confirms that the unique constraint has been added to the table. After table alteration, the modified table’s structure will be as follows:
    
    
    \d college;

The output shows that the UNIQUE constraint has been added to the selected table.

 **Step 3: DROP UNIQUE CONSTRAINT in PostgreSQL**

The **“ALTER TABLE”** statement is utilized with the **“DROP CONSTRAINT”** clause to drop the constraint. For instance, the statement is given below:
    
    
    ALTER TABLE college
    DROP CONSTRAINT running;

The constraint “ **running** ” in the existing table “ **college** ” has been dropped, which can be verified through the “ **ALTER TABLE”** message.

To verify the working of the **DROP CONSTRAINT** , let’s execute the command mentioned below:
    
    
    \d college;

The output clearly shows that the unique constraint has been successfully dropped from the “college” table.

That's all from this guide.

 **Conclusion**

Execute the **“DROP CONSTRAINT”** with the collaboration of the “ **ALTER TABLE** ” statement to drop a specific constraint from a table. UNIQUE constraints can be dropped by running the **ALTER TABLE** command with the " **DROP CONSTRAINT** " clause followed by the constraint’s name. This blog post presented a step-by-step guide for dropping a unique constraint in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-unique-constraint-in-postgresql/)

---

# PostgreSQL DIV() Function With Practical Examples

> PostgreSQL provides a built-in DIV() function that takes two numeric values as arguments, performs division on them, and retrieves the resultant integer.

PostgreSQL offers numerous built-in mathematical functions such as [**COUNT()**](<https://www.commandprompt.com/education/how-to-use-count-function-in-postgresql/>) **,** [**AVG()**](<https://www.commandprompt.com/education/how-to-use-avg-function-in-postgresql/>) **,** [**MAX()**](<https://commandprompt.com/education/how-to-use-max-function-in-postgresql/>) **, DIV(),** etc. All these functions are responsible for performing different functionalities, such as **AVG()** function calculates the average, **MAX()** function finds the maximum number, and so on. Similarly, the **DIV()** function is responsible for performing integer division.

This blog post will provide a thorough overview of the DIV() function via practical examples. So, let’s get started.

 **How to Use the DIV() Function in Postgres?**

PostgreSQL provides a built-in mathematical function named **DIV()** that takes two numeric values as arguments, performs division on them, and retrieves the resultant integer. PostgreSQL's **DIV()** function has the following syntax:
    
    
    DIV(arg_1, arg_2);

Here, arg_1 represents the dividend, while arg_2 represents the divisor. The DIV() function will divide the dividend **“arg_1”** with the divisor **“arg_2”** and retrieve a resultant integer(quotient).

Let’s understand the DIV() function via practical examples.

 **Example 1: Pass Two Positive Values to DIV() Function**

The below snippet demonstrates the working of the **DIV()** function:
    
    
    SELECT DIV(12, 8);

The output proves that the DIV() function divides the dividend “12” with the divisor “8” and retrieves the quotient “1”.

 **Example 2: Pass Two Negative Values to DIV() Function**

Let’s consider the following statement to see how the DIV() function deals with negative values:
    
    
    SELECT DIV(-120, -7);

The output shows that the **DIV()** function performs the division on the given numbers and retrieves a numeric value.

 **Example 3: Pass One Positive and One Negative Value to DIV() Function**

Let’s pass a negative dividend and positive devisor and see how the DIV() function works:
    
    
    SELECT DIV(-120, 7);

The output shows that the DIV() function retrieves the appropriate result.

 **Example 4: Pass Fractional Values to DIV() Function**

Let’s learn how does the DIV() function work with the fractional values:
    
    
    SELECT DIV(123.43, 14.54);

The output shows that the DIV() function performs division on the given fractional values and retrieves an integer value.

 **Example 5: How to Use DIV() Function on Table’s Data?**

Let’s create a table div_example that consists of two columns: num1, and num2:
    
    
    CREATE TABLE div_example (
    num1 NUMERIC,
    num2 NUMERIC
    );

A table named “div_example” has been created. Let’s insert some data into the **“div_example”** table:
    
    
    INSERT INTO div_example(num1, num2)
    VALUES(1920, 11),
    ('Seth', 890, 6),
    ('Mike', 675, 3),
    ('Joseph', 107, 15);

Four records have been inserted into the div_example table. Let’s implement the DIV() function on the div_example table to perform the division on the num1 and num2 columns:
    
    
    SELECT DIV(num1, num2)
    FROM div_example;

The output authenticates the working of the **DIV()** function as it retrieves the appropriate results.

That’s it from this Postgres guide.

 **Conclusion**

PostgreSQL provides a built-in **DIV()** function that takes two numeric values as arguments, performs division on them, and retrieves the resultant integer. The **DIV()** function accepts any positive values, negative values, fractional/floating point values, etc. as arguments and retrieves an integer value. This blog post explained different use cases of the DIV() function via practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-div-function-with-practical-examples/)

---

# How to Comment in PostgreSQL

> In Postgres, double hyphen “--” sign is used for single-line comments, while to use multi-line comments, you need to enclose the comments within “/*” and “*/”.

Comments play a very important role in PostgreSQL. Users add comments along with the commands/queries to make them more readable and understandable. At the time of execution, the interpreter completely ignores them. So, using comments, users can write anything that assists them in understanding their code/statements.

Postgres supports single-line as well as multi-line comments. This write-up will demonstrate both of them via practical examples. So, let’s start with the importance of comments in Postgres.

 **Importance of Comments**

As discussed earlier, the comments in PostgreSQL make the commands more understandable. Let’s consider the below-listed points to understand the importance of comments in a better way:

  * Comments make the statements easy to read.
  * Comments assist the users in error detection and code maintenance.
  * Comments are used to describe a function, query, statement, etc.



Let’s explore various types of comments and how to use them in Postgres via practical examples.

 **How to Comment in PostgreSQL?**

PostgreSQL facilitates us with single-line as well as multi-line comments. Let’s comprehend each of them one by one via practical examples.

 **Single-Line Comment in Postgres**

In PostgreSQL, the double hyphen “--” sign is used for single-line comments. The below syntax will provide you with more clarity regarding single-line comments in Postgres:
    
    
    – write anything here

 **Multi-Line Comment in Postgres**

To use multi-line comments in Postgres, follow the syntax given below:
    
    
    /* write anything here */

The above snippet indicates that to use multi-line comments, you need to enclose the comments within “/*” and “*/”.

 **Example 1: How to Use a Single Line Comment in PostgreSQL?**

Postgres single-line comments are demonstrated in this example program:
    
    
    -- Creating a new table using CREATE TABLE command
    CREATE TABLE cmt_example(
    id INT, --creating an INTEGER type column
    name TEXT --creating a character type column
    );

The table named cmt_example has been created. It shows that the interpreter executes the commands and ignores the single-line comments.

 **Example 2: How to Use Multi-Line Comments in PostgreSQL?**

Here is an example of commenting on multiple lines in Postgres:
    
    
    /*
    CREATE TABLE cmt_example(
    id INT, --creating an INTEGER type column
    name TEXT --creating a character type column
    );
    */
    INSERT INTO cmt_example(id, name)
    VALUES (1, 'single-line comment'),
    (2, 'Multi-line comment');

The output shows that the query enclosed within the multi-line comments didn’t execute. While the rest of the commands get executed and perform the functionality accordingly.

 **Conclusion**

PostgreSQL supports single-line as well as multi-line comments. The double hyphen “--” sign is used for single-line comments, while to use multi-line comments, you need to enclose the comments within “/*” and “*/”. Comments make the statements easy to read, more understandable, describe commands, etc. This write-up demonstrated the working of single-line and multi-line comments via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-comment-in-postgresql/)

---

# How to Create Arrays in PostgreSQL

> To create an array in Postgres, users must specify the column name, then the data type, followed by the square brackets “[]”.

PostgreSQL allows users to create **arrays** of any data type like INTEGER, TEXT, DATE, etc. In Postgres, **Arrays** allow us to store data of any inbuilt, user-defined, or enumerated data type. However, the data Stored in an array must be of the same type. For instance, in Postgres, an array can be created with the INTEGER data type, TEXT data type, DATE data type, etc., but neither can be combined into one array.

This write-up will show you how to create arrays in PostgreSQL via practical examples. So, let's get started.

 **How to Create Arrays in PostgreSQL?**

To create an array in Postgres, users must specify the column name, then the data type, followed by the square brackets “[]”. For instance, the below syntax will create an array at the time of table creation:
    
    
    CREATE TABLE tbl_name(
    col_1 data_type[]
    );

Here, in the above snippet, tbl_name represents the table name, col_1 represents the column name, and data_type indicates the data type of the array. The square brackets after the data_type depict that it’s an array.

 **Example 1: Creating Arrays in Postgres**

Let’s create a sample table named staff_data with four columns: st_id, st_name, st_phone, st_email:
    
    
    CREATE TABLE staff_data(
    st_id INT PRIMARY KEY,
    st_name TEXT,
    st_phone INT[],
    st_email VARCHAR[]
    );

The table named staff_data has been created successfully. Let’s insert the below-listed records into the “staff_data” table:
    
    
    INSERT INTO staff_data(st_id, st_name, st_phone, st_email)
    VALUES
    (1, 'Mike', '{1234567811, 1112223312}', '{"mike123@gmail.com", "mike123@hotmail.com"}'),
    (2, 'Tim', '{1899872311, 2123124551}', '{"tim123@gmail.com", "tim123@hotmail.com"}');

To verify the newly inserted data, execute the SELECT statement as follows:
    
    
    SELECT * FROM staff_data;

This is how you can create an array and insert data into that array in PostgreSQL.

 **Example 2: Creating Arrays of Specific Range in Postgres**

Specify the range within the square brackets to create arrays of a specific range:
    
    
    CREATE TABLE staff_detail(
    st_id INT PRIMARY KEY,
    st_name TEXT,
    st_exm BIGINT[13]
    );

An array with a specified range has been created. It will accept less than or equal to 13 digits:
    
    
    INSERT INTO staff_detail(st_id, st_name, st_exm)
    VALUES
    (1, 'Mike', '{1234567811, 4351112223312}'),
    (2, 'Tim', '{121899872311, 2156231245517}');

Two records have been inserted into the **“staff_detail”** table. Let’s fetch the newly inserted data via the SELECT command:
    
    
    SELECT * FROM staff_detail;

This way, the arrays with specified range work in Postgres.

 **How to Create 2-D Arrays in Postgres?**

To create a multidimensional array in Postgres, specify the column name and then the data type, followed by two sets of square brackets:
    
    
    CREATE TABLE tbl_name(
    col_1 data_type[][]
    );

Let’s comprehend the concept of 2-d arrays via a practical example:

 **Example: Creating 2-D Arrays in Postgres**

Let’s learn how to create a multidimensional array in Postgres:
    
    
    CREATE TABLE staff_info(
    st_id INT PRIMARY KEY,
    st_name TEXT,
    st_exm INT[][]
    );

A 2-D array has been created successfully. To insert the data into the “staff_bio” table, run the below command:
    
    
    INSERT INTO staff_bio(st_id, st_name, st_exm)
    VALUES
    (1, 'Ambrose', '{{323, 111},{222, 555}}'),
    (2, 'Joseph', '{{433, 421},{243, 385}}'),
    (3, 'Dean', '{{543, 511},{712, 505}}');

This is how the 2-D arrays work in Postgres.

 **Conclusion**

To create an array in Postgres, users must specify the column name, then the data type, followed by the square brackets “[]”. You can create an array with a range; to do so, Specify the range within the square brackets. To create a multidimensional array in Postgres, specify the column name and then the data type, followed by two sets of square brackets. This blog post presented an in-depth overview of the Postgres array through practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-arrays-in-postgresql/)

---

# PostgreSQL UPPER() Function With Practical Examples

> Postgres&#x27; UPPER() function accepts a string as an argument and converts the string’s case to upper. It can accept any character string, such as CHAR, TEXT, and…

PostgreSQL offers multiple built-in functions to perform different functionalities on the strings. One of the most commonly used functions/operations when working with strings is case conversion. Sometimes users must convert the given strings from lowercase to uppercase or vice versa to fulfill some specific purpose. To deal with such cases, Postgres offers some built-in functions such as **LOWER(), UPPER(),** and **INITCAP()**. Postgres' **UPPER()** function accepts a string as an argument and converts the string’s case to upper.

This blog post demonstrates the working of the **UPPER()** function in Postgres via practical examples. So, let’s begin.

 **How to Use the UPPER() Function in Postgres?**

In PostgreSQL, letter case conversion from lower to upper or upper to lower is a very common task while working with strings. A string can be converted to uppercase in Postgres using the **UPPER()** function.

 **Syntax**

To use the **UPPER()** function in Postgres, users must follow the below syntax:
    
    
    UPPER(input_string);

Here, input_string represents a string to be converted into uppercase. The data type of the input_string can be CHAR, VARCHAR, or TEXT.

Let’s comprehend the working of the UPPER() function through practical examples.

 **Example 1: How to Convert a String Into Upper Case Letters?**

Let’s pass the string “welcome to commandprompt.com” to the UPPER() function and see how it works:
    
    
    SELECT UPPER('welcome to commandprompt.com');

The output shows that the given string has been converted into uppercase successfully.

 **Example 2: How to Use the UPPER() Function on Table’s Data?**

Firstly, we will create a sample table named student_bio with three columns: student_id, student_name, and student_email:
    
    
    CREATE TABLE student_bio(
    student_id INT,
    student_name TEXT,
    student_email VARCHAR
    );

A table named **“student_bio”** with the three columns has been created successfully. To insert data into the **“student_bio”** table, we will utilize the following command:
    
    
    INSERT INTO student_bio(student_id, student_name, student_email)
    VALUES (1, 'anna', 'anna123@xyz.com'),
    (2, 'stephen', 'stephen321@abc.com'),
    (3, 'henry', 'henry098@abc.com'),
    (4, 'natie', 'natie@xyz.com'),
    (5, 'mike', 'mike@xyz.com');

Let’s utilize the UPPER() function to convert the student_name column into uppercase. To do so, we will utilize the UPPER() function as follows:
    
    
    SELECT student_name, UPPER(student_name)
    FROM student_bio;

The output authenticates that the “student_name” column has been converted into uppercase letters successfully.

 **Example 3: How to Use UPPER() Function With WHERE Clause in Postgres?**

You can use the UPPER() function with the WHERE clause to convert some specific strings into uppercase:
    
    
    SELECT student_name, UPPER(student_name)
    FROM student_bio
    WHERE student_id >= 3;

The output clarifies that the UPPER() function converts all those student names into uppercase that satisfies the given criteria.

 **Example 4: Pass Integer Value to UPPER() Function in Postgres**

Let’s utilize the UPPER() function on the student_id column to see how it deals with the integer values:
    
    
    SELECT UPPER(student_id)
    FROM student_bio;

When we passed an integer to the UPPER() function, Postgres threw an error.

That’s all from this guide!

 **Conclusion**

Postgres' UPPER **()** function accepts a string as an argument and converts the string’s case to upper. It can accept any character string, such as CHAR, TEXT, and VARCHAR. Passing anything other than string will throw an error. This blog post has demonstrated various use cases of the Postgres UPPER() function through practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-upper-function-with-practical-examples/)

---

# PostgreSQL LOWER() Function With Practical Examples

> PostgreSQL provides a built-in string function named LOWER() that accepts a string as an argument and converts it into lowercase.

In PostgreSQL, various inbuilt string functions are available to perform different functionalities on the strings. For instance, the **CONCAT()** function concatenates various strings, the **REPLACE()** function replaces a substring with some other string, and so on.

Similarly, letter case conversion from lower to upper or upper to lower is a very common task while working with strings. To deal with such cases more effectively, Postgres offers some built-in functions such as **LOWER(), UPPER(),** and **INITCAP().**

In this blog post, we will discuss the working of the **LOWER()** function through practical examples.

 **How to Use LOWER() Function in Postgres?**

Postgres' LOWER **()** function accepts a string as an argument and converts the string’s case to lower. To use the LOWER() function in Postgres, users must follow the below syntax:
    
    
    LOWER(input_string);

Here, input_string represents a string to be converted into lowercase. The data type of the input_string can be CHAR, VARCHAR, or TEXT.

Let’s comprehend the working of the LOWER() function through practical examples.

 **Example 1: How to Convert a String Into Lower Case Letters?**

Let’s pass the string “WELCOME TO COMMANDPROMPT.COM” to the LOWER() function and see how it works:
    
    
    SELECT LOWER('WELCOME TO COMMANDPROMPT.COM');

The output shows that the given string has been converted into a lowercase letter successfully.

 **Example 2: How to Use LOWER() Function on Table’s Data?**

Firstly, we will create a sample table named employee_bio with three columns: employee_id, employee_name, and employee_email:
    
    
    CREATE TABLE employee_bio(
    employee_id INT,
    employee_name TEXT,
    employee_email VARCHAR
    );

A table named **“employee_bio”** with the desired column has been created successfully. To insert data into the **“employee_bio”** table, we will utilize the following command:
    
    
    INSERT INTO employee_bio(employee_id, employee_name, employee_email)
    VALUES (1, 'JOSEPH', 'JOSEPH@XYZ.COM'),
    (2, 'JOHNSON', 'JOHNSON@XYZ.COM'),
    (3, 'HENRY', 'HENRY@XYZ.COM');

Suppose we have to convert the email address to lowercase letters; for that purpose, we will utilize the LOWER() function as follows:
    
    
    SELECT employee_name, employee_email, LOWER(employee_email)
    FROM employee_bio;

The output clearly states that the “employee_email” column has been converted into lowercase letters successfully.

 **Example 3: How to Use LOWER() Function with WHERE Clause in Postgres?**

You can use the LOWER() function with the WHERE clause to convert some specific strings into lowercase in Postgres:
    
    
    SELECT employee_name, employee_email, LOWER(employee_email)
    FROM employee_bio
    WHERE employee_id = 2;

The output clarifies that this time the LOWER() function converts only that email into lowercase which satisfies the given criteria.

 **Conclusion**

PostgreSQL provides a built-in string function named **LOWER()** that accepts a string as an argument and converts it into lowercase. It can accept any character string, such as CHAR, TEXT, and VARCHAR. This blog post demonstrated various use cases of the Postgres LOWER() function through practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-lower-function-with-practical-examples/)

---

# How to Use FLOOR() Function in PostgreSQL

> In PostgreSQL, the FLOOR() function is one of the math functions that accept a numeric value or expression and round down the given number to the nearest integ…

PostgreSQL provides numerous math functions to perform various mathematical operations, such as ROUND(), SQRT(), etc. All these functions offer different functionality, such as rounding a number to its nearest integer, finding the square root of a number, etc. PostgreSQL offers another useful function named the **FLOOR()** function that rounds down a number to the next whole number.

This blog post will demonstrate the working of the FLOOR() function via practical examples. So, let’s get started.

 **How to Use FLOOR() Function in Postgres?**

Postgres **FLOOR()** function is one of the math functions that accept a numeric value or an expression and round down to the next whole number:
    
    
    FLOOR(num);

  * The above snippet shows that the **FLOOR()** function accepts only a single argument, “num”.
  * The “num” can be a numeric value or an expression.
  * The FLOOR() function retrieves an integer/whole number.
  * The return value will always be less than or equal to the given number; the retrieved value cannot exceed the given number.



 **Example 1: How Does the FLOOR() Function Work?**

Let’s execute the below command and see how the FLOOR() function works in Postgres:
    
    
    SELECT FLOOR(72.5772);

In the above snippet, the FLOOR() function takes the number “72.5772”; consequently, it will retrieve the following output:

The output shows that the FLOOR() function rounded down the given number to the nearest integer.

 **Example 2: How Does the FLOOR() Function Work With an Expression?**

Let’s pass an expression instead of a number and see how the FLOOR() function works:
    
    
    SELECT FLOOR(72.5272 + 138.1217);

The output shows that the FLOOR() function calculates the given expression and rounds the number down to the nearest whole number.

 **Example 3: How to Use the FLOOR() Function on Table’s Data?**

Firstly, we will create a sample table named “emp_bio” with three columns: emp_id, emp_name, and emp_bio:
    
    
    CREATE TABLE emp_bio(
    emp_id INT,
    emp_name TEXT,
    emp_sal NUMERIC
    );

The “emp_bio” is successfully created. Now, we will insert some records/data in the newly created table:
    
    
    INSERT INTO emp_bio(emp_id, emp_name, emp_sal)
    VALUES (1, 'Joseph', 50587.7891),
    (2, 'Mike', 40856.5678),
    (3, 'Dean', 30756.4321),
    (4, 'Ambrose', 30712.1234);

Let’s verify the table’s data via the SELECT command:
    
    
    SELECT * FROM emp_bio;

Now let’s utilize the FLOOR() function on the emp_sal column of the emp_bio table:
    
    
    SELECT emp_sal, FLOOR(emp_sal)
    FROM emp_bio;

The output authenticates the working of the FLOOR() function as it successfully rounded down the column’s values to the nearest integers.

 **Conclusion**

In PostgreSQL, the **FLOOR()** function is one of the math functions that accept a numeric value or expression and round down the given number to the nearest integer/whole number. The return value will always be less than or equal to the given number; the retrieved value cannot exceed the given number. This blog post presented a detailed guide on the **FLOOR()** function via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-floor-function-in-postgresql/)

---

# How to Use TRIM() Function in PostgreSQL

> TRIM() is an inbuilt function in Postgres that accepts a string and deletes the leading, trailing, or both leading and trailing spaces or characters from a str…

PostgreSQL provides various in-built functions to perform different tasks on the strings. For instance, the **SUBSTRING()** function extracts a substring, the **POSITION()** function finds the location/position of a substring within the input string, and so on. Similarly, Postgres offers another useful built-in function named **TRIM()** that deletes the extra spaces from the leading(starting), trailing(ending) or both sides of the string.

This blog post will demonstrate the working of the TRIM() function via practical examples. So, let’s get started!

 **How to Use TRIM() Function in PostgreSQL?**

TRIM() is an inbuilt function in Postgres that accepts a string and deletes the leading, trailing, or both leading and trailing spaces or characters from a string. Here is the syntax that will remove all your ambiguities regarding the TRIM() function:
    
    
    TRIM(flag rem_string FROM input_string);

In the above syntax, TRIM() is a built-in function that accepts three parameters:

  * In place of the flag, you can specify LEADING, TRAILING, or BOTH.
  * Specifying the LEADING parameter will remove the spaces/characters from the beginning, while if you specify the TRAILING parameter, then the spaces/characters will be removed from the end of the string.
  * In case you specify BOTH, then the spaces/characters will be trimmed from both sides(i.e., Start and end) of the input string.
  * rem_string is an optional parameter that can be skipped. The rem_string parameter removes a particular set of characters from the input string.
  * input_string represents the main string.



Alternatively, you can use the below-listed shorter version of the TRIM() function in Postgres:

  * The LTRIM() is a shorter function to remove the character’s sequence and spaces from the start of the string.
  * The RTRIM() is a shorter function of TRIM() that removes the character’s sequence and spaces from the end of the string.
  * The BTRIM() function is a shorter function that is a combination of the LTRIM() and RTRIM() functions, and hence it trims the characters and spaces from both sides, i.e., leading and trailing.



 **Example 1: How Does the TRIM() Function Work in Postgres?**

Let’s utilize the TRIM() function to remove the leading/starting and trailing/ending spaces from the given string “ Welcome to commandprompt.com ”:
    
    
    SELECT TRIM(' Welcome to commandprompt.com ');

The output clarifies that the TRIM() function successfully trimmed the leading and trailing spaces from the input string.

 **Example 2: How to Remove Trailing Characters From a String in Postgres?**

In the following code snippet, we will remove the trailing characters '.com' from the input string using the **TRIM()** function:
    
    
    SELECT TRIM(TRAILING '.com' FROM 'Welcome to commandprompt.com');

This way, you can trim a sequence of characters from the input string via the TRIM() function.

 **Example 3: How to Remove Leading Characters From a String in Postgres?**

In this example, we will remove the leading "wel" from the input string using TRIM() function:
    
    
    SELECT TRIM(LEADING 'Wel' FROM 'Welcome to commandprompt.com');

The output shows that the TRIM() function successfully trimmed the sequence of characters from the input string.

 **Example 4: How to Use TRIM() Function on Table’s Data?**

Let’s create a sample table named “emp_data” and insert some data into that table:
    
    
    CREATE TABLE emp_data(
    emp_name TEXT,
    emp_email VARCHAR
    );

Now insert some data into the emp_data table via the following command:
    
    
    INSERT INTO emp_data(emp_name, emp_email)
    VALUES
    ('Tim Root', 'timroot@xyz.com'),
    ('Mike William', 'mikewilliam@xyz.com'),
    ('Joe Clarke', 'joeclarke@xyz.com');

Let’s utilize the TRIM() function on the emp_email column for trimming the trailing sequence of characters, i.e., “.com”:
    
    
    SELECT emp_email, TRIM(TRAILING '.com' FROM emp_email)
    FROM emp_data;

The output authenticates that the TRIM() function successfully trimmed the specified trailing characters from the emp_email column.

 **Conclusion**

 **TRIM()** is an inbuilt function in Postgres that accepts a string and deletes the leading, trailing, or both leading and trailing spaces or characters from a string. This blog post demonstrated various use cases of the TRIM() function via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-trim-function-in-postgresql/)

---

# How to Use MD5 Function in PostgreSQL

> PostgreSQL provides a built-in function named MD5 that accepts a string as an argument and converts it into a 32 characters text string. It retrieves the resul…

**MD5** is a built-in function in Postgres that takes a string as an argument and converts it into a 32 characters text string. It retrieves the resultant value in the hexadecimal. It is commonly used to fulfill security purposes. MD5 accepts only string values; passing an integer will result in an error.

This blog post will demonstrate the working of the **MD5** function via practical examples. So, let’s get started.

 **How to Use MD5 Function in PostgreSQL?**

MD5 is a cryptographic/encrypted hash function that generates a 128-bit hash value. The syntax of the MD5 function will look like this:
    
    
    MD5(string_val);

The above snippet shows that the MD5 function accepts a single string argument “string_val”. The string_val represents a string to be converted into a 32-characters text string.

 **Note:** When creating a user in Postgres, we can use **MD5** to create an encrypted password for the newly created users.

 **Example 1: How Does the MD5 Function Work in Postgres?**

Let’s pass a string value as an argument to the targeted function and see how it works:
    
    
    SELECT MD5('Welcome to commandprompt.com');

The output verifies that the **MD5** function successfully converted the given string into the 32-character text string.

 **Example 2: How Does the MD5 Function Deals With Integers?**

In this example, we are going to pass an integer value to the MD5 function to see how it works in this particular situation:
    
    
    SELECT MD5(512);

The output proves that an “argument types” error occurs when we pass an integer value to the MD5 function.

 **Example 3: How to Use MD5 Function on Table’s Data?**

Let’s create a sample table named “user_detials” with two columns: user_name and account_num:
    
    
    CREATE TABLE user_details(
    user_name TEXT,
    account_num TEXT
    );

A table named user_details is created. In the newly created table, we can insert as many rows/records as we want:
    
    
    INSERT INTO user_details(user_name, account_num)
    VALUES ('Joe', 'xyz123abc'),
    ('John', 'avc1230987898'),
    ('Seth', 'xyz1231346712'),
    ('Joseph', '1234123980112'),
    ('Mike', 'xyz1232349801');

Now let’s utilize the MD5 function to convert the values of the “account_num” column into 32-character text strings:
    
    
    SELECT user_name, account_num, MD5(account_num)
    FROM user_details;

In the above snippet, we utilized the SELECT statement to fetch the user_name and account_num columns of the user_details table. Moreover, the MD5 function is used to convert the values of the account_num column to the 32 characters TEXT strings:

This is how you can convert a table’s column into a 32-character text string.

 **Conclusion**

PostgreSQL provides a built-in function named **MD5** that accepts a string as an argument and converts it into a 32 characters text string. It retrieves the resultant value in the hexadecimal. It is commonly used to fulfill security purposes. MD5 accepts only string values; passing an integer will result in an error. This blog post considered various examples to explain the working of the Postgres MD5 function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-md5-function-in-postgresql/)

---

# How to Use LOG() Function in PostgreSQL

> PostgreSQL provides a built-in mathematical function named LOG() that calculates the logarithm of a number to the base ten or the specified base.

PostgreSQL provides a built-in **LOG()** function to calculate the logarithm of a number to the base ten or the specified base. It is a mathematical function that accepts a numeric value, double precision value, or a numeric expression and retrieves the base 10 logarithms of the given number/expression.

This blog post will demonstrate the working of the **LOG()** function via practical examples. So, let’s get started.

 **How to Use LOG() Function in Postgres?**

By default, the LOG() function calculates the base 10 logarithms of a number. However, you can specify the base of your choice as an argument to the LOG() function.

 **Syntax**

Use one of the following syntaxes to calculate the logarithms of a number using the LOG() function:
    
    
    LOG(num);

Or
    
    
    LOG(base, num);

Here, "num" can be numeric or double precision value. Or it can be a numeric expression.

 **Example 1: Base 10 Logarithm**

Let’s pass a number to the LOG() function to calculate the base 10 log of the input number:
    
    
    SELECT LOG(72);

The output shows that the LOG() function retrieves the base 10 logarithms of the “72”.

 **Example 2: Base 2 Logarithm**

In this example, we will calculate the base 2 logarithm of a number:
    
    
    SELECT LOG(2.0, 72);

The output shows that the LOG() function retrieves the base 2 logarithms of the input number.

 **Example 3: Pass an Expression to the LOG() Function**

In this example, we will pass an expression to the LOG() function:
    
    
    SELECT LOG(10 * 2);

The output authenticates the working of the LOG() function.

 **Example 4: How to Use the LOG() Function on Table’s Data?**

Let’s create a sample table named exm_tab with two columns: exp_base and exp_num:
    
    
    CREATE TABLE exm_tab(
    exp_base NUMERIC,
    exp_num NUMERIC
    );

Now we will insert some records into the newly created table:
    
    
    INSERT INTO exm_tab(exp_base, exp_num)
    VALUES (10, 200.00),
    (2, 200.00),
    (10, 20),
    (10, 20);

To see the newly inserted data, execute the SELECT command as follows:
    
    
    SELECT * FROM exm_tab;

Let’s utilize the LOG() function on the “exm_tab” table to calculate the logarithm of various numbers:
    
    
    SELECT LOG(exp_base, exp_num)
    FROM exm_tab;

This is how you can utilize the LOG() function on the table’s data.

 **Conclusion**

PostgreSQL provides a built-in mathematical function named **LOG()** that calculates the logarithm of a number to the base ten or the specified base. By default, the LOG() function calculates the base 10 logarithms of a number. However, you can specify the base of your choice as an argument to the LOG() function. This blog post considered numerous use cases of the LOG() function and practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-log-function-in-postgresql/)

---

# How to Use CEIL() Function in PostgreSQL

> Postgres provides a CEIL() function that takes a numeric value or an expression as an argument and rounds up the given value/expression to the next whole numbe…

In PostgreSQL, you can perform a variety of mathematical operations via built-in math functions, such as POWER(), SQRT(), etc. All these functions fulfill different tasks, for instance, finding the power of a number, the square root of a number, and so on. Similarly, PostgreSQL offers another convenient mathematical function named the **CEIL()** that rounds up a number to the next whole number.

This blog post will demonstrate the working of the **CEIL()** function via practical examples. So, let’s get started.

 **How to Use CEIL() Function in Postgres?**

Postgres **CEIL()** function is one of the mathematical functions that take a numeric value or an expression as an argument and round up the given value/expression to the next whole number:
    
    
    CEIL(arg_1);

  * The above snippet shows that the **CEIL()** function accepts only a single argument, “arg_1”.
  * The “arg_1” can be a numeric value or an expression.
  * The retrieved value will have the same data type as the given numeric value/expression.



 **Example 1: How Does the CEIL() Function Work?**

Let’s pass a numeric value to the CEIL() function and see how it works in Postgres:
    
    
    SELECT CEIL(112.1232);

In the above snippet, the CEIL() function takes the number “112.1232”, and consequently, it retrieves the following output:

The output shows that the CEIL() function rounded up the given number to the nearest integer.

 **Example 2: How Does the CEIL() Function Work With an Expression?**

Let’s pass an expression instead of a number to the CEIL() function and see how it works:
    
    
    SELECT CEIL(572.272 + 168.278);

The output shows that the CEIL() function calculates the given expression and rounds the resultant value up to the nearest whole number.

 **Example 3: How to Use the CEIL() Function on Table’s Data?**

We have already created an “emp_bio” table; let’s verify the selected table’s data via the SELECT command:
    
    
    SELECT * FROM emp_bio;

Now let’s utilize the CEIL() function on the emp_sal column of the emp_bio table:
    
    
    SELECT CEIL(emp_sal)
    FROM emp_bio;

The output authenticates the working of the CEIL() function as it successfully rounded up the column’s values to the nearest integers.

 **Conclusion**

Postgres provides a **CEIL()** function that takes a numeric value or an expression as an argument and rounds up the given value/expression to the next whole number. The retrieved value will have the same data type as the given numeric value/expression. This blog post presented a detailed guide on the **CEIL()** function via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-ceil-function-in-postgresql/)

---

# How to Use TRUNC() Function in PostgreSQL

> In PostgreSQL, TRUN() function is one of the math functions that accept a numeric value and truncates its entire fractional part or up to specific decimal plac…

PostgreSQL offers a wide range of math functions to perform different mathematical operations. For instance, the **ROUND()** function rounds a number to its nearest integer, the **FLOOR()** function rounds down a number to the next whole number, and so on. Similarly, Postgres provides a **TRUNC()** function that truncates the fractional/decimal part of a number.

This blog post will demonstrate the working of the TRUNC() function via practical examples. So, let’s get started.

##  **How to Use TRUNC() Function in PostgreSQL**

Postgres **TRUNC()** function is one of the math functions that accept a number and truncates its entire fractional part or up to specific decimal places:
    
    
    TRUNC(arg_1, arg_2);

  * The above snippet shows that the **TRUNC()** function accepts two arguments.
  * The first argument, i.e., “arg_1”, represents a number to be truncated.
  * While the second argument, i.e., “arg_2”, determines the number of decimal places.
  * The arg_2 is optional and can be omitted/skipped. In such a case, the TRUNC() function will truncate the whole fractional part from the given number.



###  **Example 1: How Does the TRUNC() Function Work?**

Let’s pass only a single argument to the TRUNC() function and see how it works:
    
    
    SELECT TRUNC(27.51272);

The output shows that the TRUNC() function truncates the entire fractional part from the given number.

###  **Example 2: How Does the TRUNC() Function Work With Two Parameters?**

Let’s execute the TRUNC() function with two arguments and see how it works:
    
    
    SELECT TRUNC(27.51272, 2);

The output shows that the TRUNC() function truncates the given number to two decimal places.

###  **Example 3: How Does the TRUNC() Function Work With a Negative Parameter?**

In this example, we pass a negative value as a second parameter to see how the TRUNC() function works in such a situation:
    
    
    SELECT TRUNC(2751.272, -2);

In the above snippet, the second argument is “-2”, so the TRUNC() function will truncate the digits to the left of the fractional/decimal point:

This is how the TRUNC() function works with negative parameters.

###  **Example 4: How to Use the TRUNC() Function on Table’s Data**

Firstly, we will create a sample table named “emp_bil” with three columns: emp_id, emp_name, and emp_bio:
    
    
    CREATE TABLE emp_bio(
    emp_id INT,
    emp_name TEXT,
    emp_sal NUMERIC
    );

The “emp_bio” is successfully created. Now, insert some records/data in the newly created table:
    
    
    INSERT INTO emp_bio(emp_id, emp_name, emp_sal)
    VALUES 
    (1, 'Joe', 50500.7895),
    (2, 'Kane', 40800.1234),
    (3, 'Smith', 30700.5678);

Now utilize the TRUNC() function on the emp_sal column to truncate the fractional part:
    
    
    SELECT TRUNC(emp_sal)
    FROM emp_bio;

The output proves that the TRUNC() function successfully truncated the fractional part from the column’s values.

###  **TRUNC() vs. ROUND()**

The **TRUNC()** function trims the fractional part regardless of its value while the **ROUND()** function rounds the input number based on the fractional/decimal part (i.e., >= .5 or <.5).

>  _For more details, read_ _PostgreSQL TRUNC() VS ROUND() Function_

##  **Conclusion**

In PostgreSQL, the **TRUNC()** function is one of the math functions that accept a numeric value and truncate its entire fractional part or up to specific decimal places. It accepts two values as arguments, a value to be truncated and a number that determines the number of decimal places. The second argument can be omitted/skipped. In such a case, the TRUNC() function will truncate the whole fractional part from the given number. This blog post presented a detailed guide on the TRUNC() function via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-trunc-function-in-postgresql/)

---

# How to Use Temporary Table in PostgreSQL

> How to Use Temporary Table in PostgreSQL

The temporary table is a table whose existence expires with the database session. In PostgreSQL, the working procedure of the temporary table is similar to the normal table. Normal tables get deleted only when the user deletes them willingly; however, the temporary tables get deleted automatically when the current session expires. Users can insert, delete and update values in a temporary table using respective queries.

This guide is to demonstrate the temporary table along with various examples in the PostgreSQL database as below.

  * Create Temporary Table in PostgreSQL
  * Insert Values in Temporary Table
  * Drop Temporary Table in PostgreSQL
  * Remove Temporary Table via Closing Session



 **Create Temporary Table in PostgreSQL**

For creating a temporary table in PostgreSQL, the “ **CREATE TEMP TABLE** ” statement is used:
    
    
    CREATE TEMP TABLE emp_table(
    id INT,
    name VARCHAR);

In this example, a temporary table “ **emp_table** ” has been created with two columns: “ **id** ” and “ **name** ”.

To verify the table’s creation, the user can execute the “ **SELECT** ” statement:
    
    
    SELECT * FROM emp_table;

The “ **emp_table** ” has been created.

 **Insert Values in Temporary Table**

Let’s learn how to insert values/records into an existing table. For this purpose, users must execute the “ **INSERT INTO** ” statement as follows:
    
    
    INSERT INTO emp_table(Id,name)
    VALUES (23, 'Peter');

In the above statement, the values “ **23** ” and “ **Peter** ” are added to the “ **id** ” and “ **name** ” columns of “ **emp_table** ”.

To extract the data from the temporary table, the user can utilize the “ **SELECT** ” statement, as shown below.
    
    
    SELECT * FROM emp_table;

Output verifies that the desired values have been inserted into the “ **id** ” and “ **name** ” columns of the “emp_table”.

 **Drop Temporary Table in PostgreSQL**

Before dropping any specific table, let’s check the list of existing tables in the database using “\d” command:
    
    
    \d;

Suppose we want to delete the emp_table from the database. For this purpose, the “ **DROP TABLE** ” statement can be used as follows:
    
    
    DROP TABLE emp_table;

Let’s authenticate the removal of temporary tables via the “ **\d** ” statement in PostgreSQL:
    
    
    \d;

The “ **emp_table** ” has been successfully removed from the selected database.

 **Remove Temporary Table via Closing Session**

Another way to drop a temporary table is by closing the current session. For this, a temporary table is created with a “ **CREATE TEMP TABLE** ”:
    
    
    CREATE TEMP TABLE user_data (
    id INT,
    name VARCHAR);

A temporary table named “ **user_data** ” has been created successfully.

By ending the current session, the temporary table will be removed. For this, the command is written below:
    
    
    \q

After executing the above command, Press any key to quit the current session. For verification of the removal of the temporary table, the “ **\d** ” statement is utilized as below:
    
    
    \d;

Users can confirm that the targeted temporary table(i.e., user_data) has been successfully deleted from the database.

 **Conclusion**

In Postgres, the “ **CREATE TEMP TABLE** ” statement is utilized to create the temporary table. Users can execute various commands like “ **SELECT** ”, “ **INSERT** ”, and “ **DROP** ” to perform various functionalities on the selected temporary table. The temporary table will be removed from the database after terminating the current session. This guide has covered all aspects regarding temporary tables in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-temporary-table-in-postgresql/)

---

# PostgreSQL List All Tables

> PostgreSQL List All Tables

PostgreSQL provides a **“\dt”** command to list all the available tables of a database. Postgres offers another useful command named **“\dt+”** that provides some extra/detailed information about the tables, such as table size, access method, etc. In addition to this, Postgres facilitates its user with some built-in schemas, such as **pg_catalog** and **information_schema** that are used to list all the tables.

In this post, you will learn how to list all the available tables using SQL SHELL(psql) or pgAdmin. So, let’s start with the first method.

 **PostgreSQL List All Tables Using SQL SHELL(psql)**

Here are stepwise instructions to list all the tables of a particular database using SQL SHELL:

 **Step #1: Log in to the SQL SHELL**

Firstly, open the SQL SHELL and provide all the necessary details, such as port number, user name, and super user password, as shown in the following snippet:

Hit the “ENTER” button after specifying the appropriate password; consequently, the following interface will appear:

The above snippet indicates that we are successfully connected to the default database, i.e., “postgres”.

 **Step #2: Check Available Databases**

Executing the below-mentioned command will show all the available databases:
    
    
    \l;

The output shows the list of all the available databases.

 **Step #3: Establish a Connection With the Desired Database**

Suppose we want to access the “example” database; for that purpose, we will run the following command:
    
    
    \c example;

The output indicates that we are successfully connected to the **“example”** database.

 **Step #4: List All Tables**

Once you are connected to the desired database, you can run the below command to list all the tables/relations of that particular database:
    
    
    \dt;

Congratulations! You have successfully listed all the relations/tables of the desired database using SQL SHELL.

 **Step #5: List All Tables With Detailed Information**

Execute the below command to get detailed information about each table, such as the table’s size, persistence, etc.
    
    
    \dt+;

This way, you can list all the relations using the psql tool.

 **PostgreSQL List All Tables Using pg_catalog**

Postgres provides a schema named pg_catalog that is used to list all the available tables of a database. Follow the below-listed steps to show/list all the tables using pg_catalog schema:

 **Step #1: Open pgAdmin**

Let’s open the pgAdmin and provide the superuser password as shown below:

Clicking on the OK button will log you into the pgAdmin.

 **Step #2: Open Query Tool**

Right-click on the selected database and select the Query tool:

Clicking on the “Query Tool” will open the query tool where you can execute any query of your choice.

 **Step #3: List Tables Using pg_catalog**

Let’s run the below command to list all the tables using the pg_catalog schema:
    
    
    SELECT *
    FROM pg_catalog.pg_tables;

The output shows that the above query fetched/listed all the tables, including system tables.

 **Step #4: List User-Defined Tables Using pg_catalog**

To retrieve only user-defined tables, execute the below query:
    
    
    SELECT *
    FROM pg_catalog.pg_tables
    WHERE schemaname != 'pg_catalog' AND 
    schemaname != 'information_schema';

The output shows that this time we get only user-defined tables.

 **PostgreSQL List All Tables Using information_schema**

Let’s run the below-given command to get the list of all tables:
    
    
    SELECT * FROM information_schema.tables;

This way, users can get the list of all relations using the information schema.

 **Conclusion**

In Postgres, an SQL command: “\dt”, and built-in schemas: pg_catalog and information_schema, are used to list all the tables of a database. The “\dt” or “\dt+” commands will be executed from the SQL Shell psql, however, you can run the pg_catalog or information_schema from any interface of your choice, such as pgAdmin or psql. This write-up demonstrated different methods to list all the tables in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-list-all-tables/)

---

# How to Alter Role in PostgreSQL

> How to Alter Role in PostgreSQL

PostgreSQL makes life easy for its users which are worried about managing and modifying the roles in databases. It is possible through the “ **ALTER ROLE** ” statement in PostgreSQL. Using the ALTER **ROLE** statement, users can change the name as well as the attributes of roles. Today, we will teach you how to use the “ **ALTER ROLE** ” statement in Postgres.

Let's start this journey with prerequisites.

 **Prerequisites: Check out the Existing Role in PostgreSQL**

In the Postgres database, an existing role is already created whose name is “ **teach_role** ”. To check out the existing role in the PostgreSQL database, run the “ **\du** ” statement as shown below:
    
    
    \du teach_role;

The above statement shows the details about the “ **teach_role** ”:

Now, users can verify that “ **teach_role** ” is placed in the column of “ **Role name** ”.

 **Alter the Existing Role With New Role in PostgreSQL**

Use the “ **ALTER ROLE** ” statement along with the “ **RENAME TO** ” clause to modify the name of an existing role:
    
    
    ALTER ROLE teach_role RENAME TO mentor_role;

In the above statement, “ **teach_role** ” represents the name of the existing role, which is altered with the “ **mentor_role** ” name in the database:

After executing the statement, “ **ALTER ROLE** ” is displayed as output as shown in the above figure.

By executing the “ **\du teach_role** ” statement, the user can verify that “ **teach_role** ” does not exist in the list of roles:

On the other hand, “ **mentor_role** ” can be displayed as the altered role that is located in the column of “ **Role name** ”.

 **Protect Role by ALTER ROLE in PostgreSQL**

PostgreSQL provides the facility to protect the specified role in the database. For this, the “ **ALTER ROLE** ” statement is utilized with the “ **WITH PASSWORD** ” statement as given below.
    
    
    ALTER ROLE mentor_role WITH PASSWORD 'asdf321';

In the above statement, “ **mentor_role** ” is protected with password “ **asdf321** ”:

The message “ **ALTER ROLE** ” is displayed as an output to confirm the protected role.

 **Create Roles and Database by ALTER ROLE in PostgreSQL**

In PostgreSQL, users can create roles as well as databases through the “ **ALTER ROLE** ” statement. The statement is integrated with the “ **CREATEROLE CREATEDB** ” for creating role and database:
    
    
    ALTER ROLE mentor_role CREATEROLE CREATEDB;

The “ **mentor_role** ” has the ability to create a role and database in PostgreSQL:

The output “ **ALTER ROLE** ” verifies that “ **mentor_role** ” is altered with new attributes i.e. Create role, and Create DB:

In the list of existing roles, the user can easily verify that the “ **mentor_role** ” has been altered successfully.

 **Conclusion**

PostgreSQL provides the “ **ALTER ROLE** ” statement to alter the existing role with the new role. Using the **ALTER ROLE** statement, users can change the name as well as the attributes of the existing roles. This guide has expressed the practical implementation of the “ **ALTER ROLE** ” statement along with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-alter-role-in-postgresql/)

---

# How to Use GRANT Statement in PostgreSQL

> In PostgreSQL, users can access and override the privileges/rights of the database objects through the “GRANT” statement.

The “ **GRANT** ” statement is used for assigning privileges to the objects of the database. The database objects contain tablespace, schemas, functions, tables, sequences, etc. The “ **GRANT** ” statement helps us to access or override the particular role in PostgreSQL.

This write-up aims to explain the usage of the Postgres “ **GRANT** ” statement using practical examples. So, let’s begin.

 **Usage of GRANT Privileges in PostgreSQL**

PostgreSQL is a relational DBMS that provides a variety of functionalities to its users. The new user has limited rights to access database objects by default. Therefore, the “ **GRANT** ” statement is utilized to assign a specific role to the selected users. For instance, the syntax of the “ **GRANT** ” statement is mentioned below.

 **Syntax**
    
    
    GRANT priv_list ON object(s) TO role_name;

In the above syntax, the “ **GRANT** ” command specifies the access privileges to the object. The “ **role_name** ” identify the name/role of the user. Moreover, users can give access to one or more than one privileges to objects. The “ **priv_list** ” represents the list of privileges that can be assigned to an object. Here is the list of privileges:

\- INSERT  
\- SELECT  
\- UPDATE  
\- CREATE  
\- DELETE  
\- CONNECT  
\- TRUNCATE  
\- TRIGGER  
\- EXECUTE  
\- REFERENCES

 **Note** : For assigning all privileges to an object, users can utilize the **ALL** keyword in PostgreSQL.

You need to follow the below-given stepwise instructions to understand the **“GRANT”** command in PostgreSQL.

 **Step 1: Create New Database**

Firstly, let’s create a new database on which all modifications will be performed:
    
    
    CREATE DATABASE db_org;

The database named “db_org” has been created successfully.

 **Step 2: Connect Database**

To establish a connection with the “db_org” database, let’s execute the \c command followed by the name of the selected database:
    
    
    \c db_org;

The output shows the connection with the db_org database has been established successfully.

 **Step 3: Create a Role**

In the existing database, a new role named “hr_role” is created along with the “login” attribute:
    
    
    CREATE ROLE hr_role login password 'asa123';

A new role “ **hr_role** ” has been created successfully.

 **Step 4: Create a Table**

A new table named “ **emp_tab** ” is created using the “ **CREATE TABLE** ” statement:
    
    
    CREATE TABLE emp_tab (
    f_name varchar(100) not null, 
    l_name varchar(100) not null);

In the above figure, a table “ **emp_tab** ” with two columns, has been created in the “ **db_org** ” database.

 **Step 5: Insert Records Into emp_tab**

Let’s login as “hr_role”:

Now, execute the insert query to place some new records into the emp_tab table:
    
    
    INSERT INTO emp_tab (f_name, l_name) 
    VALUES('peter', 'ben');

Since we are logged in as hr_role, so, we encountered an error “permission denied”. It proves that the hr_role doesn’t have permission to insert the data into a specific table.

 **Step 6: GRANT Privileges**

To access the privileges of object “ **emp_table** ” to “ **hr_role** ”, the “ **GRANT** ” statement is employed as shown in the below statement:
    
    
    GRANT SELECT ON emp_tab TO hr_role;

The “ **GRANT** ” message in the output verifies that privileges of “ **emp_tab** ” have been given to “ **hr_role** ” in PostgreSQL.

 **Step 7: Insert Values in Existing Table**

In this step, the “INSERT” statement is utilized to insert values “ **peter** ” and “ **ben** ” in the “ **f_name** ” and “ **l_name** ” columns of the “ **emp_tab** ” table:
    
    
    INSERT INTO emp_tab(f_name, l_name) 
    VALUES('peter', 'ben');

The output “ **INSERT 0 1** ” confirms that one row has been successfully stored into the “ **emp_tab** ”.

 **Step 8: Verify Table’s Data**

The user can confirm the table’s data through the “ **SELECT** ” statement:
    
    
    SELECT * FROM emp_tab;

Great Work! You have experienced the usage of the “ **GRANT** ” statement to acquire the privilege of objects.

 **Conclusion**

In PostgreSQL, users can access and override the privilege of database objects through the “ **GRANT** ” statement. This statement is used for assigning privileges to the database objects such as tablespace, schemas, functions, tables, sequences, etc. This post has explained all the essential steps to use the **GRANT** statement in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-grant-statement-in-postgresql/)

---

# How to Use REVOKE Privileges in PostgreSQL

> In PostgreSQL, the “REVOKE” statement is quite helpful in revoking the granted privileges from single or multiple roles.

The “ **REVOKE** ” statement revokes granted privileges from single or multiple roles in the PostgreSQL database. The granted privileges represent those rights that have already been granted to database objects. These objects include tables, schemas, indexes, functions, and many more. Today, we will guide you on how to use the “ **REVOKE** ” statement in PostgreSQL.

 **Usage of REVOKE Privileges in PostgreSQL**

Users can use the “ **REVOKE** ” statement to remove the specific privilege from the existing role in the database. It is possible by specifying the **REVOKE** statement followed by the user's name from whom you want to revoke the privileges. For instance, the syntax is provided below.

 **Syntax**
    
    
    REVOKE priv_list ON obj FROM role_name;

The description of parameters is illustrated as follows:

The **priv_list** contains the number of privileges that the user wants to revoke. The **obj** specifies the database objects, such as schemas, tables, indexes, functions, etc. The **role_name** represents the name of the role from which the privileges are being revoked.

The **priv_list** may include:

\- INSERT  
\- SELECT  
\- UPDATE  
\- CREATE  
\- DELETE  
\- CONNECT  
\- TRUNCATE  
\- TRIGGER  
\- EXECUTE  
\- REFERENCES

 **Note** : You can utilize **ALL** keyword for revoking all privileges on database objects.

This tutorial comprises step-by-step instructions for revoking privileges in PostgreSQL.

 **Step 1: Create a New Database**

Let’s create a new database named db_std using the “ **CREATE DATABASE** ” statement. In this database, various operations will be performed regarding privileges:
    
    
    CREATE DATABASE db_std;

By executing the above statement, the database “ **db_std** ” has been successfully created. Now user can switch from the default database “postgres” to “ **db_std** ”.

 **Step 2: Establish Connection with Database**

After creating a database, establish a connection by executing the “ **\c** ” statement followed by the name of the desired database:
    
    
    \c db_std;

The output authenticates that we are successfully connected to the “ **db_std** ” database.

 **Step 3: Creating a New Role**

Let’s create a new role with the login attribute:
    
    
    CREATE ROLE tech_role login password 'zar422';

User can confirm through the output message that “ **tech_role** ” has been successfully created.

 **Step 4: Create a Table**

In this step, a table “ **tech_tab** ” is created through the “ **CREATE TABLE** ” statement:
    
    
    CREATE TABLE tech_tab(
    f_name varchar(100) not null, 
    l_name varchar(100) not null);

The table “ **tech_tab** ” has been created with two columns: “ **f_name** ” and “ **l_name** ”.

 **Step 5: GRANT Privileges**

The “ **GRANT** ” statement is utilized to assign the privilege of table “ **tech_tab** ” to the selected role named “ **tech_role** ”. You can override the privileges through the “ **GRANT** ” statement in PostgreSQL.
    
    
    GRANT SELECT ON tech_tab TO tech_role;

The “ **GRANT** ” message in the output confirms that privilege has been successfully granted to the particular role.

 **Step 6: REVOKE Privileges**

PostgreSQL offers the “ **REVOKE** ” statement to remove the privilege from a specific role:
    
    
    REVOKE SELECT ON tech_tab FROM tech_role;

In the above statement, privileges of “ **tech_role** ” have been revoked, which authenticates through the “ **REVOKE** ” message in the output.

 **Step 6: Authenticate the Working of REVOKE Statement**

Login as a tech_role:

Now perform any operation, like insert, update, delete, etc., on the “tech_tab” table. Let’s say the user wants to insert a new row into the tech_tab. To do that, execute the INSERT command as follows:
    
    
    INSERT INTO tech_tab(f_name, l_name)
    VALUES(‘tim’, ‘stoke’);

The output shows that an error occurred when we tried to insert the data into the tech_tab table. It proves that the REVOKE statement has successfully removed the privileges.

That’s it! You have learned the practical implementation of revoke privileges in PostgreSQL.

 **Conclusion**

In PostgreSQL, the “ **REVOKE** ” statement is quite helpful in revoking the granted privileges from single or multiple roles. The priv_list may include: INSERT, SELECT, UPDATE, CREATE, DELETE, CONNECT, TRUNCATE, TRIGGER, EXECUTE, and REFERENCES. This tutorial has provided the step-by-step procedure to revoke the rights of the existing role in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-revoke-privileges-in-postgresql/)

---

# How to Drop Roles in PostgreSQL

> How to Drop Roles in PostgreSQL

Dropping a role is a crucial feature in PostgreSQL to remove all the privileges in the database. It is required when the user does not need a specific role in the future. For this purpose, the “ **DROP ROLE** ” statement is utilized with the role name to delete a particular role in PostgreSQL.

This guide comprises various steps to explain the usage of the “ **DROP ROLE** ” statement in PostgreSQL. So, let’s begin.

 **Prerequisite: Existing Roles in PostgreSQL**

PostgreSQL provides an interesting statement named “\du” that displays all the existing roles with attributes in the database:
    
    
    \du;

The above snippet shows all the available roles within the “postgres” database.

 **Drop Existing Role in PostgreSQL**

In PostgreSQL, the “ **DROP ROLE** ” statement is utilized to drop an existing role. For this purpose, specify the DROP ROLE statement followed by the role's name:
    
    
    DROP ROLE mentor_role;

On successful execution of the above statement, the “ **mentor_role** ” will be dropped from the database:

A message “ **DROP ROLE** ” is displayed as an output which confirms that the mentor_role has been dropped from the database.

 **ERROR: Specific Role Does Not Exist in PostgreSQL**

The **" DROP ROLE"** statement in PostgreSQL displays an error if a role doesn’t exist in the database:
    
    
    DROP ROLE simple_role;

In the above snippet, we utilized the DROP ROLE statement to drop a role named “ **simple_role** ”:

The output verifies that the specified role doesn’t exist in the database.

 **Drop Dependency of Role in PostgreSQL**

By using the **" DROP OWNED"** statement, a dependency role can be dropped in a Postgres database.

Before dropping any dependencies, the user can verify the list of roles in the existing database via the “ **\du** ” statement:
    
    
    \du;

We will try to drop the “ **hr_role** ” using the below statement:
    
    
    DROP ROLE hr_role;

An error occurred stating that the selected role can’t be dropped because some other objects depend on the selected role. To avoid such an error, the “ **DROP OWNED** ” statement can be used:
    
    
    DROP OWNED by hr_role;

Now the user can execute the “ **DROP ROLE** ” statement to drop any specific role:
    
    
    DROP ROLE hr_role;

The output shows that the hr_role has been dropped successfully. Run the below-given command to verify if the selected role has been dropped or not:
    
    
    \du ;

The “ **\du** ” statement displays the number of existing roles in the database:

Output authenticates that the “ **hr_role** ” has been successfully dropped from the targeted database.

 **Conclusion**

In PostgreSQL, the “ **DROP ROLE** ” statement is used to drop an existing role with its attributes. In the case of dependent objects, the **DROP OWNED** statement is used to drop all the objects. In this write-up, the "DROP ROLE" and "DROP OWNED" statements are demonstrated using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-roles-in-postgresql/)

---

# How to Show Users in PostgreSQL

> How to Show Users in PostgreSQL

In PostgreSQL, each user has their own specific role in managing operations in the database. In certain situations, it is difficult to find the user’s roles and privileges. To deal with such situations, PostgreSQL provides the “\du” and “\du+” statements that are used to show the list of users along with their attributes and descriptions.

This write-up will teach you how to show users in Postgres via the below-listed methods:

  * Method 1: Show Users in PostgreSQL via SQL Shell
  * Method 2: Show Users in PostgreSQL via pg Admin



Let's begin with the first method.

 **Method 1: Show Users in PostgreSQL via SQL Shell**

Open the SQL, provide the login information, and to display the list of users, execute the statement provided below:
    
    
    \du;

The above “ **\du** ” statement is utilized to show the list of all the users/roles in the selected database:

From the output, users can clearly notice that the “\du” command retrieves the list of users. For displaying the description of the role, the below statement can be utilized:
    
    
    \du+;

Executing the above statement will display additional information about the user’s roles:

This way, you can get the list of users with or without a description using the SQL SHELL.

 **Method 2: Show Users in PostgreSQL via pgAdmin**

The pgAdmin facilitates easiness to the users through the graphical representation. To show the list of users on the specified database, select the “ **Query Tool** ” option as given below.

For this, a “ **Query** ” window is displayed on which the user can execute any statement. Let’s run the below-given query to show the list of users in Postgres via pgAdmin:
    
    
    SELECT * FROM pg_catalog.pg_user;

The “ **SELECT** ” statement is utilized to get all the user information from the database through “ **pg_catolog.pg_user** ”:

The above query retrieved a result set having eight users whose names are given in the “ **usename** ” column. Here are the details of all the columns:

\- **usename** : it contains the name of users (postgres is the default database of PostgreSQL).  
\- **usesysid** : specify the unique identification of users.  
\- **usecreatedb** : identify the possibility of creating a database through boolean variables (true or false).  
\- **usesuper** : represent that the user is a superuser or not via a boolean value.  
\- **userepl** : refers that the user can initialize replication or not via the boolean value.  
\- **passwd** : user can specify the password in text format.

It is all about the guidelines of PostgreSQL.

 **Conclusion**

Run the **“\du”** and **“\du+”** statements from the SQL Shell(psql) to show the list of users along with their attributes and descriptions. Or you can use the “ **pg_catolg.pg_user** ” with the collaboration of the “SELECT” statement to show the users via pgAdmin. This article has explained all essential methods to show the detail of users in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-show-users-in-postgresql/)

---

# How to Drop Schema in PostgreSQL

> How to Drop Schema in PostgreSQL: an educational article from Command Prompt

In PostgreSQL, a schema is a namespace that offers a variety of objects, such as **indexes, tables, views, functions, datatypes, operators,** and **sequences**. In Postgres, users can create a schema, drop a schema, and alter a schema. A schema can be dropped in Postgres by using the **DROP SCHEMA** statement. When you drop a schema, all the objects present in it will also be dropped.

The purpose of this guide is to demonstrate the usage of the “ **DROP SCHEMA** ” statement in PostgreSQL:

  * Method 1: Using SQL Shell Drop a Schema in PostgreSQL
  * Method 2: Using pgAdmin Drop a Schema in PostgreSQL
  * Method 3: DROP SCHEMA Statement to Drop a Schema Via pgAdmin



Let's discuss the first method.

 **Method 1: Using SQL Shell Drop a Schema in PostgreSQL**

The below snippet illustrates the syntax of the DROP SCHEMA statement:
    
    
    DROP SCHEMA schema_name;

In the above syntax, the “ **schema_name** ” specifies the name of the existing schema in the database.

Let’s utilize the “ **\dn** ” command to display the list of existing schemas in the selected database:
    
    
    \dn;

To drop an existing schema, execute the “ **DROP SCHEMA** ” statement by specifying the schema's name such as “ **emp_data** ”:
    
    
    DROP SCHEMA emp_data;

The command mentioned above will drop the “emp_data” schema from the “postgres” database:

The output clarifies that the selected schema, i.e., “ **emp_data** ”, has been drooped successfully.

 **Method 2: Using pgAdmin Drop a Schema in PostgreSQL**

To drop a schema via pgAdmin, firstly, you have to right-click on the targeted schema; consequently, a pop-up menu will appear, select the “ **Delete/Drop** ” option:

It navigates you to a new pop-up window stating:

Select the **“Yes”** button to drop the targeted schema.

 **Method 3: DROP SCHEMA Statement to Drop a Schema Via pgAdmin**

The pgAdmin provides the “ **Query Tool** ” to write and execute statements in the GUI environment. For instance, the “ **DROP SCHEMA** ” statement can be executed via pgAdmin for deleting an existing schema.

To access the “ **Query Tool** ”, press the right-click on the existing schema’s name, such as “ **std_info** ”, and click on the query tool option:

Once the query tool is opened, you can execute any statement of your choice to achieve the desired functionality:
    
    
    DROP SCHEMA std_info;

In the above statement, “ **std_info** ” is a schema to be dropped:

The “ **DROP SCHEMA** ” message in the output shows that “ **std_info** ” has been dropped successfully. Now, right-click on the targeted database, i.e., “ **std_info** ”, and hit the “ **Refresh** ” button to refresh/reload the database objects:

The output shows that the std_info schema has been dropped from the db_store database.

Great Work! You have experienced the “ **DROP SCHEMA** ” statement in PostgreSQL.

 **Conclusion**

Use the **DROP SCHEMA** statement to drop/remove a specific schema from a database. In PostgreSQL, a schema is a collection of several objects, so when you drop a schema, all the objects present in it will also be dropped. This write-up experienced several examples to explain all the essential methods of dropping a schema in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-schema-in-postgresql/)

---

# PostgreSQL ALTER SCHEMA

> PostgreSQL ALTER SCHEMA: an educational article from Command Prompt

PostgreSQL offers an “ **ALTER SCHEMA** ” statement that is used to modify the schema’s definition, such as altering the schema’s owner, renaming a schema, and so on. In order to modify the schema’s definition, you must own that schema.

This write-up will teach you how to change the schema’s owner and how to rename a schema in PostgreSQL using the **ALTER SCHEMA** statement. So, let’s start.

 **How to Change Schema’s Owner Using ALTER SCHEMA Statement in Postgres?**

In PostgreSQL, the ALTER SCHEMA statement is used with the collaboration of the OWNER TO clause to change the schema’s owner. To do so, follow the below syntax:
    
    
    ALTER SCHEMA schema_name
    OWNER TO new_owner;

In the above syntax, the “ **schema_name** ” represents the schema to be altered while “ **new_owner** ” represents the name of the new owner.

The below-listed steps will help you understand the working of ALTER SCHEMA statement:

 **Step 1: Launch SQL Shell**

Firstly, open the SQL Shell(psql) and provide the necessary details like user name, password, etc.:

Hit the “enter” button to proceed further.

 **Step 2: Show Available Schemas**

Run the “\dn” command to get the list of available schemas:
    
    
    \dn;

Output shows the schema's names and their owners. Alternatively, you can run the below command to check the schema’s owner:
    
    
    SELECT * FROM pg_catalog.pg_namespace;

 **Step 3: Show Available Users**

Let’s run the “\du” command to see the available users:
    
    
    \du

 **Step 4: Change Owner**

Suppose we want to change the owner of the “ **employee_details1** ” schema from “ **postgres** ” to “ **command_prompt** ”. To do so, we will execute the following command:
    
    
    ALTER SCHEMA employee_details1 OWNER TO command_prompt;

The “ **ALTER SCHEMA** ” message in the output proves that the selected schema has been altered successfully.

 **Step 5: Verify The Owner**

Let’s run the “\dn” command to verify the working of “ **ALTER TABLE** ” and “ **OWNER TO** ” statements:
    
    
    \dn

The output shows that the schema owner has been successfully changed from “ **postgres** ” to “ **command_prompt** ”.

Alternatively, you can verify the schema’s owner via the following command:
    
    
    SELECT * FROM pg_catalog.pg_namespace;

The output authenticates the working of the **ALTER SCHEMA** statement.

 **How to Rename a Schema Using ALTER SCHEMA Statement in Postgres?**

In PostgreSQL, the **ALTER SCHEMA** statement is used along with the **RENAME TO** clause to modify the schema’s name. To do so, follow the below syntax:
    
    
    ALTER SCHEMA schema_name 
    RENAME TO new_name;

The “ **schema_name** ” is the schema to be altered while “ **new_name** ” represents the new/modified name of the schema.

 **Step 1: Check Available Schemas**

The below command will show the list of available schemas:
    
    
    \dn;

Let’s rename the “ **employee_details1** ” schema.

 **Step 2: Rename Schema**

Let’s use the following command to rename the “ **employee_details1** ” schema to “ **emp_info** ”:
    
    
    ALTER SCHEMA employee_details1 RENAME TO emp_info;

The “ALTER SCHEMA” message proves that the targeted schema has been altered successfully.

 **Step 3: Verify Schema Name**

Let’s run the below command to verify the modified schema’s name:
    
    
    \dn;

The output verified that the selected schema had been renamed successfully.

 **Conclusion**

PostgreSQL offers an “ **ALTER SCHEMA** ” statement that is used to modify the schema’s definition, such as altering the schema’s owner, renaming a schema, and so on. Use the **ALTER SCHEMA** statement with the collaboration of the **OWNER TO** clause to change the schema’s owner. Use **ALTER SCHEMA** statement along with the **RENAME TO** clause to rename the schema’s name. This article explained the working of **ALTER SCHEMA** statements using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-alter-schema/)

---

# How to Rename a Schema in PostgreSQL

> How to Rename a Schema in PostgreSQL: educational article from Command Prompt

PostgreSQL offers a bundle of statements to work with the schemas. These statements may include “ **CREATE** ”, “ **DROP** ”, and “ **ALTER** ”. The “ **ALTER SCHEMA** ” statement is used to modify the schema’s definition, such as altering the schema’s owner, renaming a schema, and so on.

The objective of this post is to explain all the possible methods to rename a schema in PostgreSQL. In this write-up, we will demonstrate how to rename a schema in Postgres using the following methods:

  * Method 1: How to Rename a Schema Using SQL Shell?
  * Method 2: How to Rename a Schema Using pgAdmin?



Let's start with the first method.

 **Method 1: How to Rename a Schema Using SQL Shell?**

The SQL Shell supports the command line interface on which the user can run and execute the statements. For instance, the “ **ALTER SCHEMA** ” statement can be used with the RENAME TO clause to rename a particular schema in PostgreSQL:
    
    
    ALTER SCHEMA schema_name 
    RENAME TO new_name;

In the above syntax, “ **schema_name** ” identifies the name of the existing schema in the database. While the “ **new_name** ” refers to the altered/modified name of the schema.

 **Step #1: List Schemas**

Firstly, open the SQL Shell, provide the required details and execute the “ **\dn** ” command to see the list of available schemas:
    
    
    \dn;

The output shows that there are three schemas in the “postgres” database.

 **Step #2: Rename Schema**

Suppose we want to rename the “employee_info” schema from emp_info to employee_details. To do that, we will execute the “ **ALTER SCHEMA** ” statement with the collaboration of the “ **RENAME TO** ” clause as follows:
    
    
    ALTER SCHEMA employee_info 
    RENAME TO employee_details;

The output indicates that the employee_info schema has been altered successfully.

 **Step #3: Verify Schema**

Let’s execute the “\dn” command one more time to verify that if the selected schema has been renamed or not:
    
    
    \dn;

The output proves that the employee_info schema has been renamed to employee_details.

 **Method 2: How to Rename a Schema Using pgAdmin?**

You can execute the same ALTER SCHEMA command with the collaboration of RENAME TO statement in the pgAdmin’s query tool to rename a particular schema. To open the Query Tool, right click on the targeted schema and choose the “ **Query Tool** ” option from the dropdown list:

Clinking on the Query Tool will open the desired tool where you can execute any query of your choice.

 **Step #2: Rename Schema**

Let’s execute the “ **ALTER SCHEMA** ” statement with the help of **“RENAME TO”** statement to rename the **“example”** schema to **“exp_schema”** :
    
    
    ALTER SCHEMA example
    RENAME TO exp_schema;

The output shows that the selected schema has been altered successfully.

 **Step #3: Verify Schema**

On refreshing the Schemas tab, the users can verify that a schema named “ **exp_schema** ” is located on the left side of the window:

The output verifies that the example schema has been renamed to exp_schema. This is how you can rename a particular schema through SQL SHELL or pgAdmin.

 **Conclusion**

In PostgreSQL, the **“ALTER SCHEMA”** statement is used with the collaboration of the **“RENAME TO”** statement to rename a particular schema. This post explained how to rename a particular schema using SQL SHELL(psql) or pgAdmin.

---
[View this page online](https://www.commandprompt.com/education/how-to-rename-a-schema-in-postgresql/)

---

# How to Create Schema in PostgreSQL

> How to Create Schema in PostgreSQL from Command Prompt

Schema is basically a namespace that offers a variety of objects, including **indexes** , **tables** , **views** , **functions** , **datatypes** , **operators,** and **sequences.** For these objects, the statement “ **CREATE SCHEMA** ” is utilized for creating a new schema in the PostgreSQL database. Furthermore, users can modify objects in the existing schema.

This article demonstrates how to use the “ **CREATE SCHEMA** ” statement in different interfaces to create the schema in PostgreSQL. The content that illustrates this statement is as follows.

  * How to Create Schema in PostgreSQL?
  * Method 1: Create Schema in PostgreSQL via pgAdmin 4
  * Method 2: Create Schema in PostgreSQL via SQL Shell (psql)
  * Example: Create a Table in Schema



Let's start the journey with PostgreSQL.

 **How to Create Schema in PostgreSQL?**

Follow one of the below-given syntaxes to create a schema in Postgres:
    
    
    CREATE SCHEMA schema_name;

Or
    
    
    CREATE SCHEMA [IF NOT EXISTS] schema_name;

 **Parameters**

\- **CREATE SCHEMA:** It is a statement utilized for creating a new schema into the database.  
\- **schema_name:** It defines the schema’s name in the database.  
\- **[IF NOT EXIST]:** It is an optional parameter that checks the occurrence of an existing schema. By using it, a notice will be displayed except for errors.

 **Method 1: Create Schema in PostgreSQL via pgAdmin 4**

The pgAdmin 4 is the Graphical User Interface (GUI) that allows the users to perform various tasks like creating a database, schema, table, etc.

Follow the below instructions to learn how to create a schema using pgAdmin 4:

\- A database **“db_store”,** is already created in the **“Databases”** section.

\- Right-Click on the selected database, hover over the **“Create”** option, and then click on the “schema” as shown below:

Clicking on the “Schema” will open a new pop-up window in which the user can specify the schema’s name, such as **“std_info”,** as shown below:

Hit the **“Save”** button to store the schema name in the targeted database:

Finally, the schema **“std_info”** has been successfully created in the desired database.

 **Method 2: Create Schema in PostgreSQL via SQL Shell (psql)**

Open the SQL SHELL, specify the necessary details and run the below command to create a schema named emp_data:
    
    
    CREATE SCHEMA emp_data;

Executing the above command will create the **“emp_data”** schema into the “postgres” database:

The **“CREATE SCHEMA”** message shows that schema **“emp_data”** has been successfully created using SQL Shell. In psql, the users can execute the **“\dn”** command to get the list of available schemas:
    
    
    \dn;

Finally, the **“emp_data”** can be verified in the first place in the list of available schemas.

 **Example: Create a Table in Existing Schema**

Once a schema is created, the user can create functions, tables, and indexes in that schema. Let's carry out an example to create a table in the schema using pgadmin 4. For this purpose, select the **“Query Tool”** by clicking the right button on the **“std_info”** schema as shown below:

In Query Tool, the **“CREATE TABLE”** command is executed as follows:
    
    
    CREATE TABLE std1(
    name Text,
    age Integer);

In this example, a table named **“std1”** having two columns **“name”** and **“age”** is created using the **“CREATE TABLE”** command **:**

Users can verify a message **“CREATE TABLE”** in the **“Messages”** window. Now, execute the **“SELECT”** command to get the table’s structure:
    
    
    SELECT * FROM std1;

Finally, the user can confirm that a table **“std1”** with two columns, **“name”** and **“age”** has been created.

 **Conclusion**

PostgreSQL offers the “ **CREATE SCHEMA** ” statement to create a schema using **“SQL Shell”** and **“pgAdmin 4”** interfaces. In Postgres, a schema is a namespace that offers a variety of objects, including indexes, tables, views, functions, datatypes, operators, and sequences. Once a schema is created, the user can create a table, function, index, etc. within that schema. This article demonstrates all possible methods to create a schema in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-schema-in-postgresql/)

---

# How to Create Roles in PostgreSQL

> In PostgreSQL, the CREATE ROLE statement is used with different role attributes to create a role with specific privileges such as SUPERUSER, CONNECTION LIMIT, …

In PostgreSQL, a role is an important entity that has different privileges to perform operations in a database. For instance, you can create multiple roles to perform multiple operations. Each role has its own rights according to its specifications.

Today, we will show you how to use the “ **CREATE ROLE** ” statement along with practical examples in PostgreSQL.

  * Method 1: Create a Simple User Role in PostgreSQL
  * Method 2: Create a Role With Login Attribute in PostgreSQL
  * Method 3: Create a Superuser Role in PostgreSQL
  * Method 4: Create a Role With Validity in PostgreSQL
  * Method 5: Create a Role That can Create a Database in Postgres
  * Method 6: Create a Role for Connection Limit in PostgreSQL



So, let’s begin!

 **Method 1: Create a Simple User Role in PostgreSQL**

In the PostgreSQL database, users can create a new role with the “ **CREATE ROLE** ” statement:
    
    
    CREATE ROLE std_role;

The output shows that a role named **“std_role”** has been created successfully. Execute the **“\du”** command to see the available roles:
    
    
    \du;

The output shows that the std_role has been created successfully; however, from the output, it is clear that the “std_role” can’t log in.

 **Method 2: Create a Role With Login Attribute in PostgreSQL**

To assign the login privileges to the std_role, you must use the LOGIN attribute:
    
    
    CREATE ROLE std_role LOGIN PASSWORD 'ABC123';

Let’s run the \du command to verify the role’s creation:
    
    
    \du;

This way, users can create a role with a login attribute.

 **Method 3: Create a Superuser Role in PostgreSQL**

To create a superuser role in PostgreSQL, write down the below statement:
    
    
    CREATE ROLE teacher_role SUPERUSER LOGIN PASSWORD 'xyz321';

Let’s verify the role’s creation using “\du” command:
    
    
    \du;

The output clarifies that a new role named “ **teacher_role** ” has been created as a superuser.

 **Method 4: Create Role With Validity Duration in PostgreSQL**

Do you wanna create a role whose password should expire after a specified period of time? If yes! Then you can utilize the “ **VALID UNTIL** ” attribute along with the CREATE ROLE statement as follows:
    
    
    CREATE ROLE submit_assignment
    LOGIN PASSWORD 'pas321'
    VALID UNTIL '2022-12-01';

Let’s run the “\du” command to verify the role creation:
    
    
    \du;

The output proves that the role “submit_assigment” has been successfully created with the VALID UNTIL attribute.

 **Method 5: Creating a Role That can Create a Database in Postgres**

PostgreSQL provides a facility to specify the role with database creation privileges. For this purpose, execute the “ **CREATE ROLE** ” command as follows:
    
    
    CREATE ROLE teach_role
    CREATEDB
    LOGIN PASSWORD 'ABCXYZ';

A new role named “ **teach_role** ” has been created successfully. Execute the “\du” command to verify the role creation:
    
    
    \du

The output clarifies that the teach_role has been created with the create DB privileges.

 **Method 6: Create a Role for Connection Limit in PostgreSQL**

For concurrent connections, use the **“CREATE ROLE”** statement and specify the number of connections via the **“CONNECTION LIMIT”** attribute.
    
    
    CREATE ROLE emp_limit
    LOGIN
    PASSWORD 'ABCXYZ'
    CONNECTION LIMIT 200;

The CREATE ROLE message indicates that a new role has been created successfully. Run the below command to verify the role’s creation:
    
    
    \du

The output shows that a new role with the specified connection limit has been created successfully.

That’s it! You have experienced all possible use cases to create roles in PostgreSQL via the “ **CREATE ROLE** ” statement.

 **Conclusion**

In PostgreSQL, the **CREATE ROLE** statement is used with different role attributes to create a role with specific privileges such as **SUPERUSER** , **LOGIN** , **CONNECTION LIMIT** , etc. For instance, the SUPERUSER attribute grants all the privileges to a user, the **CREATEDB** attribute grants the database creation privileges to the user, etc. This write-up explained various use cases of the **CREATE ROLE** statements via practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-roles-in-postgresql/)

---

# PostgreSQL INSERT IF NOT EXISTS

> Postgres doesn’t offer the “IF NOT EXISTS” option for the INSERT query. Alternatively, you can use the subquery to check the existence of a specific record.

Inserting data into tables is a very common operation in any database management system. In PostgreSQL, the **INSERT INTO** statement is used to insert the data into any specific table. Using the **INSERT** statement, users can insert as many records as they want using the comma-separated syntax.

But what if a user wants to insert only those records that do not already exist in the selected table? How does Postgres deal with such situations? Well! In PostgreSQL, the INSERT statement doesn’t support the **“IF NOT EXISTS”** option. So alternatively, you can use the subquery to check the existence of a specific record in a table. So, let’s start!

 **How to Use Subquery to Insert Non-existing Values in a Table?**

The below syntax will guide you on how to achieve the functionality of the **“IF NOT EXISTS”** option using a subquery:
    
    
    INSERT INTO tab_name(col_list)
    SELECT val_list
    WHERE
    NOT EXISTS (
    SELECT col_name FROM tab_name WHERE condition
    );

In the above syntax, the NOT EXIST operator/clause is used within the WHERE Clause, which will check the existence of a record. If the record to be inserted doesn’t exist in the selected table, then the sub-query will retrieve “True”. In such a case, the INSERT INTO statement will execute, and the non-existing record will be inserted into the specified table.

 **Example 1: Creating a Sample Table**

Let’s create a sample table via CREATE TABLE command:
    
    
    CREATE TABLE emp_tab(
    emp_id INT,
    emp_name TEXT,
    emp_email VARCHAR(30)
    );

In this example, we created a table named emp_tab that consists of three columns. The emp_id will take a numeric value, while emp_name and emp_email will take character values:

The resultant message verifies the working of CREATE TABLE statements. You can verify the table’s creation via the SELECT command:
    
    
    SELECT * FROM emp_tab;

The emp_tab has been created successfully.

 **Example 2: Inserting Some Records**

Let’s insert some data into the emp_tab using the INSERT query:
    
    
    INSERT INTO emp_tab(emp_id, emp_name, emp_email)
    VALUES (1, 'Joseph', 'joseph@abc.com'),
    (2, 'Tim', 'tim@abc.com'),
    (3, 'Anna', 'anna@abc.com'),
    (4, 'Henry', 'henry@abc.com');

The output proves that four records have been inserted into the **“emp_tab”** successfully. You can verify the newly inserted data using the below-mentioned command:
    
    
    SELECT * FROM emp_tab;

The output shows that four records have been inserted into the emp_tab successfully.

 **Example 3: Inserting Non-Existing Records**

Let’s execute the below query to insert non-existing records in the emp_tab:
    
    
    INSERT INTO emp_tab(emp_id, emp_name, emp_email)
    SELECT 3, 'Seth', 'seth@abc.com'
    WHERE
    NOT EXISTS (
    SELECT emp_id FROM emp_tab WHERE emp_id = 3
    );

Let’s run the SELECT statement to see if the selected record has been inserted into the emp_tab or not:
    
    
    SELECT * FROM emp_tab;

The output proves that the “emp_id = 3” already exists in the “emp_tab”, so the INSERT command didn’t insert that record into the targeted table. Let’s execute the INSERT command one more time to insert a non-existing record into the “emp_tab” table:
    
    
    INSERT INTO emp_tab(emp_id, emp_name, emp_email)
    SELECT 5, 'Seth', 'seth@abc.com'
    WHERE
    NOT EXISTS (
    SELECT emp_id FROM emp_tab WHERE emp_id = 5
    );

The output proves that the non-existing record has been inserted into the emp_tab successfully. You can verify the inserted that using the following command:
    
    
    SELECT * FROM emp_tab;

This is how you can achieve the functionality of **INSERT IF NOT EXISTS** in PostgreSQL.

 **Conclusion**

PostgreSQL doesn’t offer the **“IF NOT EXISTS”** option for the **INSERT INTO** statement. So alternatively, you can use the **subquery** to check the existence of a specific record in a table. For this purpose, use the **NOT EXISTS** option within the **WHERE** Clause. If the given record doesn’t exist in the selected table, then the sub-query will retrieve “ **True** ”. In such a case, the **INSERT INTO** statement will execute, and the non-existing record will be inserted into the specified table. This blog post explained how to insert non-existing records into a table using the subquery.

---
[View this page online](https://www.commandprompt.com/education/postgresql-insert-if-not-exists/)

---

# PostgreSQL TEXT VS VARCHAR Data Types

> In Postgres, the TEXT data type accepts unlimited characters, while the behavior of the VARCHAR data type depends on its length parameter.

PostgreSQL provides various character data types to store character data, such as **TEXT** , **VARCHAR** , etc. But the question is, why is it so? If we have a **TEXT** data type, then what is the need for the **VARCHAR** data type, and vice versa? If you are stuck in the same debate, then nothing to worry about. This write-up is going to resolve all your queries regarding **TEXT vs. VARCHAR.**

This write-up will consider several examples to demonstrate the difference between TEXT and VARCHAR data types. So, let’s start!

 **PostgreSQL TEXT VS VARCHAR Data Types**

The below-listed points will assist the users in understanding the difference between TEXT and VARCHAR data types:

  * In PostgreSQL, TEXT and VARCHAR data types store the character data. As per PostgreSQL's official documentation, both TEXT and VARCHAR data types are the same regarding performance parameters.
  * However, the major difference between these data types is the character’s “ **limit** ”. For instance, using the VARCHAR data type, you can specify the limit/length of the VARCHAR column.
  * For example, VARCHAR(100) will store only a hundred characters. A column created with the VARCHAR(100) will throw an error if you try to enter more than a hundred characters. While using the TEXT data type, you can not specify the maximum limit/length; instead, it is used to create the strings/sequence of unlimited length.
  * Another notable difference between these two data types is padding and spaces. While working with the VARCHAR data type, the padding and spaces get truncated during execution. On the other hand, if you are working with the TEXT data type, then padding and spaces wouldn’t be truncated even during the execution/storing.



Let’s understand the difference between **TEXT** and **VARCHAR** data types via practical examples.

 **Example 1: Understanding TEXT and VARCHAR Data Types?**

Let’s create a table named “example_greetings” with two columns: “ **var_txt** ” and “ **var_varchar** ”:
    
    
    CREATE TABLE example_greetings(
    var_txt TEXT,
    var_varchar VARCHAR(10)
    );

The table named “example_greetings” has been created successfully.

 **Example 2: How Do I Insert TEXT and VARCHAR Data Into a Table in Postgres?**

Let’s insert the following data into the example_greetings table via the INSERT INTO command:
    
    
    INSERT INTO example_greetings(var_text, var_varchar)
    VALUES
    ('Welcome to commmandprompt.com',
    'The Best Platform For Educational Tutorials'
    );

The “var_varchar” column exceeded the character limit; therefore, Postgres throws an error. Let’s execute the INSERT INTO command one more time to see how it works if the user enters a value within the specified limit/length:
    
    
    INSERT INTO example_greetings(var_txt, var_varchar)
    VALUES
    ('Welcome to commmandprompt.com',
    'PostgreSQL'
    );

This time, one record has been successfully inserted into the example_greetings table. You can verify the inserted data via the SELECT query:
    
    
    SELECT * FROM example_greetings;

If you didn’t specify the length parameter “n” within the VARCHAR data type, then the VARCHAR data type can accept the unlimited number of characters(same as the TEXT data type).

That’s it from this Postgres blog.

 **Conclusion**

In PostgreSQL, TEXT and VARCHAR data types store the character data. As per PostgreSQL's official documentation, both TEXT and VARCHAR data types are the same regarding performance parameters. However, the major difference between these data types is the character’s “ **limit** ”. For instance, using the VARCHAR data type, you can specify the limit/length of the VARCHAR column. While the TEXT data type doesn’t accept any length parameter, it can store unlimited characters. This blog post presented a comparative analysis of TEXT and VARCHAR data types through practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-text-vs-varchar-data-types/)

---

# PostgreSQL Character Data Types: CHAR, VARCHAR, and TEXT

> PostgreSQL provides several data types to work with the character/textual data, such as CHAR, TEXT, and VARCHAR. All these data types differ in length.

PostgreSQL offers a wide range of types to deal with various types of data, such as INTEGER, TEXT, BOOLEAN, etc. Postgres offers three main data types to handle textual data, i.e., **CHAR, TEXT, and VARCHAR**.

This post will explain all these data types through practical examples. So, let’s start.

 **Postgres CHAR Data Type**

In PostgreSQL, the CHAR data type is used to store fixed-length characters. The below snippet will assist you in this regard:
    
    
    var_name CHAR(n);

In the above snippet, **“n”** determines the length of the CHAR() type. If you try to store characters more than the specified length **“n”** , then you will encounter an error. Let’s understand it via practical examples.

 **Example 1: Creating Columns With CHAR Data Type in Postgres**

Let’s create a “cust_info” table with two columns: cust_name and cust_gender. Both columns are of a character data type but with different lengths:
    
    
    CREATE TABLE cust_info(
    cust_name CHAR(10),
    cust_gender CHAR(1)
    );

The output shows that the “cust_info” table has been created successfully. You can verify the table creation via the following command:
    
    
    SELECT * FROM cust_info;

The output shows that two columns have been created with the character data type.

 **Example 2: How do I Insert CHAR Data Into a PostgreSQL Table?**

To insert character data into the cust_info table, we will use the **INSERT** query as follows:
    
    
    INSERT INTO cust_info(cust_name, cust_gender)
    VALUES ('Joe', 'M'),
    ('Alexa', 'F');

The output proves that two records have been inserted into the cust_info table successfully. You can verify the newly inserted data via the “SELECT” command:
    
    
    SELECT * FROM cust_info;

Output authenticates that the data has been inserted into the “cust_info” table successfully. Let’s insert one more record to get more clarity about the CHAR data type:
    
    
    INSERT INTO cust_info(cust_name, cust_gender)
    VALUES ('John', 'Male');

Output proves that an error occurred when we tried to input a value more than the specified length.

 **Postgres VARCHAR Data Type**

Postgres offers another character type named **VARCHAR** or **CHARACTER VARYING**. It has a couple of implementations, as shown in the following snippets:
    
    
    CHARACTER VARYING(n) | VARCHAR(n);

Here, **“n”** represents the length of the string/sequence. If you utilize one of the notations mentioned above, then the **VARCHAR** data type will store a variable-length string/sequence within a specified length.
    
    
    VARCHAR;

The above syntax allows us to store the variable length strings with an unlimited length.

 **Example 1: Creating Columns With VARCHAR Data Type in Postgres**

Let’s create a “std_info” table with three columns: f_name, l_name, and std_email. All columns are of a character-varying data type but with different lengths:
    
    
    CREATE TABLE std_info(
    f_name VARCHAR(10),
    l_name CHARACTER VARYING(10),
    std_email VARCHAR
    );

The desired table has been created successfully. Run the below command to get the table details:
    
    
    SELECT * FROM std_info;

The output shows that three columns with the specified data type and length have been created successfully. You can insert only ten characters in the **“f_name”** and **“l_name”** columns; however, in the **“std_email”** column, you can insert as many characters as you want.

 **Example 2: How do I Insert VARCHAR Data Into a PostgreSQL Table?**

Let’s insert some specific records into the std_info table via the INSERT INTO command:
    
    
    INSERT INTO std_info(f_name, l_name, std_email)
    VALUES('Joe', 'Denly', 'joe@xyz.com'),
    ('Tim', 'Root', 'tim@xyz.com'),
    ('Mike', 'Ambrose', 'mike@xyz.com');

The above snippet proves that three records have been successfully inserted into the targeted table. Let’s verify the newly inserted data via the SELECT query:
    
    
    SELECT * FROM std_info;

The output authenticates that the three records have been inserted into the std_info table.

 **Postgres TEXT Data Type**

The **TEXT** data type is one of the character data types in PostgreSQL that is used to store an unlimited number of characters. It is used to create variable-length strings. In PostgreSQL, the TEXT data type and the VARCHAR data type without any argument are equivalent.
    
    
    var_name TEXT;

Let’s understand the working of **TEXT** data type via practical examples.

 **Example 1: Creating a Column With TEXT Data Type in Postgres?**

Suppose we want to create a table named **emp_data** with two columns: emp_name and emp_email. To do this, we will utilize the CREATE TABLE command as follows:
    
    
    CREATE TABLE emp_data(
    emp_name TEXT,
    emp_email TEXT
    );

The “CREATE TABLE” message in the output window shows that the desired table has been created successfully. The command mentioned below will show the table’s structure:
    
    
    SELECT * FROM emp_data;

The emp_data table having two TEXT-type columns has been created successfully.

 **Example 2: How do I Insert TEXT Data Into a PostgreSQL Table?**

To insert data into the emp_data table, we will use the **INSERT** query as follows:
    
    
    INSERT INTO emp_data(emp_name, emp_email)
    VALUES ('Tim', 'tim@xyz.com'),
    ('Mike', 'mike@xyz.com');

The output snippet indicates that two records have been inserted into the targeted table. Let’s execute the SELECT query one more time to display the newly inserted table’s data:
    
    
    SELECT * FROM emp_data;

The output shows that all the records have been inserted into the emp_data table successfully.

That’s all from this Postgres blog post.

 **Conclusion**

PostgreSQL provides several data types to work with the character/textual data, such as CHAR, TEXT, and VARCHAR. All these data types are used to store the character data; however, these data types differ in length. For instance, CHAR(n) and VARCHAR(n) store the characters based on the specified length, i.e., “n”. While TEXT and VARCHAR are used to store unlimited characters. This blog post explained the character types through practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-character-data-types-char-varchar-and-text/)

---

# PostgreSQL TEXT Data Type With Examples

> The TEXT data type is one of the character data types in PostgreSQL that is used to store an unlimited number of characters. It is used to create variable-leng…

PostgreSQL provides various data types to deal with the string/character type data. The **TEXT** data type is one of the character data types that can store an unlimited number of characters. It is used to create variable-length strings. In Postgres, the TEXT data type and the VARCHAR data type without any argument are equivalent.

This write-up will teach you various use cases of the **TEXT** data type in PostgreSQL. So, let’s start!

 **PostgreSQL TEXT Data Type**

The **TEXT** data type has a straightforward syntax, as shown in the following snippet:
    
    
    var_name TEXT;

Note: TEXT data must be enclosed within single quotations.

Let’s comprehend the working of **TEXT** data type via practical examples.

 **Example 1: Creating a Column With TEXT Data Type in Postgres?**

Suppose we want to create a table named **customer_info** with four columns: cust_id, cust_name, cust_age, and cust_email. For this purpose, we will utilize the CREATE TABLE command as follows:
    
    
    CREATE TABLE customer_info(
    cust_id int PRIMARY KEY,
    cust_name TEXT,
    cust_age INT,
    cust_email TEXT
    );

The “CREATE TABLE” message in the output windows indicates that the “customer_info” table has been created successfully. Let’s verify the table creation using the SELECT query as follows:
    
    
    SELECT * FROM cutomer_info;

The customer_info table with four columns has been created successfully.

 **Example 2: How do I Insert TEXT Data Into a PostgreSQL Table?**

To insert data into the customer_info table, we will use the **INSERT** query as follows:
    
    
    INSERT INTO customer_info(cust_id, cust_name, cust_age, cust_email)
    VALUES (1, 'Joe', 25, 'joe@xyz.com'),
    (2, 'Tim', 25, 'tim@xyz.com'),
    (3, 'Root', 26, 'root@xyz.com'),
    (4, 'Seth', 22, 'seth@xyz.com'),
    (5, 'Mike', 26, 'mike@xyz.com'),
    (6, 'John', 25, 'john@xyz.com');

The output clarifies that six rows have been inserted into the customer_info table. Let’s execute the SELECT query one more time to show the table’s data:
    
    
    SELECT * FROM customer_info;

The output shows that all the records have been inserted into the customer_info table successfully.

 **Conclusion**

The **TEXT** data type is one of the character data types in PostgreSQL that is used to store an unlimited number of characters. It is used to create variable-length strings. The text data must be enclosed within the single quotes. In Postgres, the TEXT data type and the VARCHAR data type without any argument are equivalent. This blog post explained how to use the TEXT data type in PostgreSQL through practical demonstration.

---
[View this page online](https://www.commandprompt.com/education/postgresql-text-data-type-with-examples/)

---

# How to Use REGEXP_REPLACE Function in PostgreSQL

> How to Use REGEXP_REPLACE Function in PostgreSQL from Command Prompt

In PostgreSQL, the **REGEXP_REPLACE** function is famous for replacing the existing strings with new strings. It is based on the regular expression that the user writes according to their requirement. This guide explains the REGEXP_REPLACE function through various examples in PostgreSQL:

  * Example 1: Use REGEXP_REPLACE Function to Arrange Name
  * Example 2: Use REGEXP_REPLACE Function to Remove Extra Spaces
  * Example 3: Use REGEXP_REPLACE Function to Remove Alphabets
  * Example 4: Use REGEXP_REPLACE Function to Remove Digits
  * Example 5: Use REGEXP_REPLACE Function to Replace String in Table



Let's start the journey with the syntax of the REGEXP_REPLACE function in PostgreSQL.

 **Syntax**
    
    
    REGEXP_REPLACE(input_str, reg_exp, replace_str,[, flags])

The description of the parameters is as follows:

\- **input_str** : the string that needs to be replaced after matching the regular expression.

\- **reg_exp** : represents the regular expression pattern.

\- **replace_str** : represents a string that will be replaced in place of input_str.

\- **flags** : refers to the argument that controls the function's behavior.

 **Example 1: Use REGEXP_REPLACE Function to Arrange Name**

This example will guide you on how to rearrange the strings using the REGEXP_REPLACE() function:
    
    
    SELECT REGEXP_REPLACE('PostgreSQL Welcome','(.*) (.*)','\2, \1');

\- The REGEXP_REPLACE function takes two strings: “PostgreSQL” and “Welcome” as arguments.

\- After that, regular expression (.*) matches the occurrence.

\- \2 replaces the content of the first variable in the second place, while \1 will replace it in the first place:

The output authenticates the working of the REGEXP_REPLACE() function as it succeeded in rearranging the given strings.

 **Example 2: Use REGEXP_REPLACE Function to Remove Extra Spaces**

The **REGEXP_REPLACE** function can also be used to remove the extra spaces:
    
    
    SELECT REGEXP_REPLACE('Welcome  to  database', '(   ){2,}', ' ', 'g');

Users can verify the REGEX_REPLACE() function successfully removes the extra spaces and retrieves the output as “ **Welcome to database** ”.

 **Example 3: Use REGEXP_REPLACE Function to Remove Alphabets**

Suppose you have to filter the numbers from a string. To do that, the **REGEXP_REPLACE()** function can be used as follows:
    
    
    SELECT REGEXP_REPLACE('PostgreSQL51214Database', '[[:alpha:]]','','g');

The “: **alpha:** ” expression will remove the alphabet from the existing string:

Users can verify that “ **PostgreSQL51214Database** ” has been altered to “ **51214** ” using the **REGEXP_REPLACE()** function.

 **Example 4: Use REGEXP_REPLACE Function to Remove Digits**

For removing digits, you can specify the “ **:digit:** ” expression within the **REGEXP_REPLACE** function:
    
    
    SELECT REGEXP_REPLACE('PostgreSQL51214Database', '[[:digit:]]','','g');

Users can confirm that “ **PostgreSQL51214Database** ” is replaced with the “ **PostgreSQLDatabase** ”.

 **Example 5: Use REGEXP_REPLACE Function to Replace String in Table**

In PostgreSQL, the **REGEXP_REPLACE()** function can be used to replace the existing string with the new one. For better understanding, a table is carried out having some information in it. To fetch the table’s data, we can execute the SELECT query as follows:
    
    
    SELECT * from candidates;

The output shows that the “candidates” table has one record in it.

Let’s utilize the REGEXP_REPLACE() function to alter the “email” column of the “candidates” table.
    
    
    SELECT REGEXP_REPLACE(email , 'joe', 'peter') AS "Final" FROM candidates;

In this example, we replaced a string “joe” with the “peter” in the “email” column:

Users can verify that the substring “ **joe** ” has been replaced with the “ **peter** ” in the existing selected column.

That is all from this guide.

 **Conclusion**

PostgreSQL provides the **REGEXP_REPLACE()** function to replace an existing string with a new string using regular expressions. The string will be replaced only if a substring satisfies the specified pattern. Users can perform multiple operations using regular expressions, such as rearranging strings, removing alphabets from the strings, removing digits, and so on. This guide has covered the REGEXP_REPLACE() function along with practical implementation in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-regexp_replace-function-in-postgresql/)

---

# How to Concatenate Strings in PostgreSQL

> How to Concatenate Strings in PostgreSQL from Command Prompt

In PostgreSQL, concatenation is an important concept that allows the users to join two or more words, sentences, strings, etc. It is possible through the “||” operator and the “ **CONCAT()** ” function. This article demonstrates syntax along with practical examples to cover all aspects of the **“||”** operator and “ **CONCAT()** ” function to concatenate multiple strings. The below concepts will be explained in this Postgres guide:

  * How to Concatenate Strings in PostgreSQL
  * Example 1: Concatenate Two Strings Using || Operator in Postgres
  * Example 2: Concatenate Two Strings and a NULL Value Using || Operator
  * Example 3: Concatenate Two Strings Using CONCAT() Function
  * Example 4: Concatenate Two Strings and a NULL Value Using CONCAT() Function



Let’s begin!

 **How to Concatenate Strings in PostgreSQL**

In this section, we will show you how to concatenate strings using the “||” operator and the CONCAT() function. Let's start with the syntax of the “||” operator:
    
    
    'str_1' || 'str_2 ' || 'str_n';

Here, str_1, str_2, str_n are the strings to be concatenated.

The syntax to concatenate two or more strings using the “CONCAT()” function will be as follows:
    
    
    SELECT CONCAT('str_1', 'str_2', 'str_n');

In the above syntax, **str_1, str_2, str_n** represents the strings, words, characters to be concatenated.  


 **Example 1: Concatenate Two Strings Using || Operator in Postgres**

In PostgreSQL, two strings can be concatenated with the help of the **“||”** operator. For this, two strings “PostgreSQL” and “Databases” will be concatenated through the “||” operator:
    
    
    SELECT 'PostgreSQL' || ' ' || 'Databases' AS result;

The output shows that the “||” operator successfully concatenated the given strings.

 **Example 2: Concatenate Two Strings and a NULL Value Using || Operator**

Let’s consider the below snippet to see how the “||” operator deals with the NULL values:
    
    
    SELECT 'PostgreSQL' || NULL || 'Databases' AS output;

Output proves that concatenating a NULL value with strings using the "||" operator returns null. In simple terms, we can say that the “||” operator retrieves faulty(NULL) results while concatenating strings with a NULL value.

 **Example 3: Concatenate Two Strings Using CONCAT() Function**

An example is considered to concatenate two strings through the “ **CONCAT()** ” function:
    
    
    SELECT CONCAT ('Welcome',' ', 'PostgreSQL');

Users can verify that two strings “ **Welcome** ” and “ **PostgreSQL** ” have been concatenated as “ **Welcome** **PostgreSQL** ” in the above figure.

 **Example 4: Concatenate Two Strings and a NULL Value Using CONCAT() Function**

Let’s concatenate a couple of strings, i.e., “ **Harry** ”, “ **Peter** ” and a **NULL** value using the **CONCAT()** function:
    
    
    SELECT CONCAT('Harry', NULL, 'Peter');

Users can verify that “ **HarryPeter** ” has been concatenated without any interruption of the **NULL** value.

 **Example 5: Concatenate Two Columns of a Table in PostgreSQL**

Let’s concatenate the values of the table’s columns using the CONCAT() function. For this purpose, an existing table “ **candidates** ” is utilized as follows:
    
    
    SELECT * FROM candidates;

The “ **candidates** ” table has multiple columns including “ **candidate_id** ”, “ **first_name** ”, “ **last_name** ” and “ **email** ”.

To concat “ **first_name** ” and “ **last_name** ” column values, we will execute the following statement:
    
    
    SELECT first_name, last_name, 
    CONCAT(first_name,' ' , last_name) "Full Name" 
    FROM candidates;

Users can verify that “ **Joe** ” and “ **Com** ” have been concatenated as “ **Joe Com** ” in the “ **Full Name** ” column.

Great Job! You have learned the usage of the “ **CONCAT** ” function in this PostgreSQL tutorial.

 **Conclusion**

In PostgreSQL, the “||” operator and a built-in function named “CONCAT()” are used to concatenate multiple strings, characters, etc. The “||” operator retrieves faulty results while concatenating the strings with the NULL values. However, the CONCAT() function handles the NULL values appropriately. This article has covered all possible aspects of concatenating strings in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-concatenate-strings-in-postgresql/)

---

# How to Use RETURNING Clause in PostgreSQL

> How to Use RETURNING Clause in PostgreSQL by Command Prompt

In Postgres, the “ **RETURNING** ” clause is used to return the newly inserted, deleted, or updated data. The working procedure of the RETURNING clause is similar to the “SELECT” statement. It is quite an interesting feature of PostgreSQL to verify the operations during execution time. The objective of this guideline is to demonstrate the usage of the RETURNING clause in Postgres.

The below-listed aspects will be explained in this post:

  * Create a Sample Table in Postgres.
  * Inserting Values Into a Table in Postgres.
  * Example 1: Using RETURNING Clause with INSERT Statement
  * Example 2: Using RETURNING Clause with DELETE Statement
  * Example 3: Using RETURNING Clause with UPDATE Statement



Let's start the journey.

 **Create a Sample Table in PostgreSQL**

First of all, create a table in the PostgreSQL database. Execute the below-given query to create a table named “team”:
    
    
    CREATE TABLE team(
    name VARCHAR(255),
    age INTEGER);

On successful execution, the “ **team** ” table with two columns, “ **name** ” and “ **age** ”, has been created successfully.

 **Inserting Values Into a Table in PostgreSQL**

The “ **INSERT INTO** ” statement is used for inserting values in the “ **team** ” table. The command that performs this insertion is as follows.
    
    
    INSERT INTO team(name, age) 
    VALUES ('Adam', '32');

In this table, two values, “ **Adam** ” and “ **32** ” are inserted in the “ **name** ” and “ **age** ” columns that can be confirmed from the resultant output.

Different examples are carried out in this write-up to explain the usage of the “ **RETURNING** ” clause in PostgreSQL.

 **Example 1: Using RETURNING Clause with INSERT Statement**

An example is considered to return the values of a specific table column via the “ **RETURNING** ” clause. For instance, the statement is provided below:
    
    
    INSERT INTO team(name , age) 
    VALUES ('Adam', '32')
    RETURNING name;

The output shows that the RETURNING clause retrieves the newly inserted value of the name column.

Specify the * after the RETURNING clause to get the newly inserted data of all the table columns:
    
    
    INSERT INTO team (name, age) 
    VALUES ('Molo', 27),
    ('King', 35) 
    RETURNING *;

The output authenticates the working of the **RETURNING** Clause with the INSERT query.

 **Example 2: Using RETURNING Clause with DELETE Statement**

In PostgreSQL, users can execute the DELETE Query with the “ **RETURNING”** clause to retrieve the newly deleted records.

For displaying the data of the “team” table, execute the “ **SELECT** ” query as follows.
    
    
    SELECT * FROM team;

Let’s delete some specific records from the “team” table using the DELETE query. The following statement explains how the "RETURNING" clause can be used to retrieve the deleted rows:
    
    
    DELETE FROM team
    WHERE name = 'Adam'
    RETURNING *;

The above statement deletes all those records whose **name** is equal to “ **Adam** ”.

 **Example 3: Using RETURNING clause with UPDATE Statement**

Another example is considered with the “ **UPDATE** ” statement to update specific information in the existing column. For instance, a value **30** is assigned to all those entities whose age is equal to or greater than **40**. After that, the “ **RETURNING** ” clause is used to retrieve the updated names:
    
    
    UPDATE team 
    SET age= 30 
    WHERE age>= 40 
    RETURNING name, age AS new_age;

This is how you can retrieve the newly updated records using the RETURNING Clause.

 **Conclusion**

In Postgres, the “ **RETURNING** ” clause is used with the INSERT, DELETE or UPDATE queries to retrieve the newly inserted, deleted, or updated data. It is useful to visualize the current operation by placing the “RETURNING” clause at the end of the statement. This article has explained all aspects of the “RETURNING” clause along with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-returning-clause-in-postgresql/)

---

# PostgreSQL Primary Key - A Complete Guide

> PostgreSQL Primary Key - A Complete Guide from Command Prompt

In all the databases, including PostgreSQL, the Primary keys are used to identify a record uniquely. It can be defined using primary key constraints. In PostgreSQL databases, the primary key ensures the relationship between two tables. But if there is only one table, that does not associate with any other table. For this, it does not require any primary key.

The purpose of this tutorial is to present the complete guidance of the primary key along with practical implementation.

  * Usage of Primary Key in PostgreSQL
  * Example 1: Creation of Primary key via CREATE TABLE Statement
  * Example 2: Removal of Primary key via ALTER TABLE Statement
  * Example 3: Altering a Primary key via ALTER TABLE Statement



Let's start an interesting journey.

 **Usage of Primary Key in PostgreSQL**

To create a primary key in Postgres, the user must specify the keyword “PRIMARY KEY” along with the targeted column.

 **Syntax**

The following syntax shows how a primary key is created during table creation:
    
    
    CREATE TABLE table_name(
    column_1 data_type PRIMARY KEY, 
    column_2 data_type
    );

The above syntax has some parameters which are enlisted as below:

\- **CREATE TABLE** statement is utilized for creating a table.  
\- **table_name** specifies the name of the created table in the database.  
\- **column_1** represents the name of the column.  
\- **data_type** identifies the data type of the specified column.  
\- **PRIMARY KEY** is a keyword to create a Primary key in a table.

 **Example 1: Creation of Primary Key via CREATE TABLE Statement**

This example demonstrates how to create a primary key while creating a table. The **CREATE TABLE** statement is utilized for creating a table named “ **org_table** ”. After that, specify the column's name and write the primary key name as a constraint:
    
    
    CREATE TABLE org_table (
    emp_id INTEGER CONSTRAINT off_pk PRIMARY KEY,
    name TEXT,
    age INTEGER
    );

The above figure shows that a column “ **emp_id** ” is set as the primary key during creating a table. We specified the name of the primary key constraint as “ **off_pk** ” as shown in the above figure.

Let’s execute the below-given command to describe the structure of the org_table:
    
    
    \d org_table;

Users can verify that the primary key is assigned to the “ **emp_id** ” column of table “ **org_table** ”.

 **Example 2: Removal of Primary key via ALTER TABLE Statement**

Removing the primary key is also an important concept in the PostgreSQL database. In Postgres, the “ **ALTER TABLE** ” statement must be used with the “ **DROP CONSTRAINT** ” command to drop the primary key:
    
    
    ALTER TABLE org_table DROP CONSTRAINT off_pk;

When dropping a primary key constraint, the user must specify the constraint name instead of specifying the column name:

In the above figure, the “ **ALTER TABLE** ” message confirms that the primary key named “ **off_pk** ” has been successfully removed from the targeted table. Run the \d command to describe the updated table:
    
    
    \d org_table;

Users can verify that the primary key constraint has been dropped from the org_table.

 **Example 3: Altering Primary key via ALTER TABLE Statement**

Let’s add a new column to the org_table using ALTER TABLE statement:
    
    
    ALTER TABLE org_table ADD COLUMN id_card VARCHAR;

The “ **ALTER** **TABLE** ” message is displayed in the output which confirms that a new column “ **id_card** ” has been added to the “ **org_table** ”.

Let’s describe the structure of “org_table” using the following command:
    
    
    \d org_table;

The output shows that the column named “id_card” has been added to the org_table successfully. Suppose we want to alter the behavior of the id_card column (i.e. id_card column should be uniquely identified), to do so, we will execute the ALTER command as follows:
    
    
    ALTER TABLE org_table ADD PRIMARY KEY (id_card);

For displaying the table details, users can utilize the “\d” command as follows:
    
    
    \d org_table;

The resultant output clarifies that the **PRIMARY KEY** constraint has been added to the id_card column.

That’s it! You have learned all the aspects of the primary key in PostgreSQL.

 **Conclusion**

To create a primary key in Postgres, user must specify the **“PRIMARY KEY”** keyword along with the name of the targeted column. Usually, primary keys are created when a table is created, but they can also be assigned to existing columns. This tutorial demonstrates the syntax, usage, and practical implementation of the primary key in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-primary-key-a-complete-guide/)

---

# How Do I Count Unique Values in PostgreSQL?

> In PostgreSQL, the DISTINCT clause can be used with the COUNT() function to count only unique/distinct values of a table.

PostgreSQL provides a built-in function named **COUNT()** that counts the number of records in a table. It retrieves the number of all records/rows, including duplicate/redundant records and null values. However, the DISTINCT clause can be used with the **COUNT()** function to count only unique/distinct values of a table.

This write-up is going to present a detailed guide on how to count unique values through practical examples. So, let’s get started!

 **How to Count Distinct/Unique Values in Postgres?**

Use the DISTINCT Clause with the COUNT() function to count only the unique values:
    
    
    COUNT(DISTINCT col_name);

 **Example: How to Count Distinct Values in Postgres?**

Firstly, we will create a sample table named emp_reocrd with four columns: emp_id, emp_name, emp_age, and emp_salary.
    
    
    CREATE TABLE emp_record(
    emp_id SERIAL PRIMARY KEY,
    emp_name TEXT, 
    emp_age SMALLINT,
    emp_salary SMALLINT);

We will insert multiple records into the emp_record table including some duplicates:
    
    
    INSERT INTO emp_record(emp_name, emp_age, emp_salary)
    VALUES ('JOHN', 26, 20000),
    ('JOE', 26, 25000),
    ('SETH', 29, 20000),
    ('JOHNSON', 34, 25000),
    ('JOHN', 26, 20000),
    ('MIKE', 22, 25000),
    ('JOE', 26, 25000),
    ('JOE', 26, 25000);

Let’s run the below command to see the table’s data:
    
    
    SELECT * FROM emp_record;

There are eight records in the emp_record table. Now use the COUNT() function to count the number of rows in the emp_record table:
    
    
    SELECT COUNT(emp_name)
    FROM emp_record;

Output retrieves ‘8’, which proves that the COUNT() function counted each record, including duplicates. Run the below command to count only unique values from the emp_record table:
    
    
    SELECT COUNT(DISTINCT emp_name)
    FROM emp_record;

The COUNT() function returned '5' this time, proving that it only counts unique values.

This way, you can count the number of unique records; however, you can fetch the unique rows from the desired table using the DISTINCT clause as follows:
    
    
    SELECT DISTINCT emp_name;

In the actual result set, JOHN occurs two times while JOE occurs three times. However, the DISTINCT clause skipped the duplicate names and retrieved only unique values.

 **Conclusion**

In PostgreSQL, the DISTINCT clause can be used with the COUNT() function to count only unique/distinct values of a table. The simple COUNT() function retrieves all the rows/records, including duplicate values and null. To count only unique rows, you must specify a DISTINCT clause with the COUNT() function. Use the DISTINCT clause with the aid of the SELECT statement to get and describe the unique table records. Through practical examples, this post explained how to count the unique values from a table.

---
[View this page online](https://www.commandprompt.com/education/how-do-i-count-unique-values-in-postgresql/)

---

# PostgreSQL Foreign Key With Practical Examples

> Foreign keys allows us to link the data of one table to others. The table referencing the foreign key is known as child table, while the table referenced by th…

In relational databases like PostgreSQL, Foreign keys are a widely used concept that allows us to link the data of one table to another. A table can have zero, one, or multiple foreign keys; it depends on the table’s relation with other tables. The table holding a foreign key is known as the child/referencing table, while the table which is referenced through the foreign key is named as parent/referenced table.

This write-up will cover all the basics of Postgres Foreign key constraints using practical examples. So, let’s begin.

 **FOREIGN KEY Constraint in Postgres?**

The FOREIGN KEY refers to a column/field in a table that points to the PRIMARY KEY in some other Postgres table. Postgres allows foreign keys to be defined using foreign key constraints. Moreover, the data referential integrity is maintained between the child and parent tables with the help of the foreign key constraint.

 **Syntax**

The below snippet depicts the syntax of the foreign key constraint:
    
    
    [CONSTRAINT name]  FOREIGN KEY(col_list)
    REFERENCES parent_tab(col_list)
    [ON DELETE action]
    [ON UPDATE action]

Let’s comprehend the above-given syntax step-by-step:

  * Firstly, specify the foreign key name using the CONSTRAINT keyword/clause. The CONSTRAINT is optional; if you skip it, Postgres will specify an auto-generated name.
  * Next, use the FOREIGN KEY keyword followed by a set of parentheses and specify the foreign key column or group of columns within the parenthesis.
  * In the REFERENCES clause, identify the parent/referenced table along with the foreign key columns.
  * Finally, you can use a couple of optional clauses, such as ON DELETE and ON UPDATE, to determine the referential actions.



 **Create a Foreign Key Constraint in Postgres**

The following example shows how a foreign key constraint can be created at the time of table creation:
    
    
    CREATE TABLE emp_info( 
    emp_id INT PRIMARY KEY NOT NULL, 
    emp_name TEXT NOT NULL, 
    emp_email VARCHAR(100) NOT NULL, 
    emp_salary INT NOT NULL);

emp_info table with four columns has been created successfully.

Let’s create another table named dept_info that contains a foreign key emp_id:
    
    
    CREATE TABLE dept_info(
    dept_id INT PRIMARY KEY NOT NULL, 
    dept_name TEXT NOT NULL, 
    emp_id INT,
    CONSTRAINT fk_emp_dept 
    FOREIGN KEY(emp_id)
    REFERENCES emp_info(emp_id));

The dept_info table has been created successfully. Let’s run the below command to get more clarity:
    
    
    \d+ emp_info;

The output shows that the emp_id column is referenced by the dept_info table.

Let’s execute the below command to understand the table’s relation more clearly:
    
    
    \d+ dept_info;

The output clarifies that the emp_id is a foreign key in the dept_info table.

That was all the basics regarding Postgres FOREIGN KEY CONSTRAINT.

 **Conclusion**

In PostgreSQL, Foreign keys are a widely used concept that allows us to link the data of one table to others. A table can have zero, one, or multiple foreign keys; it depends on the table’s relation with other tables. The table referencing the foreign key is named the child/referenced table, while the table referenced by the foreign key is known as the parent/referenced table. This post explained the FOREIGN KEY CONSTRAINT with a practical example.

---
[View this page online](https://www.commandprompt.com/education/postgresql-foreign-key-with-practical-examples/)

---

# How to Use EXCEPT Operator in PostgreSQL?

> In PostgreSQL, EXCEPT returns the rows that exist in the result set of the first SELECT query but not in the result set of the second SELECT query.

**EXCEPT** is an operator provided by Postgres that compares the result sets of two queries and retrieves all the rows that exist in the result set of the first select query but not in the result set of the second SELECT query.

Through practical examples, this write-up will teach you the basic syntax and usage of the Postgres EXCEPT operator. So, let’s start.

 **How to Use an EXCEPT Operator in PostgreSQL?**

To implement the EXCEPT operator, you have to follow the below syntax:
    
    
    SELECT col_list
    FROM tbl_1
    [WHERE condition_tbl_1] 
    EXCEPT
    SELECT col_list
    FROM tbl_2
    [WHERE condition_tbl_2];

Let’s comprehend this syntax step-by-step:

  * In place of col_list, the user can specify the columns/expressions he wants to compare between the two SELECT commands.
  * tbl_1 and tbl_2 are the targeted tables.
  * WHERE is an optional clause that can be used to specify criteria.



 **Practical Implementation of the EXCEPT Operator**

We have already created a couple of tables in our database named article_details and recommended_articles. Let’s fetch the details of each table one by one:
    
    
    SELECT * FROM article_details;

Now let’s fetch the content of the recommended_articles table:
    
    
    SELECT * FROM recommended_articles;

Now we will see how the EXCEPT operator works on the given tables.

 **Example#1: How to Use the EXCEPT Operator on a Single Column?**

The below-given query will show the usage of the EXCEPT operator:
    
    
    SELECT article_title
    FROM article_details
    EXCEPT
    SELECT article_title
    FROM recommended_articles;

The EXCEPT operator retrieves all the article titles of the result set except two titles, i.e., PostgreSQL INSERT Query and PostgreSQL ALTER Command.

 **Example#2: How to Use the EXCEPT Operator on Multiple Columns?**

The below-given query will show you how to use the EXCEPT operator with multiple columns:
    
    
    SELECT article_id, article_title
    FROM article_details
    EXCEPT
    SELECT article_id, article_title
    FROM recommended_articles;

The EXCEPT operator retrieves all the article ids and titles of the first result set except two, namely PostgreSQL INSERT Query having id 7 and PostgreSQL ALTER Command having id 8.

 **Example#3: How to Use the EXCEPT Operator With ORDER BY Clause?**

From the previous result sets, it can be seen that the records are out of order. To sort a result set into a specific order, run the below query:
    
    
    SELECT *
    FROM article_details
    EXCEPT
    SELECT *
    FROM recommended_articles
    ORDER BY article_id DESC;

EXCEPT returns all records from the first query's result set that do not appear in the second query's result set.

That was all the basic information related to the Postgres EXCEPT operator.

 **Conclusion**

In PostgreSQL, the **EXCEPT** operator compares the result sets of two queries and retrieves all the rows that exist in the result set of the first select query but not in the result set of the second SELECT query. Through Practical examples, this post explained the usage of the EXCEPT operator.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-except-operator-in-postgresql/)

---

# How to Use Check Constraint in PostgreSQL?

> CHECK constraints in PostgreSQL allow us to specify Boolean conditions for inserting or updating values in one or more columns.

**CHECK** constraints in PostgreSQL allow us to specify boolean conditions for inserting or updating values in one or more columns. While updating or inserting, the values that don’t satisfy the specified criteria/condition will be rejected. In Postgres, the **CHECK** constraints are beneficial for adding additional logic or restrictions at the database layer.

The following concepts of **CHECK** constraint will be covered in this post:

  * How to Define/Add CHECK Constraints While Creating a Table in Postgres?
  * Adding CHECK Constraint to an Existing Table



So let’s learn all these concepts one-by-one through practical examples.

 **How to Define/Add CHECK Constraints While Creating a Table in Postgres?**

The CHECK constraint is normally defined at the time of table creation. The syntax of defining a CHECK constraint will be as follows:
    
    
    CREATE TABLE tab_name(
    col_name DATA TYPE CHECK(CONDITION)
    );

 **Example #1: How Does CHECK Constraint Work in Postgres?**

The below-given query will create a book_info table with four columns: book_name, book_category, published_date, and book_price:
    
    
    CREATE TABLE book_info (
    book_name VARCHAR (50),
    book_category TEXT, 
    published_date DATE CHECK(published_date > '2000-01-01'),
    book_price INT
    );

For the published_date column, a condition is specified using the CHECK constraint. The specified condition states that the book published_date must be greater than ‘2000-01-01’:

Let’s insert a record into the book_info table using the following command:
    
    
    INSERT INTO book_info(book_name, book_category, published_date)
    VALUES('Introduction to Postgres', 'Database', '1999-06-01', 500);

The output verified that an error occurred on violating the **CHECK** constraint.

 **Adding CHECK Constraint to an Existing Table**

ALTER TABLE can be used to add CHECK constraints to an existing table:
    
    
    ALTER TABLE tab_name
    ADD CONSTRAINT check_constraint_name 
    CHECK (Condition);

 **Example: How Does the CHECK Constraint Work on an Already Existing Table?**

Suppose we want to add the CHECK constraint on the book_price column. For that purpose, we will use the CHECK constraint as follows:
    
    
    ALTER TABLE book_info
    ADD CONSTRAINT book_price CHECK(book_price <= 1000);

Now, the book_price column will not accept those value that exceeds the book_price 1000:
    
    
    INSERT INTO book_info(book_name, book_category, published_date, book_price)
    VALUES('Introduction to Postgres', 'Database', '2008-06-01', 1500);

The output shows that the value entered for the book_price column violates the condition specified in the CHECK constraint. Let’s insert a record that satisfies the CHECK constraint for both publised_date and book_price columns:
    
    
    INSERT INTO book_info(book_name, book_category, published_date, book_price)
    VALUES('Introduction to Postgres', 'Database', '2018-06-01', 500);

The output shows that if the values to be inserted satisfy the CHECK constraint, the data will be inserted into the targeted table.

 **Conclusion**

 **CHECK** constraints in PostgreSQL allow us to specify boolean conditions for inserting or updating values in one or more columns. Values that meet the specified criteria/condition will be inserted/updated into PostgreSQL, while those that do not will be rejected. This post explained the usage of the CHECK constraint through examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-check-constraint-in-postgresql/)

---

# PostgreSQL SERIAL- How to Create Auto-increment Columns

> PostgreSQL offers a Pseudo-type known as SERIAL. It allows Postgres users to create auto-incremented columns in a table. Using SERIAL, you can create a sequenc…

PostgreSQL offers a Pseudo-type known as **SERIAL** that allows the Postgres users to create auto-incremented columns in a table. Using **SERIAL** Pseudo-type, you can create a sequence of integers. Postgres offers three serial pseudo-types: **SERIAL** , BIGSERIAL, and SMALLSERIAL. All these pseudotypes differ in storage size and range.

This Post will teach you how to create auto increment columns using SERIAL pseudotype. So, let’s start.

 **How to Use SERIAL Pseudo-type in Postgres?**

Follow the below-given syntax at the time of table creation to define the auto-increment columns:
    
    
    CREATE TABLE tab_name(
    col_name SERIAL
    );

 **How Does SERIAL Pseudo-type Work in Postgres?**

Consider the below snippet:
    
    
    CREATE TABLE tbl_name(
    id SERIAL
    );

The **SERIAL** Pseudo-type works according to the following principles:

  * It creates sequences of integers, e.g., 1,2,3, and so on.
  * As discussed earlier, the SERIAL type generates a sequence of integer values, therefore set NOT NULL constraint to avoid the NULL values.
  * Last but not least, the column's sequence owner must be set. Dropping a column or table automatically deletes these IDs.



 **Types**

Postgres offers three serial pseudo-types:

  1. The SERIAL carries 4 bytes of storage size and ranges between 1 to 2147483647.
  2. The SMALLSERIAL takes 2 bytes of storage size and ranges between 1 to 32767.
  3. A BIGSERIAL takes up 8 bytes of storage and ranges from 1 to 9223372036854775807.



 **Practical Implementation of SERIAL Pseudo-type:**

Several examples will be exercised in this section to explain the working of SERIAL data type:

 **Example #1: How to Create Auto-incremented Columns in Postgres?**

Following is a sample emp_data table to be created:
    
    
    CREATE TABLE emp_data(
    emp_id SERIAL PRIMARY KEY,
    emp_name TEXT NOT NULL,
    emp_email VARCHAR(80) NOT NULL,
    emp_age SMALLINT
    );

Now we will insert the below-given records into the emp_data table:
    
    
    INSERT INTO emp_data(emp_name, emp_email, emp_age)
    VALUES ('JOE', 'joe@xyz.com', 25),
    ('Natie', 'natie@xyz.com', 29),
    ('Sasha', 'sasha@xyz.com', 26),
    ('Mike', 'mike@xyz.com', 22),
    ('JOHN', 'john@xyz.com', 27),
    ('JOHNSON', 'johnson@xyz.com', 22);

Six records have been inserted into the emp_data table. Let’s run the SELECT command to fetch the table’s content:
    
    
    SELECT * FROM emp_data;

The output shows that the SERIAL pseudo-type auto-assigned an id to each record.

 **Example #2: How to Insert Values Using the DEFAULT keyword in Postgres?**

You can use the DEFAULT keyword to insert a value into a column having a SERIAL pseudo-type:
    
    
    INSERT INTO emp_data(emp_id, emp_name, emp_email, emp_age) 
    VALUES(DEFAULT, 'AMANDA', 'amanda@xyz.com', 25);

Let’s run the below command to check the newly inserted record:
    
    
    SELECT * FROM emp_data;

This way, the DEFAULT keyword assists the users in inserting the value into an auto-incremented column.

 **Example #3:** **RETURNING Clause With SERIAL Pseudo-Type**

This example will show you the usage of RETURNING clause:
    
    
    INSERT INTO emp_data(emp_name, emp_email, emp_age) 
    VALUES('KEVIN', 'kevin@xyz.com', 27)
    RETURNING emp_id;

The RETURNING clause retrieved the newly inserted emp_id.

 **Conclusion**

PostgreSQL offers a Pseudo-type known as SERIAL. It allows Postgres users to create auto-incremented columns in a table. Using SERIAL Pseudo-type, you can create a sequence of integers. Through practical examples, this write-up explained the multiple use cases of the SERIAL data type.

---
[View this page online](https://www.commandprompt.com/education/postgresql-serial-how-to-create-auto-increment-columns/)

---

# PostgreSQL NOT NULL Constraint With Examples

> The NOT NULL constraint ensures that the column accepts only non-null values. In Postgres, the CHECK constraint can be used as an alternative to the NOT NULL.

In PostgreSQL, the **NOT NULL** constraint makes sure that the column should accept only non-null values. For instance, if a column is created with a NOT NULL constraint, then attempting to insert a NULL value to that column will throw an error. Moreover, the NOT NULL constraint prevents users from updating NULL values in columns.

Using practical examples, this post will describe the NOT NULL constraint in detail. So let’s start.

 **How to Create Table’s Columns With NOT NULL Constraint?**

To create a column with NOT NULL Constraint, use the following syntax:
    
    
    CREATE TABLE tab_name(
    col_name DATA TYPE NOT NULL
    );

The above syntax states that you must specify the NOT NULL constraint after the data type to create a column that doesn't accept null values.

 **Note:** NULL, zero, and empty string are three different things in PostgreSQL. The term NULL refers to unknown/missing information.

 **Example: How to Declare a Column Using NOT NULL?**

Let’s create a sample table named emp_record, that consists of four columns: emp_id, emp_name, emp_age, and emp_email. Suppose we want the users to insert the Non-null value in the emp_email column. To achieve this purpose, we will utilize the NOT NULL Constraint as follows:
    
    
    CREATE TABLE emp_records(
    emp_id INT PRIMARY KEY,
    emp_name TEXT,
    emp_age INT,
    emp_email VARCHAR NOT NULL
    );

The above statement creates a new table emp_record with the following details:

  * A column named emp_id is created that will accept unique integer values.
  * Next, we created two more columns: emp_name to accept string data and emp_age column, which will accept integer values.
  * Finally, we declare an emp_email column with VARCHAR data type and NOT NULL constraint, ensuring that the user must insert the NON-NULL values:



The first step is done, i.e., the emp_record table has been created. Let’s insert some data into the emp_record table to understand the working of the **NOT NULL** constraint:
    
    
    INSERT INTO emp_record(emp_id, emp_name, emp_age, emp_email)
    VALUES (1, 'JOHN', 24, NULL);

The output snippet makes this concept crystal clear, i.e., you can’t insert NULL values to the column created with a NOT NULL constraint.

Let’s insert a couple of non-null values into the selected table:
    
    
    INSERT INTO emp_record(emp_id, emp_name, emp_age, emp_email)
    VALUES(1, 'JOHN', 24, 'john@xyz.com'),
    (2, 'JOE', 27, 'joe@abc.com'),
    (3, 'MIKE', 28, 'mike@xyz.com')
    ;

This is how the **NOT NULL** constraint works in PostgreSQL.

 **How Do I Add a NOT NULL Constraint to an Existing Table 's Column?**

Use the below syntax to set a NOT NULL constraint in an existing table’s column:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_1_name SET NOT NULL;

This way, a NOT NULL constraint can be set to an existing column using the ALTER COLUMN command and the SET clause. Use the comma-separated syntax to set the NOT NULL constraint to several columns:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_1_name SET NOT NULL,
    ALTER COLUMN col_2_name SET NOT NULL,
    …,
    ALTER COLUMN col_N_name SET NOT NULL;

 **Example: How to Update an Existing Column With NOT NULL Constraint?**

Let’s add the **NOT NULL** constraint to the emp_name column using the below query:
    
    
    ALTER TABLE emp_record
    ALTER COLUMN emp_name SET NOT NULL;

Now, the emp_name column will accept only the non-null values:
    
    
    INSERT INTO emp_record(emp_id, emp_name, emp_age, emp_email)
    VALUES (4, NULL, 23, 'abx@xyz.com');

The output snippet authenticates the working of the NOT NULL constraint.

 **CHECK Constraint: An Alternate Approach For the NOT NULL Constraint**

The CHECK constraint can be used as an alternative to the NOT NULL constraint. You need to follow the below syntax to avail the functionality of the NOT NULL Constraint using the CHECK constraint:
    
    
    CHECK(col_name IS NOT NULL);

 **Example: How to Use CHECK Constraint as an Alternative to NOT NULL Constraint?**

Let’s create a new table named std_record with three columns: std_id, std_name, std_email. Suppose we want the student to enter a non-null value into the std_email column. We will achieve this purpose using the CHECK Constraint as follows:
    
    
    CREATE TABLE std_record (
    std_id INT PRIMARY KEY,
    std_name TEXT,
    std_email VARCHAR(30),
    CONSTRAINT std_email CHECK (
    NOT (std_email IS NULL OR std_email = '' )
    )
    );

Now, attempting to insert a null value to the std_email column will throw an error:
    
    
    INSERT INTO std_record(std_id, std_name, std_email)
    VALUES (1, 'Joe', NULL);

In this way, the CHECK constraint can be used as an alternative to the NOT NULL constraint.

 **Conclusion**

In PostgreSQL, the **NOT NULL** constraint makes sure that the column should accept only non-null values. Occasionally, the CHECK constraint can be used as an alternative to the NOT NULL constraint. This write-up demonstrates various use cases of the NOT NULL constraint using practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-not-null-constraint-with-examples/)

---

# How to Use ABS() Function in PostgreSQL

> PostgreSQL offers a built-in mathematical function named ABS() that takes an expression as an argument and retrieves an absolute value for the specified number…

PostgreSQL offers a built-in mathematical function named **ABS()** that takes a number or expression as an argument and retrieves an absolute value of the specified number. The absolute value of a number indicates how far it is away from zero. It is a non-negative(always positive) value because it doesn’t signify the direction.

This post will explain the following topics through practical examples:

  * How to Use ABS() Function in Postgres?
  * What is the ABS() Function, and How Does it Work on Positive Values?
  * How Does the ABS() Function Work on Negative Values?
  * How Does the ABS() Function Work on Table’s Data?



So, let’s get started!

 **How to Use ABS() Function in Postgres?**

To use the Postgres ABS() function, follow the below syntax:
    
    
    ABS(numeric_expression);

The syntax illustrates the below-listed points:

  * The **ABS()** function accepts only one argument, i.e., a numeric expression.
  * The data type of the retrieved value depends on the data type of the value passed to the **ABS()** function.
  * In the case of negative numbers, the **ABS()** function will return the negation of that number.



Let’s implement it practically.

 **What is the ABS() Function and How Does it Work on Positive Values?**

Let’s pass a positive numeric value to the **ABS()** function and see how it works:
    
    
    SELECT ABS(1001.5225);

Since the passed value was non-negative, therefore the ABS() function retrieved that value as it is.

 **How Does the ABS() Function Work on Negative Values?**

In this example, we will pass a negative numeric value to the ABS() function:
    
    
    SELECT ABS(-1001.5225);

This time we passed a negative value to the ABS() function. Consequently, the ABS() function retrieved the negation of that number.

 **How Does the ABS() Function Work on Table’s Data?**

For profound understanding, we create a table named abs_example containing an original_val column. The original_val column will accept numeric values:
    
    
    CREATE TABLE abs_example(
    original_val NUMERIC
    );

Let’s insert some positive as well as negative values into the abs_example table:
    
    
    INSERT INTO abs_example(original_val)
    VALUES (550),
    (-210), 
    (72.12),
    (-87.93),
    (-0.0);

Let’s utilize the ABS() function on the abs_example table to see how the ABS() function works on the table’s data:
    
    
    SELECT original_val, ABS(original_val) AS absolute_value
    FROM abs_example;

The output verifies the working of the ABS() function.

 **Conclusion**

PostgreSQL provides an inbuilt mathematical function named **ABS()** to get an absolute value. It takes a number or expression as an argument and retrieves an absolute value of the specified number. The absolute numeric value represents how far it is away from zero. It is a non-negative(always positive) value because it doesn’t signify the direction. Through practical examples, this article explained the working of the ABS() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-abs-function-in-postgresql/)

---

# How to Round Numbers in PostgreSQL

> PostgreSQL offers several built-in math functions such as ROUND(), CEIL(), and FLOOR() to round a number up to specific decimal places.

PostgreSQL offers several built-in math functions such as **ROUND(), CEIL(),** and **FLOOR()** to round a number up to specific decimal places. All these functions accept a numeric value as an argument and retrieve a rounded number.

This post will discuss the below-listed functions and their working through practical examples:

  * What is ROUND() Function and How Does It Work in PostgreSQL?
  * What is FLOOR() Function and How Does It Work in PostgreSQL?
  * What is CEIL() Function and How Does It Work in PostgreSQL?
  * How to Round Table Data in PostgreSQL?



So, let’s get started!

 **What is ROUND() Function and How Does It Work in PostgreSQL?**

ROUND() is an inbuilt mathematical function in Postgres that can accept either one or two numbers as arguments.
    
    
    ROUND(argument_1, argument_2);

The above snippet depicts that the ROUND() function accepts two arguments:

  * The first one represents a number to be rounded, which is mandatory.
  * If we pass only one argument, then the ROUND() function will skip the fractional points and retrieve the rounded numeric value.
  * While the second argument is optional, it determines the number of fractional points.
  * The ROUND() function retrieves the nearest/closest numeric value.



 **Example #1: Passing One Argument**

Let’s pass only one number as an argument to the ROUND() function and see how the ROUND() function works in that case:
    
    
    SELECT ROUND(572.172);

The output shows that the ROUND() function successfully rounded the specified number.

 **Example #2: Passing two Argument**

In this example, we will pass two arguments to the ROUND() function. Consequently, you will notice that the first number will be rounded up to specific decimal places based on the second number:
    
    
    SELECT ROUND(572.17214 , 2);

This way, you can round a number up to specific decimal places.

 **What is FLOOR() Function and How Does It Work in PostgreSQL?**

Postgres offers another built-in math function named FLOOR() that rounds down the provided number to the next whole number (e.g12. 78 will be rounded down to 12). Use the following syntax for the FLOOR() function:
    
    
    FLOOR(argument);

 **Example: How to Use FLOOR() Function in Postgres?**

This example will show you how to round a positive or negative value using the FLOOR() function:
    
    
    SELECT FLOOR(572.17214);

The FLOOR() function rounded down the given value.

Let’s pass a negative value to the FLOOR() function:
    
    
    SELECT FLOOR(-572.77214);

Output proves that the FLOOR() function retrieves the rounded-down value.

 **What is CEIL() Function and How Does It Work in PostgreSQL?**

Postgres offers another built-in math function named CEIL() that rounds up the provided number to the next whole number (e.g12. 78 will be rounded up to 13). Use the following syntax for the CEIL() function:
    
    
    CEIL(argument);

 **Example: How to Use CEIL() Function in Postgres?**

This example will show you how to round a positive or negative value using the CEIL() function:
    
    
    SELECT CEIL(572.17214);

Output proves that the CEIL() function retrieves the rounded-up value.

Let’s pass a negative value to the CEIL() function:
    
    
    SELECT CEIL(-572.77214);

The CEIL() function rounded up the given value.

 **How to Round Table Data in PostgreSQL?**

We created a table named round_example that has only one column: original_val. The original _val column has some positive as well as negative values. Let’s utilize the ROUND(), CEIL(), and FLOOR() function on the orignal_val column and see how each function work on the table’s data:
    
    
    SELECT original_val, 
    ROUND(original_val), 
    CEIL(original_val), 
    FLOOR(original_val) 
    FROM round_example;

The output will assist the users in analyzing the working of the ROUND(), CEIL(), and FLOOR() functions.

 **Conclusion**

PostgreSQL offers several built-in math functions such as **ROUND(), CEIL(),** and **FLOOR()** to round a number up to specific decimal places. All these functions accept a numeric value as an argument and retrieve a rounded number. The ROUND() function retrieves the nearest/closest numeric value, the FLOOR() function rounds down the provided number to the next whole number, and the CEIL() function rounds up the given number to the next whole number. This post explained each method through practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-round-numbers-in-postgresql/)

---

# How to Optimize Postgres Performance Using ANALYZE and VACUUM Commands

> PostgreSQL offers several commands to optimize, improve or maintain the health of a database, tables, etc., such as ANALYZE and VACUUM commands.

In Postgres, large database tables can experience some issues such as table/index bloat or corrupted indexes, etc. So how to deal with such issues in PostgreSQL?

PostgreSQL offers several commands to optimize, improve or maintain the health of a database, tables, etc., such as **ANALYZE** and **VACUUM** commands.

This post will explain how to optimize the performance of a database or table in PostgreSQL using **VACUUM** and **ANALYZE** commands. So, let’s get started.

 **What is VACUUM Command and How to Use it in PostgreSQL?**

It is a command-line utility that vacates the space engaged by obsolete records, tuples, etc. The VACUUM command optimizes the performance of the Postgres databases, records, etc.

 **Syntax:**

The below syntax will guide you on how to use the VACUUM command in Postgres:
    
    
    VACUUM [FULL] [FREEZE] [VERBOSE] (tab_name);

Here, the tab_name is optional, if you specify the tab_name, then only that specific table will be vacuumed; however, if you don’t specify the table’s name, then all the tables of the selected database will be vacuumed. FULL, FREEZE and VERBOSE are the optional arguments that **VACUUM** can accept. All these options serve different functionalities.

 **Example: How to Optimize Postgres Performance Using VACUUM Command?**

Firstly, establish a connection with the desired database and then apply the VACUUM command on the example database:
    
    
    \c example;

Now, let’s execute the below command to optimize the performance of example database using **VACUUM** command:
    
    
    VACUUM VERBOSE;

The output shows that the VERBOSE option along with VACUUM provides the details of the vacuumed database. Similarly, you can specify the table name with the VACUUM command to optimize only specific table:
    
    
    VACUUM FULL VERBOSE bike_details;

The output shows that the VACUUM command successfully optimized the performance of the selected table.

 **What is ANALYZE Command and How to Use it in PostgreSQL?**

It is a command line utility that the ANALYZE command collects the statistics about a database, table, or table’s columns for the query planner. These collected stats can be used by the query planner to yield efficient/appropriate execution plans for the Postgres queries.

 **Syntax:**

The ANALYZE command runs on all the tables available in the selected schema. However, you can specify the table’s name with the ANALYZE command to get the stats of only that specific table:
    
    
    ANALYZE VERBOSE [tab_name];

 **Example: How to Optimize Postgres Performance Using ANALYZE Command?**

Follow the below-listed steps to learn the working of ANALYZE command:

 **Step #1: List Databases**

Let’s execute the \l command to get the list of databases:
    
    
    \l;

 **Step #2: Connect to Database**

Suppose we want to get the stats of the “example” database. To do that, firstly, we will establish a connection with the selected database using the “\c” command:
    
    
    \c example;

 **Step #3: Get Stats of Specific Database**

We have successfully established a connection with the targeted database, i.e., “example”. Now, we can get the stats of the “example” database using ANALYZE command:
    
    
    ANALYZE;

In this way, the ANALYZE command can be used to get the database/table stats.

 **Step # 4: Optimize Postgres Performance**

Run the below command to optimize Postgres performance using the VACUUM and ANALYZE commands combinedly:
    
    
    VACUUM VERBOSE ANALYZE;

This is how the ANALYZE command works with the VACUUM command.

 **Conclusion**

PostgreSQL offers several commands to optimize, improve or maintain the health of a database, tables, etc., such as **ANALYZE** and **VACUUM** commands. Both of them are command line utilities that are used to optimize the Postgres performance. This post shows you how to use ANALYZE and VACUUM commands to improve the Postgres performance.

---
[View this page online](https://www.commandprompt.com/education/how-to-optimize-postgres-performance-using-analyze-and-vacuum-commands/)

---

# How to Use VACUUM Command in PostgreSQL

> In Postgres, VACUUM is a command-line utility that vacates the space engaged by obsolete records, tuples, etc. It optimizes the performance of the Postgres dat…

In PostgreSQL, sometimes some records engage too much space because of various reasons, such as dead records or records with older versions, etc. In such cases, the Postgres **VACUUM** command can be used to vacate that storage. The **VACUUM** statement regains the storage by deleting obsolete tables, tuples, indexes, etc.

This post will present a detailed working mechanism and usage of the **VACUUM** command through practical examples. So, let’s start.

 **What is VACUUM and How to Use it in PostgreSQL?**

It is a command-line utility that vacates the space engaged by obsolete records, tuples, etc. The VACUUM command optimizes the performance of the Postgres databases, records, etc.

 **Syntax**

The below syntax will guide you on how to use the VACUUM command in Postgres:
    
    
    VACCUM [FULL] [FREEZE] [VERBOSE] (tab_name);

Here, the tab_name is optional, if you specify the tab_name, then only that specific table will be vacuumed; however, if you don’t specify the table’s name, then all the tables of the selected database will be vacuumed.

 **Which Parameters Does PostgreSQL Accept for the VACUUM Command?**

FULL, FREEZE, and VERBOSE are the optional arguments that **VACUUM** can accept. All these options serve different functionalities.

 **FULL:** It is used to write the full content of a table into a new file. It assists the users in regaining all the unused space.

 **FREEZE:** It is very much similar to the FULL option in terms of applicability. When the vacuum operation is performed, all the records are frozen.

 **VERBOSE:** If the VERBOSE option is used with the VACUUM command, then the output will be in a more detailed format.

 **When to Use VACUUM** **Command in PostgreSQL?**

Vacuuming in PostgreSQL requires a lot of CPU & I/O compute memory; therefore, the VACUUM command should ONLY be used in moderately active applications.

 **Key Points**

Some key points and good practices regarding the **VACUUM** command are listed below that will assist you in understanding the working of the VACUUM command in a better way:

\- Skipping the table/column name from the **VACUUM** command will vacuum the entire database.

\- A database keeps the original records when you update a table. VACUUM deletes that old records/tuples and frees up space in the Postgres database.

\- Only those users can process a request for the **VACUUM** command who have access privileges.

\- Only tables with VACUUM permissions can be vacuumed.

VACUUM commands cannot be run within transactions.

Let’s implement it practically.

 **Practical Implementation of VACUUM Command in Postgres.**

The **VACUUM** command can be implemented on databases, tables, etc. This section will show you various use cases of the VACUUM command:

 **Example #1: How to Regain the Unused Space Using VACUUM Command?**

Let’s learn how to use the VACUUM command to free up unused space so that the same table can use it. It wouldn’t reduce the database size.

Firstly, establish a connection with the desired database and then apply the VACUUM command on the example database:
    
    
    \c example;

Now, run the VACUUM command:
    
    
    VACUUM;

Output retrieves “VACUUM”, proving that the command frees up the storage within each table, and now the available storage can be reused. To verify the working of the VACUUM command, run the below query:
    
    
    SELECT relname, n_dead_tup 
    FROM pg_stat_user_tables;

  * Here, pg_stat_user_tables is a built-in table in Postgres used to find the number of dead rows in a particular table.
  * “relname” and “n_dead_tup” represents the table’s columns that describe the relation name and number of dead tuples, respectively.



The output verifies that each table of the targeted table has been vacuumed successfully.

 **Example #2: How to Get the Details of the Vacuumed Database?**

Let’s run the VACUUM command with the VERBOSE option to get the details of the vacuumed database:
    
    
    VACUUM VERBOSE;

The output shows that the VERBOSE option provides the details of the vacuumed data.

 **Example #3: How to Free Unused Space and Optimize the Database?**

Run the VACUUM command with the FULL option to free the unused space and minimize the database file:
    
    
    VACUUM FULL;

The example database has been vacuumed successfully.

 **Example #4: How to Use VACUUM Command on a Table?**

Specify the table name with the VACUUM command to vacuum only a specific table. The following command will free the unused space from the bike_details table:
    
    
    VACUUM FULL VERBOSE bike_details;

As we used FULL and VERBOSE with the VACUUM command, so, all the unused space was regained, and a vacuum activity report was also produced. Run the following command to verify the working of the VACUUM command with respect to a specific table:
    
    
    SELECT n_dead_tup
    FROM pg_stat_user_tables
    WHERE relname='bike_details';

The above-given query will retrieve the number of dead rows in the bike_details table:

The output proves that the bike_details table has been vacuumed successfully. It shows that the bike_details table has zero dead row.

 **What is AUTOVACUUM, and How to Use it in Postgres?**

The Postgres database provides an automated VACUUM and ANALYZE command named AUTOVACUUM. It reduces the user’s efforts as it automates the execution process. By default, Postgres activates the autovacuum command; however, you can manually deactivate it using the following query:
    
    
    ALTER TABLE tab_name SET(autovacuum_enabled = false);

Let's deactivate the autovacuum command for the article_details table:
    
    
    ALTER TABLE article_details SET(autovacuum_enabled = false);

That was all the basics regarding Postgres VACUUM Command.

 **Conclusion**

In PostgreSQL, **VACUUM** is a command-line utility that vacates the space engaged by obsolete records, tuples, etc. The VACUUM command optimizes the performance of the Postgres databases, records, etc. Through practical examples, this post explained how to optimize the performance of the databases and tables using the VACUUM command.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-vacuum-command-in-postgresql/)

---

# How to Use MOD() Function in PostgreSQL?

> The MOD() function is one of the built-in mathematical functions in Postgres that perform the modulo operation on two numbers and retrieves the remainder.

PostgreSQL offers several math functions such as ABS(), **MOD()** , ROUND(), etc. All these functions assist the users in performing mathematical operations conveniently and efficiently. If we talk about the **MOD()** function, it is one of the most frequently used mathematical functions that perform the modulo operation on two numbers and retrieves the remainder.

This post will teach you how to use MOD() Function in PostgreSQL using practical examples. So, let’s start.

 **How to Use MOD() Function in PostgreSQL?**

In Postgres, the **MOD()** function accepts two numbers as arguments, performs division on the given numbers, and retrieves the remainder.

 **Syntax:**

The below snippet will assist you in understanding the syntax of the **MOD()** function:
    
    
    MOD(num_1, num_2);

The syntax shows that the MOD() function takes two arguments: num_1 represents a dividend, and num_2 represents a divisor.

The MOD() function will perform the division on the given numbers and retrieves the remainder/quotient.

The divisor must be a non-zero; otherwise, the MOD() function will throw a “division by zero” error.

 **Example#1: Positive Integers**

In this example, we will pass two positive integers to the MOD() function, i.e., 150 and 7:
    
    
    SELECT MOD(150, 7);

The MOD() function retrieves the resultant remainder.

 **Example#2: Division BY Zero**

Let’s pass the 0 as a divisor:
    
    
    SELECT MOD(150, 0);

On passing 0 as a divisor, the MOD() function throws a "division by zero" error.

 **Example#3: Negative Divisor**

In this example, we will pass a positive dividend and a negative divisor to the MOD() function:
    
    
    SELECT MOD(170, -8);

The MOD() function retrieves the positive remainder.

 **Example#4: Negative Dividend**

Let’s pass a negative dividend and positive divisor to the MOD() function:
    
    
    SELECT MOD(-170, 8);

We can conclude from examples 3 and 4 that the dividend's sign determines the sign of the retrieved value.

 **Example#5: Positive Decimal Values**

In this example, we will see how the MOD() function deals with the decimal values:
    
    
    SELECT MOD(154.72, 12.14);

This is how the MOD() function works with decimal values.

 **Example#6: How to Use MOD() Function on Table’s Data?**

Let’s create a table “modulus_example” with two columns: first_number, second_number:
    
    
    CREATE TABLE modulus_example(
    first_number INT,
    second_number INT
    );

The modulus_example table with two integer type columns has been created successfully. Let’s insert some integers into the newly created modulus_example table:
    
    
    INSERT INTO modulus_example(first_number, second_number)
    VALUES (120, 7),
    (500, 8),
    (639, 4),
    (-72, 5),
    (-344, 11);

The specified values have been inserted into the modulus_example table. Let’s use the MOD() function to perform the modulus operation on the table’s data:
    
    
    SELECT first_number, second_number, 
    MOD(first_number, second_number) AS remainder
    FROM modulus_example;

This way, you can use the **MOD()** function on the table’s data to get the remainder values.

 **Conclusion**

The **MOD()** function is one of the most frequently used mathematical functions in Postgres that perform the modulo operation on two numbers and retrieves the remainder. It accepts two numbers as arguments, performs division on the given numbers, and retrieves the remainder. This write-up considered multiple use cases to explain the working of the MOD() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-mod-function-in-postgresql/)

---

# How to Use ANALYZE Command in PostgreSQL

> PostgreSQL offers a convenient command named ANALYZE that collects the statistics about a database, table, or table’s columns for the query planner.

In PostgreSQL, the **ANALYZE** command collects the statistics about a database, table, or table’s columns for the query planner. Afterward, the query planner utilizes that data to yield efficient/appropriate execution plans for the Postgres queries.

This post will present a detailed working mechanism and usage of the **ANALYZE** command through practical examples. So, let’s start.

 **Key Points**

Some key points regarding the ANALYZE command are listed below that will help you to understand the working of the ANALYZE command in a better way:

  * Postgres' ANALYZE command deals with the table or column contents; however, it does not read or update indexes.
  * While ANALYZE runs, other queries may access the table because the ANALYZE command does not block the table.



 **When to Use ANALYZE Command?**

ANALYZE is preferable in the following scenarios:

  * When a table's contents have changed significantly, run the ANALYZE command. For instance, adding, updating, or deleting a few percent of records in a particular table.
  * In order to generate the optimal query plan, run the ANALYZE command before or after adding an index to a particular table.



 **How to Read the ANALYZE Command Output?**

By using the VERBOSE option along with the ANALYZE command, you can emit progress messages indicating which table is currently being processed. Additionally, it assists us in printing the table’s stats.

 **How to Analyze All Databases Using the ANALYZE Command in Postgres?**

If the **ANALYZE** command gets executed successfully, it will return “ANALYZE”. Let’s learn how to use the **ANALYZE** command to get the statistics of all the databases. Firstly open the SQL SHELL and run the below command:
    
    
    ANALYZE;

 **How to Analyze a Specific Database Using the ANALYZE Command in Postgres?**

In Postgres, databases, tables, and columns are analyzed hierarchically using the ANALYZE command. So, to get the stats of some specific database, firstly, we must connect to that database, and then we can execute the **ANALYZE** command.

 **Example: How to Get Stats of Databases Using ANALYZE Command?**

This example shows how to get stats of the databases using the ANALYZE command in Postgres:

 **Step #1: List Databases**

Let’s execute the \l command to get the list of databases:
    
    
    \l;

 **Step #2: Connect to Database**

Suppose we want to get the stats of the “example” database. To do that, firstly, we will establish a connection with the selected database using the “\c” command:
    
    
    \c example;

 **Step #3: Get Stats of Specific Database**

We have successfully established a connection with the targeted database, i.e., “example”. Now, we can get the stats of the “example” database using the ANALYZE command:
    
    
    ANALYZE;

 **How to Analyze a Table Using ANALYZE Command in Postgres?**

To get the stats of a specific table, use the ANALYZE Command as follows:
    
    
    ANALYZE tab_name;

 **Example: How to Get Table’s Stats Using ANALYZE?**

Let’s execute the below command to see the tables available in the example database:
    
    
    \d

Suppose we want to get the stats of the article_details table. You can accomplish this by executing the ANALYZE command as follows:
    
    
    ANALYZE article_details;

 **How to Analyze Columns Using ANALYZE Command in Postgres?**

Follow the below syntax to learn how to get the stats of columns in Postgres:
    
    
    ANALYZE tab_name (col_1, col_2, …, col_n);

Here, tab_name represents the targeting table while col_1, col_2, … col_n are the columns whose data needs to be collected/analyzed.

 **Example: How to Get Stats of Columns Using ANALYZE Command?**

In this example, we will get the stats of two columns: article_title and published_date, using the ANALYZE command as follows:
    
    
    ANALYZE article_details(article_title, published_date);

This way, you can get the statistics of any database, table, or column using the ANALYZE command.

 **What is VERBOSE, and How to Use it With the ANALYZE Command?**

By default, ANALYZE command does not display any processing on the screen. However, if the VERBOSE option is used with the ANALYZE command, then the output will be in a more detailed format.

 **Example: How to Use VERBOSE Option With ANALYZE Command?**

In this example, we will get the detailed statistics of the article_details table using the ANALYZE command:
    
    
    ANALYZE VERBOSE article_details;

The VERBOSE option retrieves the detailed statistics of the targeted table:

  * The output indicates that there are twelve rows in the article_details table. All twelve rows are live, and there are zero dead rows in the selected table.



 **How to Use VACUUM With ANALYZE Command?**

In Postgres, the **VACUUM** command is used to reclaim the useless space by removing the dead/old records. The VACUUM and ANALYZE commands can be used combinedly to analyze the tables while vacuuming:
    
    
    VACUUM VERBOSE ANALYZE;

This is how the VACUUM command works with the ANALYZE command.

 **Conclusion**

PostgreSQL offers a convenient command named ANALYZE that collects the statistics about a database, table, or table’s columns for the query planner. The collected data can then be used by the query planner to yield efficient/appropriate execution plans for the Postgres queries. This post considered multiple use cases of the ANALYZE command through practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-analyze-command-in-postgresql/)

---

# A Tutorial on Logical Replication

> IntroductionOne vital aspect of database administration is making copies of data and ensuring the replications remain in sync. With PostgreSQL there are two fo…

## Introduction

One vital aspect of database administration is making copies of data and ensuring the replications remain in sync. With PostgreSQL there are two forms of native replication: **physical replication** , also known as binary replication, which sends changes at a disk block level and **logical replication** , which offers row-by-row changes streamed from a primary server to a secondary server. One of the major benefits of logical replication is that you may target certain tables instead of the entire database. This tutorial provides a guide for implementing logical replication between a primary and secondary server.

### Assumptions

This tutorial assumes that you are operating on a Linux OS, and the examples shown are specific to Ubuntu 20.04 LTS. It is also assumed that PostgreSQL is already installed on your server and data in the database already exists. The user performing commands should have sudo access to the postgres user.

### Variables

The primary server will have an example IP address of 198.168.0.1, and the secondary server will have an IP address of 198.168.0.2. The user, database, table, publication, subscription names, and target directories/files are examples and will need modification specific to you and your system.

____________________________________________________________________________

## Primary Server Procedure

### Step 1: Set Up the Replication Role

Let us begin by creating a role with replication privileges, as this is mandatory to carry out any replication procedures. First, we login as the postgres user and initiate the psql prompt to run the commands:

> sudo -iu postgres psql

Now, we create the role replicator with:

> CREATE ROLE replicator WITH REPLICATION LOGIN;

For security reasons, we don’t want the password stored anywhere in plain text and accessible to anyone with nefarious intentions, so we use the \password meta-command to conceal our password. First we set the superuser postgres’s password, as this will be needed for the data dumps:

> \password

Enter the password when prompted. Then for our replication user:

> \password replicator

Now, we exit the psql prompt and return to the system user:

> exit

### Step 2: Edit the Configuration File

We must edit the PostgreSQL configuration file (postgresql.conf) in order for replication of any data to occur. On Ubuntu 20.04 LTS, the configuration file is located in the /etc/postgresql/12/main directory. The 12 in the path name reflects the use of PostgreSQL 12 in this scenario; replace it with the version you are working with or the correct path to the configuration file on the OS you are using. We will open an editor with:

> sudo nano /etc/postgresql/12/main/postgresql.conf

The comment hash (#) must be removed from the beginning of each line we want to enable so the system will recognize it as an active setting. Find the line with listen_addresses and alter the text within quotes to be the IP address of the primary server, or a wildcard (*) to indicate that PostgreSQL will listen to all addresses it has access to. It will look something like this:

> listen_addresses = '198.168.0.1'

or

> listen_addresses = '*'

To keep the connection secure, we will set the encryption on passwords to md5. We do so by editing the password_encryption line to look like this:

> password_encryption = md5

The Write-Ahead Log (WAL) is the log of changes made to a database cluster to be used as part of the database recovery process or, as in this case, to replay changes in the database for replication. The wal_level setting determines how much information is written into the WAL file. We want enough information in the WAL file to perform logical replication, so we set wal_level to logical, like so:

> wal_level = logical

 **NOTE** : During the initial sync, the WAL files will build up on the primary. Additionally, any pause during logical replication will cause the WAL files to build up on the primary.

Now we will set the max_replication_slots to a minimum of the number of subscriptions that will connect, plus some reserve to account for table synchronization. This setting is not so easily changed on a running database because it will need a restart for changes to take effect, therefore it is often a good idea to set it a bit higher (the default of 10) to account for a growing system and future needs. Since we will only be connecting one subscription, we will set the value to 3 to account for synchronization:

> max_replication_slots = 3

The max_wal_senders setting should be equal to max_replication_slots, plus the number of physical replicas that will be connected simultaneously. Since we do not have any physical replicas connected, we also set this to 3:

> max_wal_senders = 3

Now that we have made the changes to this configuration file, we will save and exit the postgresql.conf file.

### Step 3: Edit the Host-Based Authentication File

Next, we need to allow access to the database via the PostgreSQL Host-Based Authentication configuration file (pg_hba.conf), which should be located in the same directory as postgresql.conf. Open the editor with:

> sudo nano /etc/postgresql/12/main/pg_hba.conf

The pg_hba.conf file has 5 fields that need to be filled out in order to authenticate a client to use PostgreSQL. They are the host type (TYPE), database name (DATABASE), user name (USER), IP address (ADDRESS), and encryption method (METHOD). In order to match connection attempts using TCP/IP, we set our TYPE to host. We enter all as the record for DATABASE to have access to all databases. We enter all under USER because the role we created and the superuser (postgres) will need access from the secondary. Under ADDRESS, we enter the IP address of the secondary server that will be accessing the database. Under METHOD, we enter the encryption method we are using, which is md5. Add the following line to pg_hba.conf:

> # TYPE DATABASE USER ADDRESS METHOD  
>   
>  host all all 198.168.0.2/32 md5

We have finished entering authentication information, so we will save and exit pg_hba.conf.

### Step 4: Restart/Reload PostgreSQL

For the changes made to postgresql.conf and pg_hba.conf to take effect, we must restart PostgreSQL. The systemd service unit name will vary depending on the OS and software package source you are using. In Debian (Ubuntu) and most Linux systems, we can do so with the systemctl command:

 **NOTE:** If you changed the listen_addresses or wal_level settings in postgresql.conf while following this tutorial, a restart will be required. Otherwise, you can simply reload the database for any other setting changes by replacing restart with reload in the following commands.

> sudo systemctl restart postgresql

It is likely to vary between systems and versions of PostgreSQL. For example, it is possible that you will need to use a command like this:

> sudo systemctl restart postgresql-12

Or perhaps something like this:

> sudo systemctl restart postgresql@12-main

In these examples, you would replace the 12 with the version you are working with.

 **Alternative Method:** To reload PostgreSQL from within, you can use the following command:

> SELECT pg_reload_conf();

### Step 5: Granting User Privileges

Now that we have a user role with replication privileges, we want to grant that user access to the data that we want to replicate. One of the beauties of logical replication is the ability to fully customize and target the data you are replicating without replicating everything. A full list of options for granting privileges can be found [here](<https://www.postgresql.org/docs/current/sql-grant.html>). Let’s first switch to our postgres user and psql prompt:

> sudo -iu postgres psql

Next, we need to connect the postgres user to the tutorial database with the \connect meta-command:

> \c tutorial

We will be granting connection privileges on the tutorial database and tables in the public schema to our user. We can do so with:

> GRANT CONNECT ON DATABASE tutorial TO replicator;  
> GRANT SELECT ON ALL TABLES IN SCHEMA public TO replicator;

### Step 6: Creating the Publication

In order for tables to be available for replication, we must publish them. The publication we create will serve as a master copy of the data for any subscription that is connected to it. Once we have created the publication, we will also alter the publication to include the table we will be replicating. This can be done like so:

> CREATE PUBLICATION best_pub;  
> ALTER PUBLICATION best_pub ADD TABLE first_table;

More tables can be added in the future with the same method. This concludes the configuration setup we need on the primary server.

Secondary Server Procedure

Now, let’s move to the secondary server for configuration and creating a subscription to the publication from the primary server.

### Step 7: Setting Up .pgpass

To increase fluidity for our replication process and prevent possible security breaches, we will store PostgreSQL user passwords in the .pgpass file. We want this file to be located in the postgres user’s home directory, which is /var/lib/postgresql in Debian-based systems and /var/lib/psql in Red Hat systems. Let’s create the file with:

> sudo touch /var/lib/postgresql/.pgpass

For postgres to use the .pgpass file, we must ensure postgres owns the file. For security purposes, we will restrict access to the file so only the postgres user can write on and read the file. We can change the ownership and change the mode of the .pgpass file with the following command:

> sudo chown postgres:postgres /var/lib/postgresql/.pgpass; sudo chmod 0600 /var/lib/postgresql/.pgpass

Now that its data is properly protected, Let’s open .pgpass with:

> sudo nano /var/lib/postgresql/.pgpass

You will see that the lines in this file follow the format:

> hostname:port:database:username:password

For simplicity, you can use wildcards (*) in the hostname, port, and database fields. The wildcards indicate that the username and password will be applicable to any hostname, port, or database to which the user has access. For this tutorial and our desired security levels, we will be more specific and explicitly name the hostname, port, and database for which the username and password will be applicable. Based on the user and password (iwonttell) used when creating the replication role, we will add this line:

> 198.168.0.1:5432:tutorial:replicator:iwonttell

Now let’s save and exit the file.

### Step 8: Copy Roles and Database Schema

Now that we have .pgpass configured where we are not entering passwords where they are visible, we want to pull the roles that have been previously set on the primary server. We can use the pg_dumpall with the roles-only (-r) option to accomplish this. The following command will create the roles.dmp file in the postgres home directory:

> sudo pg_dumpall -U postgres -r -h 198.168.0.1 -f /var/lib/postgresql/roles.dmp

Depending on your system, this may ask you for a password. It will be asking for the postgres user’s password.

Next, let’s take a dump of the tutorial schema using the options schema (-s) and custom format (-Fc), which will allow us to use pg_restore to recreate the schema on the secondary:

> sudo pg_dump -U postgres -Fc -h 198.168.0.1 -f /var/lib/postgresql/schema.dmp -s tutorial

 **Note:** When using RDS and other cloud providers, passwords will need to be reset on the secondary, as passwords do not transfer as part of the dump. Additionally, tablespaces are not taken into account during logical replication and sequences do not replicate in this process.

### Step 9: Recreate Roles and Database Schema

Now that we have our roles and schema copied from the primary, we will recreate them on the secondary, which will duplicate the replicator role and the framework of our table. Let’s first sign in as the postgres user:

> sudo -iu postgres

Next, we will call psql to unpack the roles.dmp file, and we can omit the file path since this prompt source is the PostgreSQL home directory:

> psql -f roles.dmp

Now, we will restore the contents of the schema.dmp file by connecting through the postgres database and using the create option (-C):

> pg_restore -d postgres -C schema.dmp

### Step 10: Creating the Subscription

Finally, we arrive at the subscription to the publication. We have already created the publication on the primary server, which makes the data we want to replicate available. Now, we need to subscribe to that publication in order to have access to the data. First, let’s go to the psql prompt and connect to the tutorial database we just recreated. Since you should be at the postgres user prompt, go to the psql prompt with:

> psql

Now, connect to the tutorial database with:

> \c tutorial

The CREATE SUBSCRIPTION parameter creates and names the subscription. The CONNECTION parameter defines details for our connection with the primary server. These details include host IP address, port number (5432 is the postgres default), password, user name, and database name. We will omit the password in our example, as we have set it for automatic application via the .pgpass file. And, the PUBLICATION parameter states the name of the publication we are subscribing to:

> CREATE SUBSCRIPTION best_sub CONNECTION 'host=198.168.0.1 port=5432 user=replicator dbname=tutorial' PUBLICATION best_pub;

Follow-Up Procedures

### Step 11: Confirm Successful Replication

Let’s confirm that the replication was successful. Run the following query at the psql prompt:

> SELECT * FROM first_table;

If the data on the secondary matches the data from the primary, the replication has been successful. Let’s make sure the data is streaming properly. Return to primary and insert some data into first_table:

> INSERT INTO first_table VALUES ('some data', 101);

Make sure the data was inserted properly (substitute data to match what you inserted):

> SELECT * FROM first_table WHERE first_column='some data';

Now, let’s return to secondary to make sure the changes have been made:

> SELECT * FROM first_table WHERE first_column='some data';

If the data matches the data from the primary, you have successfully set up streaming logical replication!

### Step 12: Monitor Replication

It is important to monitor the replication that you have set up because sometimes the primary or the secondary has a heavy load and may have trouble keeping up with data transfer. It is also important to diagnose and address any network related issues that might occur. From the psql prompt, for visual clarity let’s first create an expanded view format with the meta-command:

> \x

And now let’s look at the replication statistics from the primary. It should look something like this:

> SELECT * FROM pg_stat_replication;  
> -[ RECORD 1 ]----+------------------------------  
> pid | 21111  
> usesysid | 24576  
> usename | replicator  
> application_name | best_sub  
> client_addr | 198.168.0.2  
> client_hostname |  
>  client_port | 50330  
> backend_start | 2022-05-18 17:18:10.05812+00  
> backend_xmin |  
>  state | streaming  
> sent_lsn | 0/16776F8

> write_lsn | 0/16776F8

> flush_lsn | 0/16776F8

> replay_lsn | 0/16776F8

> write_lag | 00:00:00.000049  
> flush_lag | 00:00:00.00053  
> replay_lag | 00:00:00.000562

> sync_priority | 0

> sync_state | async

> reply_time | 2022-05-19 14:58:58.667474+00

Let’s briefly discuss what some of these mean. First of all, the record itself indicates that there is an active subscription and the state line that reads streaming indicates that it is actively streaming data. The lines with the labels ending with _lsn indicate the location on the secondary of the WAL file for each stage of replication; we will return to the sent_lsn momentarily. Also important are the lines with labels ending with _lag. These indicate the lag times for their respective tasks. All of these lag times are very low, but if they have high levels, you can pinpoint where delays occur in the process. The absence of values on these lines indicates that everything is in sync.

Now let’s take a look at the subscription statistics on the secondary. First, we make the layout easier to read with:

> \x

Now we run the query:

> SELECT * FROM pg_stat_subscription;  
> -[ RECORD 1 ]---------+------------------------------

> subid | 16399

> subname | best_sub

> pid | 21069

> relid |

> received_lsn | 0/16776F8

> last_msg_send_time | 2022-05-19 14:58:48.656812+00

> last_msg_receipt_time | 2022-05-19 14:58:48.656994+00

> latest_end_lsn | 0/16776F8

> latest_end_time | 2022-05-19 14:58:48.656812+00

We can see some important data points between the two queries. Again, the record itself indicates an active subscription. You’ll notice that the location of the latest_end_lsn on the secondary and the sent_lsn on the primary are identical, indicating that the two servers are in sync.

There are a host of other things we can look at for replication monitoring, but that is out of the scope of this tutorial. Perhaps there will be a future tutorial that covers these in more detail…

## Summary

And there you have it! This tutorial has covered configuration, publication, and subscription settings necessary for logical replication. This should offer a thorough understanding of how to set up logical replication using .pgpass and md5 for increased security. From now on, any changes made on the primary server via INSERT, UPDATE, and UPDATE will be reflected on the secondary server.

---
[View this page online](https://www.commandprompt.com/education/a-tutorial-on-logical-replication/)

---

# PostgreSQL Column Alias With Practical Examples

> In PostgreSQL, column aliases are temporary alternative names assigned to columns. The aliases are temporary alternatives, so they exist temporarily during the…

In Postgres, an Alias is a temporary replacement name for a column, table, view, etc. Column Aliases in PostgreSQL are temporary alternative names assigned to columns. Since the aliases are temporary alternatives, so they exist temporarily during the query’s execution.

We will discuss the below-mentioned concepts of the Column Aliases through practical examples:

  * What is a Column Alias, and How Does it Work in Postgres?
  * Rules For Column Alias.
  * Practical Demonstration of Column Alias.



So, let’s discuss all the concepts one by one.

 **What is a Column Alias, and How Does it Work in Postgres?**

The concept of Aliases is used during the query execution to assign a temporary alternative name to any table, column, view, etc. Using the column alias, we can assign a temporary name to a column or expression within the SELECT statement.

 **Syntax**

Column Alias has a pretty straightforward syntax, as shown in the below-given snippet:
    
    
    SELECT col_name AS alias_name
    FROM tab_name;

In the above syntax, alias_name is a column alias to be assigned to the col_name. The **“AS”** keyword is optional and can be skipped. The syntax of column alias without the “AS” keyword will be as follows:
    
    
    SELECT col_name alias_name
    FROM tab_name;

 **Rules For Column Alias**

  * Use column aliases in Postgres select lists.
  * In PostgreSQL, a column alias can be used along with the ORDER BY, or GROUP BY clause; however, it can't be used with the WHERE or HAVING clause.
  * By default, an alias will be in small letters. However, to specify special symbols, white spaces, mixed-case letters, etc., quotes must be used.



 **Practical Demonstration of Column Alias**

Let’s consider a couple of practical examples to demonstrate the working of the column aliases in PostgreSQL. But first, we will create a sample table:

 **Creating Sample Table**

Let’s create a table named emp_record with the following three columns: emp_id, emp_name, and emp_salary:
    
    
    CREATE TABLE emp_record(
    emp_id SERIAL PRIMARY KEY,
    emp_name TEXT,
    emp_salary INT);

Now, let’s insert some records into the emp_record table:
    
    
    INSERT INTO emp_record(emp_name, emp_salary)
    VALUES('JOE', 25000),
    ('JOHN', 35000),
    ('AMBROSE', 25000),
    ('ALEX', 45000),
    ('MIKE', 45000),
    ('SETH', 55000),
    ('DEAN', 50000),
    ('JONES', 50000),
    ('PAUL', 25000),
    ('KEVIN', 30000);

Ten records have been inserted into the emp_record table.

 **Example #1: How to Assign Column Alias to a Column in Postgres?**

Let’s run the below query to fetch the data of the emp_record column:
    
    
    SELECT * FROM emp_record;

We can utilize the column alias on any column of the above-given table to assign a temporary name to that column. For instance, we want to assign a new temporary name to the emp_name column. To do so, we will use the column alias as follows:
    
    
    SELECT emp_name AS name,
    emp_salary
    FROM emp_record;

This is how the column alias can be assigned to a column in Postgres. You can skip the AS keyword from the column alias:
    
    
    SELECT emp_name name,
    emp_salary
    FROM emp_record;

The output verified that skipping the **AS** keyword from the column alias doesn’t affect the performance/functionality of the column alias.

 **Example #2: How do I Assign Column Aliases to an Expression in PostgreSQL?**

On successful execution, the Postgres queries return a result set. Within the result set, sometimes the columns contain a meaningless name. In such cases, we can use the column aliases to provide a meaningful name to those columns:
    
    
    SELECT emp_name || ': ' || emp_salary 
    FROM emp_record;

In this query, we utilized the concatenation operator **“||”** to concatenate the emp_name and emp_salary columns of the emp_record table:

From the resultant table, you can observe that the column’s name (i.e., ?column?) is meaningless. To make it meaningful, we will utilize the column alias as follows:

The output shows that a meaningful name has been assigned to the column using the column alias.

 **Conclusion**

Column alias allows us to assign a temporary name to a column or expression within the SELECT statement. The concept of Aliases is used during the query execution to assign a temporary alternative name to any table, column, view, etc. Since the aliases are temporary alternatives, so they exist temporarily during the query’s execution. This post went through several practical examples to explain the working of the column aliases.

---
[View this page online](https://www.commandprompt.com/education/postgresql-column-alias-with-practical-examples/)

---

# How to Find Duplicate Rows in PostgreSQL

> PostgreSQL offers several built-in functions to find duplicate rows/records from a table, such as ROW_NUMBER() and COUNT().

In any database, including PostgreSQL, it is preferred to use a UNIQUE constraint on a table to avoid the duplication of the records. Occasionally, you may encounter a database with duplicate records due to human errors, bugs, or unclean data.

So, PostgreSQL offers several built-in functions to find **duplicate** rows/records from a table. This post will explain the below-listed methods that assist the users in finding the duplicate rows from a PostgreSQL table:

  * How to Find Duplicates Using **COUNT()** Function in Postgres?
  * How to Find Duplicates Using **ROW_NUMBER()** in Postgres?



So, let’s begin!

 **How to Find Duplicates Using COUNT() Function in Postgres?**

The built-in functions always bring ease for the users, and so does the **COUNT()** function. In Postgres, the [COUNT()](<https://commandprompt.com/education/how-to-use-count-function-in-postgresql/>) function counts the number of rows/records. It assists the users in finding duplicate records in a specific table.

 **Example: How to Find Duplicates Using COUNT() Function?**

In this example, we will present a step-by-step procedure to find duplicate records from a table:

 **Step #1: Create New Table**

We will [create a table](<https://www.commandprompt.com/education/different-methods-to-create-a-table-in-postgresql/>) named std_info using the CREATE TABLE as follows:
    
    
    CREATE TABLE std_info(
    std_id INT,
    std_name TEXT,
    std_age INT);

The output verifies that the std_info table with three columns has been created successfully.

 **Step #2: Insert Data Into Table**

Now we will utilize the [INSERT INTO](<https://www.commandprompt.com/education/how-to-use-insert-query-in-postgresql/>) statement to insert the data into the std_info table:
    
    
    INSERT INTO std_info(std_id, std_name, std_age)
    VALUES (1, 'SETH', 18),
    (4, 'AMBROSE', 21),
    (3, 'JOHN', 17),
    (1, 'SETH', 18),
    (2, 'JOE', 19),
    (1, 'SETH', 18),
    (1, 'SETH', 18),
    (3, 'JOHN', 17),
    (1, 'SETH', 18),
    (3, 'JOHN', 17);

The output verifies that ten records have been inserted into the std_info table. From the output, it can be seen that some records are duplicated.

 **Step #3: Find Duplicates Using Count()**

Let’s utilize the COUNT() function to find the duplicates from the std_info table:
    
    
    SELECT std_name, COUNT(*)
    FROM std_info
    GROUP BY std_name
    HAVING COUNT(*) > 1;

In the above given query, we used the COUNT(*) function to count the number of rows. Next, we used the Postgres GROUP BY clause to group the rows/records based on std_name. Finally, we utilized the COUNT(*) function within the HAVING clause to find the duplicates:

The output clarifies that the COUNT(*) function, with the aid of the HAVING clause, succeeded in finding the duplicate rows.

 **How to Find Duplicates Using ROW_NUMBER() in Postgres?**

Another convenient way of finding duplicates is the ROW_NUMBER() approach. In PostgreSQL, the ROW_NUMBER() method can be used with the collaboration of the PARTITION BY Clause to find the duplicate rows from a table.

 **Example: How to Find Duplicates Using ROW_NUMBER() Method?**

We will consider the same std_info table, and we will find the duplicate records from that table using the ROW NUMBER() method:
    
    
    SELECT DISTINCT * 
    FROM std_info WHERE std_name IN(
    SELECT std_name 
    FROM(SELECT std_name, ROW_NUMBER() OVER(PARTITION BY std_name) AS occurrences
    FROM std_info) AS duplicates
    WHERE duplicates.occurrences > 1);

In the above query, we utilized the ROW_NUMBER() function to assign a sequential number to each record in the result set. Moreover, we utilized the PARTITION BY clause to make smaller sets/partitions. Finally, in the where clause, we specified a condition to find the duplicates(row >1):

The output authenticates the working of the ROW_NUMBER() approach.

 **Conclusion**

PostgreSQL offers several built-in functions to find **duplicate** rows/records from a table, such as ROW_NUMBER() and COUNT(). In Postgres, the COUNT() function counts the number of rows/records and can be used to find duplicate records in a specific table. While the ROW_NUMBER() method can be used with the collaboration of the PARTITION BY Clause to find the duplicate rows from a table. Using practical examples, this post explained how to find duplicates from the PostgreSQL table.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-duplicate-rows-in-postgresql/)

---

# PostgreSQL ISNULL Function With Examples

> PostgreSQL doesn’t support the ISNULL function. To achieve the functionality of the ISNULL function in Postgres, COALESCE function and CASE expressions are use…

SQL server offers an inbuilt function named **ISNULL** that is used to replace the NULL values with some specific values. The **ISNULL** function accepts an expression and a replacement as arguments and replaces the occurrence of a null value with the specified replacement. However, **PostgreSQL** doesn’t support the **ISNULL** function. So, how to avail the functionality of the ISNULL function in PostgreSQL?

Through practical examples, this write-up will explain how to replace a NULL value with some specific value in PostgreSQL. To do that, this guide will explain the below-listed concepts:

  * SQL **ISNULL** Function: How Does It Work?
  *  **ISNULL** Equivalent in PostgreSQL?
  * How to Replace a Null Value With Some Specific Value Using **COALESCE()** Function?
  * How to Replace a Null Value With Some Specific Value Using **CASE** Expression?



So, let’s get started!

 **SQL ISNULL Function: How Does It Work?**

In SQL, use the following syntax for the ISNULL function:
    
    
    ISNULL(expression, replacement);

The syntax demonstrates that the ISNULL function accepts two arguments: an expression and a replacement. The ISNULL function will retrieve the specified replacement whenever a NULL value occurs, and it will retrieve the resultant expression for the non-null value.

 **ISNULL Equivalent in PostgreSQL?**

As discussed earlier, PostgreSQL doesn’t support the ISNULL function. So, the question is, does Postgres provide any equivalent of the ISNULL function? Yes! Postgres offers a COALESCE function that can assist us in such scenarios. Moreover, in Postgres, you can use the CASE expression to achieve the same functionality.

 **How to Replace a Null Value With Some Specific Value Using COALESCE() Function?**

The COALESCE function retrieves a first non-null value/argument. You can learn more about the COALESCE function from the following [link](<https://commandprompt.com/education/postgresql-coalesce-function-with-examples/>).

 **Basic Syntax**

You have to follow the below syntax to replace a NULL value with a value of your choice:
    
    
    COALESCE(expression,replacement);

 **Example: How to Use COALESCE() Function as Equivalent of ISNULL?**

Firstly, let’s utilize the SELECT statement to see the content of the emp_details table:
    
    
    SELECT * FROM emp_details;

From the output, it can be clearly seen that the emp_bonus column contains some null values. We can replace them with the value of our choice using the COALESCE() function:
    
    
    SELECT COALESCE(emp_bonus, 0)
    FROM emp_details;

Here, emp_bonus represents a column whose NULL values need to be replaced while ‘0’ is the replacement value. So, all in all, the COALESCE() function will find the NULL values in the emp_bonus column and replace all the occurrences of the NULL values with the “0”:

The result set proves the working of COALESCE() function.

 **How to Replace a Null Value With Some Specific Value Using CASE Expression?**

In Postgres, the CASE expression can be used to achieve the functionality of the ISNULL function. Use the below syntax to find and replace the Null values using the CASE expression:
    
    
    SELECT col_list, CASE 
    WHEN expression IS NULL 
    THEN replacement_value
    ELSE resultant_expression 
    END AS column_alias
    FROM tab_name;

 **Example: How to Use CASE Expression as Equivalent of ISNULL?**

We will utilize the same table’s column to depict the working of the CASE expression:
    
    
    SELECT emp_bonus, 
    CASE WHEN emp_bonus IS NULL
    THEN 0 
    ELSE emp_bonus 
    END AS modified_emp_bonus
    FROM emp_details;

The output authenticates the working of CASE Expression.

 **Conclusion**

SQL server offers an inbuilt function named ISNULL that is used to replace the NULL values with some specific values. However, PostgreSQL doesn’t support the ISNULL function. To achieve the functionality of the ISNULL function in Postgres, the COALESCE() function and CASE expressions are used. Through practical examples, this post explained how to avail the functionality of the ISNULL function using the CASE expression and COALESCE() function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-isnull-function-with-examples/)

---

# How to Use NULLIF Function in PostgreSQL

> NULLIF takes some arguments and returns a NULL value if both arguments are equal or if one of them is NULL, and it returns first argument if both arguments are…

PostgreSQL provides several functions to deal with the NULL values, such as COALESCE() function, **NULLIF()** function, etc. The **NULLIF** is one of the most frequently used conditional expressions that deal with the null values.

This post will elaborate on the below-listed concepts of the NULLIF() function:

  * What is NULLIF() and How to Use it in PostgreSQL?
  * Basic Syntax
  * How to Use NULLIF Function in PostgreSQL?



So, let’s get started!

 **What is NULLIF() and How to Use it in PostgreSQL?**

It is a built-in function in Postgres that accepts a couple of arguments and retrieves a NULL value if both arguments are equal or if either of the specified arguments is NULL. It retrieves the first argument if both arguments are not equal and both of the specified arguments are non-null.

 **Basic Syntax**

The below snippet illustrates the usage of the NULLIF() function in PostgreSQL:
    
    
    NULLIF(argument_1, argument_2);

 **How to Use NULLIF Function in PostgreSQL?**

The NULLIF() function can be better understood by implementing it practically. So, let’s do it!

 **Example #1: Both Arguments Are Equal**

Let’s consider the below snippet to learn how the NULLIF() function deals with the equal arguments:
    
    
    SELECT NULLIF('Hello', 'Hello');

The output clarifies that the NULLIF function retrieves “NULL” when both arguments are equal.

 **Example #2: Both Arguments are Different**

Let’s specify different values for both the arguments:
    
    
    SELECT NULLIF('Command', 'Prompt');

The output shows that the NULLIF() function retrieves the value of the first argument when both arguments have different values.

 **Example #3: How to Use NULLIF() Function on Table’s Data?**

Let’s create a new table named std_info with three columns: std_id, std_name, std_hobbies:
    
    
    CREATE TABLE std_info(
    std_id SERIAL PRIMARY KEY,
    std_name TEXT NOT NULL,
    std_hobbies TEXT
    );

The std_info table with three columns has been created successfully. Now we will insert some records into the std_info table using the INSERT INTO command:
    
    
    INSERT INTO std_info(std_name, std_hobbies)
    VALUES('Joe', 'Reading Books'),
    ('John', ''),
    ('Ambrose', 'Traveling'),
    ('Mike', NULL),
    ('Jones', 'Sports'),
    ('Seth', NULL');

Output states that six records have been inserted into the std_info table. Let’s run the SELECT command to fetch the newly inserted records of the std_info table:
    
    
    SELECT * FROM std_info;

The output depicts that the std_hobbies column has some null values. Let’s utilize the **NULLIF()** function with the collaboration of the **COALESCE()** function to replace the **‘ ’,** or **NULL** value with the “Watching TV” value in the std_hobbies column:
    
    
    SELECT std_id, std_name, std_hobbies, 
    COALESCE(NULLIF(std_hobbies, ''), 'Watching TV') AS updated_hobbies
    FROM std_info;

In the above-given statements, we used the NULLIF function to check whether any student had left the std_hobbies column as null or blank ‘ ’. If yes, then specify a value “Watching TV” in place of that record using the COALESCE() function:

The output authenticates the working of the NULLIF() function.

 **Conclusion**

The **NULLIF** is one of the most frequently used conditional expressions that deal with the null values. It accepts a couple of arguments and retrieves a NULL value if both arguments are equal or if either of the specified arguments is NULL. It retrieves the first argument if both arguments are not equal and both of the specified arguments are non-null. Through practical examples, this post explained what NULLIF is and how it works in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-nullif-function-in-postgresql/)

---

# PostgreSQL NOT EXISTS Operator With Practical Examples

> NOT EXISTS operator negates the working of the EXISTS operator. It returns TRUE if the subquery returns zero rows and FALSE if the subquery returns at least on…

In PostgreSQL, the **NOT EXISTS** operator negates the working of the [EXISTS](<https://commandprompt.com/education/postgresql-not-exists-operator-with-practical-examples/>) operator. This means the **NOT EXISTS** operator will return TRUE if the subquery retrieves zero row/record, and it will retrieve FALSE if the subquery returns one or more rows.

The following aspects of the Postgres “ **NOT EXISTS** ” operator will be discussed in this article with practical examples:

  * What Does the **NOT** **EXISTS** Operator Do in PostgreSQL?
  * What Does the **NOT EXISTS** Operator Return in Postgres?
  * Practical Implementation of Postgres **NOT EXISTS** Operator



So, let’s get started!

 **What Does the NOT EXISTS Operator Do in PostgreSQL?**

The syntax of the NOT EXISTS operator will be as follows:
    
    
    SELECT col_1
    FROM tab_1
    WHERE NOT EXISTS(
    SELECT 1 FROM tab_2
    WHERE col_2 = table_1.col_1);

The syntax shows that the **NOT EXISTS** operator receives a subquery as an argument, and it will check the existence of some specific records in that subquery.

 **What Does the NOT EXISTS Operator Return in Postgres?**

The **NOT EXISTS** operator retrieves a true or false:

  * If the specified subquery retrieves one or more than one record, then the result of the **NOT EXISTS** operator will be “FALSE”.
  * If the specified subquery doesn’t retrieve a record(i.e., zero rows), then the result of the **NOT EXISTS** operator will be “TRUE”.
  * If the specified subquery retrieves a NULL value, then the result of the **NOT EXISTS** Operator will be “FALSE”.



 **Practical Implementation of Postgres NOT EXISTS Operator**

Let’s implement the NOT EXISTS operator practically to get a profound understanding.

 **Example #1: How Does the NOT EXISTS Operator Work in Postgres?**

We have already created two tables named author_details and article_info in our database, whose details are depicted in the below-given snippets:
    
    
    SELECT * FROM author_details;

Let’s demonstrate the content of the article_info table:
    
    
    SELECT * FROM article_info;

From the output snippets, we can observe that the author_details table has six records, and the article_info table has eight records. Moreover, the author_id of the author_details table is a foreign key in the article_info table.

Suppose we want to find the authors whose experience is not more than two years:
    
    
    SELECT author_name, author_experience
    FROM author_details
    WHERE NOT EXISTS(SELECT 1
    FROM article_info
    WHERE article_info.author_id = author_details.author_id
    AND author_experience >2);

The subquery will check if the author’s experience is more than two years. If the specified subquery retrieves one or more than one record, then the result of the NOT EXISTS operator will be “FALSE”. Else it will return “TRUE”:

The output authenticates the working of the NOT EXISTS operator, i.e., it retrieves the result opposite to the EXISTS operator.

 **Example #2: How Does the NOT EXISTS Operator Deal With the NULL Value in Postgres?**

If the specified subquery retrieves a NULL value, then the result of the NOT EXISTS Operator will be “FALSE”:
    
    
    SELECT author_name, author_experience
    FROM author_details
    WHERE NOT EXISTS(SELECT NULL);

The result set proves that the EXISTS operator retrieves FALSE; hence the outer SELECT statement doesn’t retrieve any record.

 **Conclusion**

In PostgreSQL, the **NOT EXISTS** operator negates the working of the EXISTS operator. This means the **NOT EXISTS** operator will return TRUE if the subquery retrieves zero row/record, and it will retrieve FALSE if the subquery returns one or more rows. This post demonstrated the working of PostgreSQL NOT EXIST Operator with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-not-exists-operator-with-practical-examples/)

---

# PostgreSQL EXISTS Operator With Practical Examples

> In Postgres, the EXISTS operator takes a subquery as an argument and checks the existence of a record in the subquery. Consequently, it returns true or false.

In PostgreSQL, the **EXISTS** operator/clause checks the existence of a record within the subquery. It receives a subquery as an argument, and depending on the existence of the targeted row or record, it returns true or false.

The following aspects of the Postgres **EXISTS** operator will be discussed in this article with practical examples:

  * What Does the **EXISTS** Operator Do in PostgreSQL?
  * What Does the **EXISTS** Operator Return in Postgres?
  * Practical Implementation of Postgres **EXISTS** Operator



So, let’s learn the working of the EXISTS operator.

 **What Does the EXISTS Operator Do in PostgreSQL?**

Let's begin by understanding the syntax of the **EXISTS** operator:
    
    
    EXISTS(subquery);

The syntax illustrates that the **EXISTS** operator receives a subquery as an argument and checks the existence of some specific records in that subquery.

 **What Does the EXISTS Operator Return in Postgres?**

The EXISTS operator retrieves a true or false:

  * If the specified subquery retrieves one or more than one record, then the result of the EXISTS operator will be “TRUE”.
  * If the specified subquery doesn’t retrieve a record(i.e., zero rows), then the result of the EXISTS operator will be “FALSE”.
  * If the specified subquery retrieves a NULL value, then the result of EXISTS Operator will be “TRUE”.



 **Practical Implementation of Postgres EXISTS Operator**

Until now, we've covered the theoretical part of the Postgres EXISTS operator; now it's time to put it into practice.

 **Example #1: How Does the EXISTS Operator Work in Postgres?**

We have two tables in our database named author_details and article_info. Let’s illustrate the content of each table one-by-one:
    
    
    SELECT * FROM author_details;

The result set shows that the author-details table consists of six records. Let’s run the SELECT query to depict the article_info table:
    
    
    SELECT * FROM article_info;

Suppose we want to find authors who have published at least one article and whose experience is greater than or equal to 2 years. For this purpose, we will use the **EXISTS** operator as follows:
    
    
    SELECT author_name, author_experience
    FROM author_details
    WHERE EXISTS(SELECT 1
    FROM article_info
    WHERE article_info.author_id = author_details.author_id
    AND author_experience >= 2);

  * The subquery will check if the author has published at least one article (i.e., article_info.author_id = author_details.author_id) and if the author’s experience is more than two year.
  * The subquery will return true if at least one author satisfies both conditions.
  * The main/outer SELECT query will show the name and experience of all those authors who satisfies both conditions:



The result set proves the working of the EXISTS operator.

 **Example #2: What if the EXISTS Operator Returns False?**

Suppose we want to find authors who have published at least one article and whose experience is greater than five years. To do this, we will utilize the **EXISTS** operator as follows:
    
    
    SELECT author_name, author_experience
    FROM author_details
    WHERE EXISTS(SELECT 1
    FROM article_info
    WHERE article_info.author_id = author_details.author_id
    AND author_experience >5);

The output states that there is not a single author who fulfills the specified criteria.

 **Example #3: How Does the EXISTS Operator Deal With the NULL Value in Postgres?**

As discussed earlier, if the specified subquery retrieves a NULL value, then the result of EXISTS Operator will be “TRUE”. The below snippet will validate this concept:
    
    
    SELECT author_name, author_experience
    FROM author_details
    WHERE EXISTS(SELECT NULL);

The result set proves that the EXISTS operator retrieves TRUE, and the SELECT statement fetches the records accordingly.

 **Conclusion**

In PostgreSQL, the **EXISTS** operator/clause is used to check the existence of a record within the subquery. It receives a subquery as an argument and checks the existence of some specific records in that subquery. EXISTS is a Boolean operator, so it retrieves either true or false based on the existence of the row/record within the subquery. This post demonstrated the working of PostgreSQL EXIST Operator with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-exists-operator-with-practical-examples/)

---

# PostgreSQL Else If Statement With Examples

> In Postgres, the ELSIF is one of the decision-driven statements that evaluate several conditions. It checks/evaluates each condition one by one.

PostgreSQL offers several decision-making statements such as **IF** , **IF-THEN-ELSE** , **IF-THEN-ELSIF** , etc. All these decision-driven statements are used to control the flow of the SQL statements based on specific criteria. In Postgres, the [IF](<https://www.commandprompt.com/education/postgresql-if-statement-with-examples/>) and [IF-THEN-ELSE](<https://www.commandprompt.com/education/postgresql-if-else-statement-with-examples/>) statements evaluate only one condition; however, the **IF-THEN-ELSIF** statement evaluates several conditions.

This write-up will discuss the working of the IF-THEN-ELSIF statement through practical examples. So, let’s start.

 **How Does the ELSE IF Statement Work in PostgreSQL?**

 **IF-THEN-ELSIF** is one of the decision-driven statements that evaluate several conditions.

  * The IF THEN ELSIF statement checks/evaluates each condition one by one.
  * When a condition becomes true, all the statements associated with that condition will get executed, and the rest of the conditions will be skipped.
  * If none of the specified conditions retrieve a true value, then the statements associated with the else part will get executed.



 **Syntax**

The below snippet elaborates the syntax of the IF-THEN-ELSIF statement:
    
    
    IF condition_1 THEN
    Statements;  //gets executed only if condition_1 retrieves true.
    ELSIF condition_2 THEN
    Statements;  //gets executed only if condition_2 retrieves true.
    ...
    ELSIF condition_n THEN
    Statements; //gets executed only if condition_n retrieves true.
    ELSE
    Statements; //gets executed only if all the provided conditions retrieve false.
    END IF;

 **Example #1: How to Use IF-THEN-ELSIF Statement in Postgres?  
** Let’s create two variables and assign them some random values:
    
    
    DO $$
    DECLARE
    first_val INT := 72;
    second_val INT := 50;
    BEGIN
    IF first_val < second_val THEN
    RAISE NOTICE 'first_val is less than second_val';
    ELSIF first_val > second_val THEN
    RAISE NOTICE 'first_val is greater than second_val';
    ELSE
    RAISE NOTICE 'first_val is equal to second_val';
    END IF;
    END $$;

In this example, we created two variables named first_val and second_val. We assigned them integer values. Afterward, we utilized conditional statements to compare their values:

  * In the if statement, we checked whether the first_val < second_val; if yes, then show the message “first_val is less than second_val”.
  * Else if the first_val > second_val; then return “first_val is greater than second_val”.
  * Else raise a notice “first_val is equal to the second_val”.



The output shows that the condition specified in the ELSIF part retrieves a true value, so the statement associated with the ELSIF part gets executed.

 **Example #2: How to Use ELSIF Statement on Table’s Data?**

We have created a table named student_info and inserted the following records into it:
    
    
    SELECT * FROM student_info;

Now we will specify the following five scenarios in the control statements:

  * If std_age <= 18 and std_gender = M then show “Teenage Male”.
  * If std_age <= 18 and std_gender = F then show “Teenage Female”.
  * If std_age > 18 and std_gender = M then show “Adult Male”.
  * If std_age > 18 and std_gender = F then show “Adult Female”.
  * If none of the above-given conditions return true, then show a notice "student with the specified id doesn't exist in the student_info table".


    
    
    DO $$
    DECLARE
    student_data student_info%rowtype;
    BEGIN  
    SELECT * FROM student_info
    INTO student_data
    WHERE std_id = 3;
    IF student_data.std_age <=18 AND student_data.std_gender= 'M' THEN
    RAISE NOTICE 'Teenage Male';
    ELSIF student_data.std_age > 18 AND student_data.std_gender= 'M' THEN
    RAISE NOTICE 'Adult Male';
    ELSIF student_data.std_age <=18 AND student_data.std_gender= 'F' THEN
    RAISE NOTICE 'Teenage Female';
    ELSIF student_data.std_age >18 AND student_data.std_gender= 'F' THEN
    RAISE NOTICE 'Adult Female';
    ELSE
    RAISE NOTICE 'Student with the specified id does not exist in the student_info table';
    END IF;
    END $$

Since the student having id 3 is a 19-year-old male, so, the ELSIF statement that satisfies the given condition retrieves a notice “Adult Male”.

 **Conclusion**

In Postgres, the ELSIF is one of the decision-driven statements that evaluate several conditions. It checks/evaluates each condition one by one. When a condition becomes true, all the statements associated with that condition will get executed, and the rest of the conditions will be skipped. If none of the specified conditions retrieve a true value, then the statements associated with the else part will get executed. Through practical examples, this post explained the working of Postgres ELSE IF statement.

---
[View this page online](https://www.commandprompt.com/education/postgresql-else-if-statement-with-examples/)

---

# PostgreSQL If Else Statement With Examples

> In Postgres, the if statement checks a condition/criteria and returns true or false. If statement doesn’t handle the false condition. To handle the false condi…

PostgreSQL offers some control statements such as **“if”** , **“if then else”** , and **“if then elsif”** that are used to control the flow of a program. These statements are also known as conditional statements or control statements. All these statements execute a command or set of commands based on a specific condition.

This write-up will teach us how to use the **if then else** statement in PostgreSQL with the help of practical examples.

 **How to Use If Else Statements in PostgreSQL?**

In Postgres, the [if statement](<https://www.commandprompt.com/education/postgresql-if-statement-with-examples/>) checks a condition/criteria and returns true or false. In PostgreSQL, when a condition is false, the if statement does not handle it. Therefore, to handle the false conditions, the else statement is used in Postgres.
    
    
    if condition then
    statements/commands;
    else
    alternate-statements/commands;
    END if;

The syntax illustrates that the statements/commands affiliated with the if statement will execute only if the given condition/expression is true. However, the statements specified within the else block will get executed when the given condition is false.

Let’s understand it practically.

 **Example #1: How Does the IF Else Statement Work in Postgres?**

Let’s create a variable “std_age” and assign it some values. Next, the if statement will get executed to check if the given condition is true or not. The notice “student under 18” will appear if the specified condition is true, else you will see a notice “student over 18”:
    
    
    DO $$
    DECLARE std_age INT:= 20;
    BEGIN
    IF std_age <= 18 THEN
    RAISE NOTICE 'student under 18';
    ELSE
    RAISE NOTICE 'student over 18';
    END IF;
    END $$;

The specified condition was false, so the else part gets executed.

 **Example #2: How Does the IF Else Statement Work on Table’s Data?**

We have created a table named bike_details, whose details are shown in the following snippet:
    
    
    SELECT * FROM bike_details;

If a bike with white color exists in the targeted table, then we will replace/update it with blue. Else if the white bike doesn’t exist in the bike_details table, then we will insert a new bike having a blue color:
    
    
    DO $$
    BEGIN
    IF EXISTS (SELECT FROM bike_details WHERE bike_color='White') THEN
    UPDATE bike_details SET bike_color='Blue' WHERE bike_color='White';
    ELSE
    insert into bike_details values (12,'Blue',2022,'ABC 111','2022-08-25','160000');
    END IF;
    END $$;

Let’s check the updated records using the below command:
    
    
    SELECT * FROM bike_details;

The updated table proves that all the white bikes have been updated to blue color. Now in the bike_details table there is no bike that has a white color.

Let’s run the following statement one more time to see how the if-else statement deals with the false condition:
    
    
    DO $$
    BEGIN
    IF EXISTS (SELECT FROM bike_details WHERE bike_color='White') THEN
    UPDATE bike_details SET bike_color='Blue' WHERE bike_color='White';
    ELSE
    insert into bike_details values (12,'Blue',2022,'ABC 111','2022-08-25','160000');
    END IF;
    END $$;

In this example, there is not a single bike having white color, so this time **else** part will get executed, and hence a new record will be inserted into the bike_details table:

Let’s check the updated content of the bike_details table using the below command:
    
    
    SELECT * FROM bike_details;

A new record has been inserted into the bike_details table. It proves that this time the else part gets executed.

 **Conclusion**

In Postgres, the **if statement** checks a condition/criteria and returns true or false. In Postgres, the if statement doesn’t handle the false condition. To handle the false conditions, the **else statement** is used in PostgreSQL. Therefore, the statements/commands affiliated with the if statement will execute only if the given condition/expression is true. However, the statements specified within the else block will get executed when the given condition is false. This write-up considered various examples to explain the working of the if else statement.

---
[View this page online](https://www.commandprompt.com/education/postgresql-if-else-statement-with-examples/)

---

# PostgreSQL Upsert Using INSERT ON CONFLICT Statement

> In PostgreSQL, the upsert feature is used either to update existing records or insert new ones into a table. The upsert feature is implemented using the INSERT…

PostgreSQL offers an **Upsert** feature that allows us to execute an insert or update operation. In other databases, the upsert feature is known as merge. This is because the **upsert** feature combines update and insert queries, and hence using the upsert feature, you can update an already existing record, or you can insert a new record into the targeted table.

In PostgreSQL, the upsert feature can be implemented with the aid of the **INSERT ON CONFLICT** statement.

This write-up will show you how to perform insert or update operations using the Postgres upsert feature with examples. So, let’s start!

 **How to Use INSERT ON CONFLICT Statement in Postgres?**

Here is the syntax of the **INSERT ON CONFLICT** statement:
    
    
    INSERT INTO tab_name(col_1, col_2,..., col_N) 
    VALUES(val_1, val_2,..., val_N)
    ON CONFLICT target action;

Let’s describe the above-given query step-by-step:

\- “ **INSERT INTO** ” is a query used along with the “ **ON CONFLICT target action** ” clause to insert or update the table’s data.

\- In place of “target”, you can specify a column name, a unique constraint using ON CONSTRAINT, or a WHERE clause with a predicate.

\- In Place of the “action”, you can specify DO NOTHING or DO UPDATE; the DO UPDATE clause will modify some specific fields in the given table based on the condition.

 **Example #1: INSERT ON CONFLICT DO NOTHING**

To understand the working of **upsert** , follow the below-given step_wise guidelines:

 **Step # 1: Create Table**

Firstly, create a table named emp_details:
    
    
    CREATE TABLE emp_data(
    emp_id INT UNIQUE,
    emp_name TEXT,
    emp_email VARCHAR NOT NULL);

The above-given query will create a table named emp_data with three columns: emp_id, emp_name, and emp_email.

\- The emp_id column will accept a unique integer value.

\- emp_name column will accept the string type data.

\- emp_email column will accept only unique emails because we utilized the UNIQUE constraints for the emp_email column.

A table named emp_data has been created successfully.

 **Step #2: Insert Data**

Let’s insert some data into the emp_data table using the INSERT command:
    
    
    INSERT INTO emp_data(emp_id, emp_name, emp_email)
    VALUES (1, 'Joe', 'joe123@abc.com'),
    (13, 'John', 'john123@abc.com'),
    (10, 'Mike', 'mike123@abc.com'),
    (7, 'Seth', 'seth123@abc.com'),
    (3, 'Bob', 'bob123@abc.com');

Five rows have been inserted into the emp_data table.

 **Step #3: Understanding DO NOTHING**

Specifying the “DO NOTHING action” within **INSERT ON CONFLICT** statement will perform one of two functionalities:

\- If the specified record doesn’t exist in the table, then the INSERT ON CONFLICT will insert that record into the targeted table.

\- If the specified record already exists in the table, then the INSERT ON CONFLICT statement will ignore that record and do nothing.

 **Scenario #1: Record Doesn’t Exist:**

Here's how the **INSERT ON CONFLICT** statement works if the specified record does not exist in the target table:
    
    
    INSERT INTO emp_data(emp_id, emp_name, emp_email)
    VALUES(2, 'ambrose', 'ambrose21@xyz.com') 
    ON CONFLICT (emp_id) 
    DO NOTHING;

The output clarifies that one record has been inserted into the emp_data table.

 **Scenario #2: Record Already Exist:**

Suppose “Bob” wants to change his email address from “bob123@abc.com” to “bob321@xyz.com”. Let’s use the upsert feature using “ **INSERT ON CONFLICT** ” as follows:
    
    
    INSERT INTO emp_data(emp_id, emp_email)
    VALUES(3, 'bob321@xyz.com') 
    ON CONFLICT (emp_id) 
    DO NOTHING;

In this example, we specified “emp_id” in the ON CONFLICT clause and “DO NOTHING” in place of action. So, if the specified emp_id already exists in the given table, then the “INSERT ON CONFLICT” statement will do nothing.

In the INSERT ON CONFLICT command, specifying the “DO NOTHING” action ignored the specified value and did nothing.

 **Learning Outcomes:**

From the respective outputs, we can conclude that if you specify the “DO NOTHING” action in the “INSERT ON CONFLICT” statement, then:

\- Either the specified record will be inserted(if it does not exist in the table) into the targeted table.

\- Or the INSERT ON CONFLICT statement will ignore the specified record(if a record already exists).

\- The record that already exists wouldn’t be updated.

 **Example #2: INSERT ON CONFLICT DO UPDATE**

To update the existing data, specify the “DO UPDATE” in place of action in the INSERT ON CONFLICT statement:
    
    
    INSERT INTO emp_data(emp_id, emp_name, emp_email)
    VALUES(3, 'bob', 'bob321@xyz.com') 
    ON CONFLICT (emp_id) 
    DO UPDATE SET emp_email = EXCLUDED.emp_email;

Run the SELECT statement to see the updated record:
    
    
    SELECT * FROM emp_data;

The output shows that specifying the DO UPDATE action within the INSERT ON CONFLICT statement updated the selected record.

 **Conclusion**

In PostgreSQL, the upsert feature is used either to update the already existing records or to insert new records into a table. The upsert feature is implemented using the INSERT ON CONFLICT statement. Within the INSERT ON CONFLICT statement, the action determines what to do, i.e. either update the record or insert the new record. This write-up taught us how to use the upsert feature using the INSERT ON CONFLICT statement.

---
[View this page online](https://www.commandprompt.com/education/postgresql-upsert-using-insert-on-conflict-statement/)

---

# PostgreSQL Copy Table With Practical Examples

> PostgreSQL allows us to copy an existing table with or without data. In Postgres, either you can copy only the structure of an existing table, or you can copy …

PostgreSQL allows us to copy an existing table with or without data. In Postgres, either you can copy only the structure of an existing table, or you can copy a table completely along with its data. To copy only the table’s structure, you must specify a WITH NO DATA clause.

This write-up will demonstrate how to copy a table with or without data in PostgreSQL. So, let's start.

 **PostgreSQL: How to Copy a Table?**

Let’s learn how to copy the table’s data in PostgreSQL. To do this, firstly, you need to understand the following syntax:
    
    
    CREATE TABLE new_tab_name AS 
    TABLE existing_tab_name;

By following the above syntax, the data of the existing table will be copied to the new table.

 **Example: How to Copy Entire Table’s Data in Postgres?**

We have created a student_info table whose details are shown in the following snippet:
    
    
    SELECT * FROM student_info;

Let’s run the following query to copy the data of the student_info table to a new table named student_record:
    
    
    CREATE TABLE student_record AS 
    TABLE student_info;

Let’s run the SELECT command to fetch all the records of the newly created student_record table:
    
    
    SELECT * FROM student_record;

From the output, it is clear that all the records of student_info have been copied to the student_record table.

 **How to Copy Only Specific Table’s Record in PostgreSQL?**

To partially copy the data of one table to another, use the WHERE clause as follows:
    
    
    CREATE TABLE new_tab_name AS 
    SELECT * FROM existing_tab_name
    WHERE condition;

By following the above syntax, only those records will be copied to the new table, which satisfies the given condition.

 **Example: How to Copy Partial Data From a Table?**

Suppose we want to copy the details of only those students who are above 18 years. To do so, we will copy the specific records from the student_info table to the selected_student table as follows:
    
    
    CREATE TABLE selected_student AS 
    SELECT * FROM student_info
    WHERE std_age > 18;

Let’s execute the SELECT command to fetch the filtered/copied data:
    
    
    SELECT * FROM selected_student;

The output shows that partial data has been copied to the seleted_student table.

 **How to Copy Only Table’s Structure in PostgreSQL?**

If you need to copy the table’s structure without copying the table’s data, then you have to use the WITH NO DATA clause as follows:
    
    
    CREATE TABLE new_tab_name AS 
    TABLE existing_tab_name
    WITH NO DATA;

Let’s implement it practically to get more clarity.

 **Example: How to Copy Only Structure of a Table in Postgres?**

Suppose we have to copy only the table’s structure; to do that, we will use the WITH NO DATA clause as follows:
    
    
    CREATE TABLE student AS 
    TABLE student_info
    WITH NO DATA;

Let’s utilize the SELECT statement to see the structure of the student table:
    
    
    SELECT * FROM student;

The output authenticates that the structure of the student_info table has been successfully copied to the student table.

 **Conclusion**

PostgreSQL allows us to copy an existing table with or without data. In Postgres, either you can copy only the structure of an existing table, or you can copy a table completely along with its data. You can also copy partial data of a table using the WHERE clause. To copy only the table’s structure, you must specify a WITH NO DATA clause. This post considered various examples to explain how to copy a table in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-copy-table-with-practical-examples/)

---

# PostgreSQL SUBSTRING() Function - How to Extract a Substring From a String

> PostgreSQL provides a built-in function named SUBSTRING() that extracts a substring from any specific string. The SUBSTRING() function accepts three parameters…

PostgreSQL provides a built-in function named **SUBSTRING()** that extracts a substring from any specific string. The **SUBSTRING()** function accepts three parameters: a string, starting position, and length. The starting position” and “length” parameters are optional that can be skipped depending on the situation.

This write-up will present a detailed overview of extracting a substring from a string using the PostgreSQL **SUBSTRING()** function. So, let's get started.

 **How to Use SUBSTRING() Function in PostgreSQL?**

The following snippet illustrates the syntax of the Postgres SUBSTRING() function:
    
    
    SUBSTRING(str [from <start_ind>] [for <len>]);

Here,

\- str represents a string.

\- start_ind represents a starting position(from where the string extraction will start).

\- len represents the length of the sub-string(sequence of characters) to be extracted.

 **Example #1: How Does SUBSTRING() Function Work in Postgres?**

Suppose we have to get the six characters from a string “commandprompt”. The sub-string should be extracted from the 8th index:
    
    
    SELECT SUBSTRING('commandprompt' from 8 for 6);

The above query will return a substring starting from the 8th index, and it consists of 6 characters:

The output proves that the SUBSTRING() function extracted the desired substring from the given string.

 **Example #2: Use SUBSTRING() Function Without Length Parameter?**  
Omitting the length parameter will extract a substring from the specified starting position to the last position:
    
    
    SELECT SUBSTRING('commandprompt', 8);

This time, we didn’t specify the length parameter, so the SUBSTRING() function extracted the desired substring from the specified index to the last index of the string.

 **Example #3: How to Use the SUBSTRING() Function on Table’s Data?**

We have a table named bike_details that contains the following content:
    
    
    SELECT * FROM bike_details;

Suppose we want to display the bike_model and the first three characters of bike_color. To do so, we will SUBSTRING() Function as follows:
    
    
    SELECT bike_model,
    SUBSTRING(bike_color,1,3) as bike_color
    FROM bike_details;

In this way, you can extract a substring from a table’s data using the SUBSTRING() function.

 **Example #4: How to Use ORDER BY Clause With the SUBSTRING() Function?**

In this example, we will show you how to use the SUBSTRING() function with the ORDER BY clause:
    
    
    SELECT bike_model,
    SUBSTRING(bike_color,1,3) as bike_color
    FROM bike_details
    ORDER BY bike_color;

This is how the SUBSTRING() function works in PostgreSQL.

 **Conclusion**

PostgreSQL provides a built-in function named SUBSTRING() that extracts a substring from any specific string. The SUBSTRING() function accepts three parameters: a string, starting position, and length. The “starting position” and length parameters are optional. The starting position determines where the string extraction will start, while the length parameter describes the number of characters to be extracted. This post taught us how the working of SUBSTRING() function with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-substring-function-how-to-extract-a-substring-from-a-string/)

---

# Connecting PostgreSQL Using psql and pgAdmin

> Installing the PostgreSQL on your machine will also install a couple of very handy tools, such as pgAdmin, and SQL SHELL. pgAdmin is a web-based GUI tool, whil…

[Installing the PostgreSQL](<https://commandprompt.com/education/how-to-download-and-install-postgresql/>) on your machine will also install a couple of very handy tools, such as pgAdmin, and SQL SHELL. pgAdmin is a web-based GUI tool, while psql is a terminal-based tool. Both these tools assist us in working with Postgres.

This write-up will assist the beginners who have installed **PostgreSQL** on their PCs and are now looking to establish a **connection** to it. This post will cover the following topics:

  * Connecting to a Postgres Database Server Using psql.
  * Connecting to a Postgres Database Server Using pgAdmin.



So, what are you waiting for? Let’s start!

 **Connecting to a Postgres Database Server Using psql**

SQL SHELL, or psql for short, is an open-source, terminal-based, cost-effective, secure, and scalable tool that allows us to execute queries/commands interactively.

Here are the stepwise instructions that will assist you in establishing a connection with the Postgres database server via psql:

 **Step #1: Launch the SQL SHELL**

Firstly, you need to open the psql to avail any of its functionality. For this purpose, type psql in the Windows search bar and click on the respective app to open it:

Clicking on the targeted app will open the following window:

 **Step #2: Provide the Required Details**

Now, provide all the required information, such as server address, database name, port number (default port number is 5432), user name, and password. Press enter if you did not change the default values during installation; as a result, SQL SHELL will pick the default values for each field. Finally, specify the password that you set during the PostgreSQL installation:

 **Step #3: Interact With the Database Server**

Upon connecting to the Postgres Database Server, you can execute any statement/command. The below statement will show you the list of available databases:

Similarly, you can execute any statement of your choice depending on the situation. For instance, run the below-given command to see the Postgres version:
    
    
    SELECT VERSION();

This way, you can issue any statement of your choice.

 **Connecting to a Postgres Database Server Using pgAdmin**

Another way to connect to a PostgreSQL database server is by using pgAdmin. It is a management tool for Postgres that allows us to interact with the Postgres database server through an interactive user interface.

Let’s learn the step-by-step procedure to connect to a Postgres database using pgAdmin:

 **Step #1: Launch the pgAdmin**

Firstly, type the pgAdmin in the Windows search bar and then click on the respective app to open it:

Clicking on the desired app will open the following window:

Provide the superuser password that you set during the Postgres installation, and then click on the OK button.

 **Step #2: Register Server**

Now, right-click on the “servers” node, then select register > server:

Clicking on the server will open a new window:

Specify the server’s name and then click on the Connection tab to provide the hostname/address and super user password:

Clicking on the save button will register the server.

 **Step #3: Interact With the Database Server**

Now, in order to interact with the database server, you need to open the query tool. To do this, right-click on the desired database and then the query tool:

Clicking on the query tool will lead you to the following window:

Here, you can specify any statement of your choice. For example, to check the Postgres version, you can execute the following command from the query tool:
    
    
    SELECT VERSION();

That was all the required information that you need to learn in order to connect to a database server using psql or pgAdmin.

 **Conclusion**

In PostgreSQL, we can connect to the database server using the SQL SHELL(psql) or pgAdmin. For instance, connecting to PostgreSQL using psql involves the following steps: launch psql > provide the required details like server address, port number, password, etc. > interact with Postgres by executing any query of your choice. In order to connect to Postgres using pgAdmin, you have to launch the pgAdmin, then create/register the database server by providing the required details and finally open the query tool to execute the statements/queries of your choice. This write-up explained how to connect to Postgres using psql and pgAdmin.

---
[View this page online](https://www.commandprompt.com/education/connecting-postgresql-using-psql-and-pgadmin/)

---

# PostgreSQL AGE() Function With Examples

> The AGE() function takes two timestamps as arguments, subtracts the second timestamp from the first one, and retrieves the resultant interval.

Calculating age is a very common task in our daily lives. For instance, in commercial applications, we frequently need to determine ages, such as people's age, years of service, etc. In Postgres, the AGE() function can be used to carry out these activities. It accepts two dates/timestamps and calculates the number of years, months, and days.

This post will teach us how to use the AGE() function in PostgreSQL.

 **How Does AGE() Function Work in PostgreSQL?**

The AGE() function takes two timestamps as arguments, subtracts the second timestamp from the first one, and retrieves the resultant interval. The basic syntax of the AGE() function will look like this:
    
    
    AGE(First_TIMESTAMP, Second_TIMESTAMP);

 **Example #1: How to Use the AGE() Function in Postgres?**

In this example, we will pass two timestamps as arguments to the AGE() function:
    
    
    SELECT AGE('2018-12-12','2000-01-10');

The output verifies that the AGE() function returns the appropriate results.

 **Example #2: How to Use CURRENT_DATE Function With AGE() Function in Postgres?**

Suppose we want to find the age of an employee whose birth date is “1990-01-10”. To do so, we can utilize the CURRENT_DATE() function with the AGE() function as follows:
    
    
    SELECT AGE(CURRENT_DATE, '1990-01-10');

The above snippet proves the working of the AGE() function, as it retrieves accurate results.

 **Example #3: How to Calculate the Age From the Current Date in Postgres?**

You can find the age between the current date and the specified date by simply specifying the TIMESTAMP as follows:
    
    
    SELECT AGE(TIMESTAMP '2000-01-01');

This is how you can find the age between the current date and the specified date.

 **Example #4: How to Use AGE() Function on Table’s Data in Postgres?**

We have created a table named student_bio that consists of the following records:
    
    
    SELECT * FROM student_bio;

Let’s say we have to find the Age of each student. To do so, we will use the AGE() function as follows:
    
    
    SELECT std_name, AGE(CURRENT_DATE, std_dob) 
    FROM student_bio;

The AGE() function successfully returned the age of each student.

 **Conclusion**

In PostgreSQL, the AGE() function accepts two dates/timestamps and calculates the number of years, months, and days. The AGE() function takes two timestamps as arguments, subtracts the second timestamp from the first one, and retrieves the resultant interval. This write-up considered some practical examples to explain the working of the PostgreSQL AGE() function.

---
[View this page online](https://www.commandprompt.com/education/postgresql-age-function-with-examples/)

---

# PostgreSQL TO_DATE() Function: Convert String to Date

> PostgreSQL provides a built-in function named TO_DATE() that assists us in converting a string into a date. The TO_DATE() function retrieves a date value in “Y…

PostgreSQL provides a built-in function named **TO_DATE()** that assists us in converting a string into a date. It accepts a string and a format as an argument and converts the given string according to the specified format. The **TO_DATE()** function retrieves a date value in “YYYY-MM-DD” format.

This article will illustrate the usage of the **TO_DATE()** function with practical examples. So, let’s get started.

 **How to Use TO_DATE() Function in Postgres?  
** The below snippet shows the syntax of the TO_DATE() function:
    
    
    TO_DATE(str, format);

The above snippet demonstrates that the TO_DATE() function accepts two arguments: str and a format. Based on the given format/pattern, the provided string will be converted to a date value. The TO_DATE() function accepts only a valid format based on which the given string will be converted into a date value.

The list of valid date formats/patterns is provided below:

  * YYYY: Indicates the Year in four digits/figures.
  * YYY: To specify the Year in three digits.
  * YY: Specifies the Year in two digits.
  * Y: To specify only the last digit of the year.
  * Y,YYY: Specifies the Year in four digits; the first digit will be separated with a comma.
  * IYYY: ISO standard 4-digit year.
  * IYY: ISO standard 3-digit year.
  * IY: Specifies the year in two digits ISO standard.
  * I: Indicates only the last digit of the year as per ISO standard.
  * Q: Used to specify a quarter (1 quarter = 3 months, e.g., Jul-Sep).
  * MM: Specifies a month in two digits(01-12; e.g., JAN = 01, DEC =12).
  * MONTH: Month in Uppercase Letters.
  * Month: Capitalized(first letter capital) month name.
  * month: Month name in lowercase.
  * MON: First three letters of a month in uppercase (e.g., DEC).
  * Mon: First three letters of the month(capitalized), e.g., Nov, Dec, etc.
  * mon: First three letters of the month in lowercase, e.g., nov, dec, etc.
  * RM: To specify the month in uppercase roman numerals e.g., IX, X, XI, etc.
  * rm: Specifies the month in lowercase roman numerals e.g., ix, x, xi, etc.
  * W: Week number of month (1-5).
  * WW: Week number of year (1-53).
  * IW: Week number according to ISO 8601 standards.
  * DAY: Specifies a day in uppercase letters.
  * Day : Specifies a capitalized(first letter capital) day.
  * day: Specifies the day name of day in lowercase letters.
  * DY: Abbreviated day name in uppercase letters.
  * Dy: Abbreviated capitalized(First letter capital) day name.
  * dy: Abbreviated day name in lowercase letters.
  * DDD: Day of the year (001-366).
  * IDDD: Day of a year according to ISO.
  * DD: Day of a month(01-31).
  * D: Day of week (1-7, here 1 represents Sunday, 2 for Monday, … and 7 represents Saturday)
  * ID: Day of the week according to ISO year (1-7, here 1 represents Monday, 2 represents Tuesday, and so on.)
  * J: Julian day; i.e., no. of days since Nov 24, 4714 BC.
  * AD, A.D, a.d, ad: AD indicator.
  * BC, B.C, b.c, bc: BC indicator.
  * CC: Specifies a century in two digits.



 **Example #1: How Does the TO_DATE() Function Work in Postgres?  
** Let’s pass a string and a format to the TO_DATE() function and see how it works:
    
    
    SELECT TO_DATE('2022-01-01','YYYY-MM-DD');

We passed a string “2022-01-01” as the first argument and a format “YYYY-MM-DD” as a second argument. Consequently, we will get the following resultant output:

The output shows that the given string has been converted into the date value.

 **Example #2: Converting a String Into a Date Value Using TO_DATE() Function  
** Here is another example that illustrates the working of TO_DATE() function:
    
    
    SELECT TO_DATE('01 January 2022','DD Month YYYY');

The provided string has been successfully converted into a date value.

 **Example #3: How to Use the TO_DATE() Function on Table’s Data?  
** We have already created a table named employee_details, whose details are depicted in the following snippet:
    
    
    SELECT * FROM employee_details;

The emp_joining_date column has string type data. Let’s utilize the TO_DATE() function to convert the type of emp_joining_date column from text to date:
    
    
    SELECT emp_name, TO_DATE(emp_joining_date, 'YYYY-MM-DD') 
    FROM employee_details;

The data type of the selected column has been converted from string to date.

 **Conclusion  
** The **TO_DATE()** is built-in function in Postgres that assists us in converting a string value to a date value. It accepts a string value and a format as an argument and converts the given string according to the specified format. The TO_DATE() function retrieves a date value in “YYYY-MM-DD” format. Multiple examples were considered in this write-up to explain how the TO_DATE() function works in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-to_date-function-convert-string-to-date/)

---

# PostgreSQL CURRENT_TIMESTAMP VS LOCALTIMESTAMP

> In Postgres, the CURRENT_TIMESTAMP retrieves the date and time along with the time zone, while the LOCALTIMESTAMP function retrieves the date and time without …

PostgreSQL provides multiple built-in functions to deal with the date and time, such as TO_DATE(), **LOCALTIMESTAMP** , NOW(), **CURRENT_TIMESTAMP** , and so on. All these functions perform different functionalities on the date and time values. For instance, the TO_DATE() function is used for string-to-date conversion, the LOCALTIMESTAMP function retrieves the current date and time, etc.

This write-up will present a comparative analysis of the Postgres **CURRENT_TIMESTAMP** and **LOCALTIMESTAMP** functions with examples. So, let’s get started.

 **What is Difference Between the CURRENT_TIMESTAMP and LOCALTIMESTAMP Functions?**

In Postgres, the current/latest date and time at which the transaction started can be obtained using the CURRENT_TIMESTAMP and LOCALTIMESTAMP functions. So, what's the distinction between these two functions? Well! It’s the time zone that makes a key difference. The CURRENT_TIMESTAMP retrieves the date and time along with the time zone, while the LOCALTIMESTAMP function retrieves the date and time without the time zone.

 **Example #1: CURRENT_TIMESTAMP VS LOCALTIMESTAMP in PostgreSQL**

Let us implement these functions one by one and see where they differ:
    
    
    SELECT CURRENT_TIMESTAMP;

The resultant output proved that the CURRENT_TIMESTAMP function retrieves the timestamp and the time zone.

Now, it’s time to implement the LOCALTIMESTAMP function practically:
    
    
    SELECT LOCALTIMESTAMP;

From the resultant output, it is clear that the LOCALTIMESTAMP function returns a timestamp without a time zone.

 **Example #2: CURRENT_TIMESTAMP VS LOCALTIMESTAMP With Precision Parameter**

In Postgres, both CURRENT_TIMESTAMP and LOCALTIMESTAMP functions can accept a precision parameter that allows us to specify the fractional seconds up to the specific number of digits:
    
    
    SELECT CURRENT_TIMESTAMP(3);

In this example, we specified 3 as a precision parameter, so the CURRENT_TIMESTAMP function retrieves the seconds with only three fractional points.
    
    
    SELECT LOCALTIMESTAMP(3);

The output clarifies that the LOCALTIMESTAMP function keeps only three digits for the seconds and skips the rest of the fractional points.

That’s all you need to know about the Postgres CURRENT_TIMESTAMP VS LOCALTIMESTAMP functions.

 **Conclusion**

In Postgres, the only difference between the **CURRENT_TIMESTAMP** and **LOCALTIMESTAMP** functions is the time zone. The current/latest date and time at which the transaction started can be obtained using the CURRENT_TIMESTAMP and LOCALTIMESTAMP functions. The CURRENT_TIMESTAMP retrieves the date and time along with the time zone, while the LOCALTIMESTAMP function retrieves the date and time without the time zone. A couple of examples were considered in this write-up to explain the difference between **CURRENT_TIMESTAMP** and **LOCALTIMESTAMP** functions.

---
[View this page online](https://www.commandprompt.com/education/postgresql-current_timestamp-vs-localtimestamp/)

---

# PostgreSQL TO_TIMESTAMP() Function With Examples

> In PostgreSQL, the TO_TIMESTAMP() is a built-in function that accepts a string and a format and converts the given string to a TIMESTAMP based on the specified…

In PostgreSQL, the **TO_TIMESTAMP()** is a built-in function that accepts a string and a format as arguments and converts the given string to a TIMESTAMP based on the specified format. It retrieves a TIMESTAMP along with a time zone.

This write-up will consider some examples to provide a detailed guide on how to use the **TO_TIMESTAMP()** function in PostgreSQL. So, let’s get started!

 **How to Use TO_TIMESTAMP() Function in PostgreSQL?**

The following snippet will illustrate the syntax of the **TO_TIMESTAMP** function:
    
    
    TO_TIMESTAMP(string, format);

Here, the string represents a timestamp that needs to be converted to a timestamp based on the specified format.

The format must be a valid format based on which the given string will be converted into a timestamp. The valid formats for the **TO_TIMESTAMP()** function are listed below:

  * CC: Specifies a century in two digits.
  * YYYY: Indicates the Year in four digits/figures.
  * YYY: To specify the Year in three digits.
  * YY: Specifies the Year in two digits.
  * Y: To specify only the last digit of the year.
  * Y,YYY: Specifies the Year in four digits; the first digit will be separated with a comma.
  * IYYY: ISO standard 4-digit year.
  * IYY: ISO standard 3-digit year.
  * IY: Specifies the year in two digits ISO standard.
  * I: Indicates only the last digit of the year according to the ISO standard.
  * Q: Used to specify a quarter (1 quarter = 3 months, e.g., Jul-Sep).
  * MM: Specifies a month in two digits(01-12; e.g., JAN = 01, DEC =12).
  * MONTH: Month in Uppercase Letters.
  * Month: Capitalized(first letter capital) month name.
  * month: Month name in lowercase.
  * MON: First three letters of a month in uppercase (e.g., DEC).
  * Mon: First three letters of the month(capitalized), e.g., Nov, Dec, etc.
  * mon: First three letters of the month in lowercase, e.g., nov, dec, etc.
  * RM: To specify the month in uppercase roman numerals e.g., IX, X, XI, etc.
  * rm: Specifies the month in lowercase roman numerals e.g., ix, x, xi, etc.
  * W: Week number of month (1-5).
  * WW: Week number of year (1-53).
  * IW: Week number according to ISO 8601 standards.
  * DAY: Specifies a day in uppercase letters.
  * Day : Specifies a capitalized(first letter capital) day.
  * day: Specifies the day name of day in lowercase letters.
  * DY: Abbreviated day name in uppercase letters.
  * Dy: Abbreviated capitalized(First letter capital) day name.
  * dy: Abbreviated day name in lowercase letters.
  * DDD: Day of the year (001-366).
  * IDDD: Day of a year according to ISO.
  * DD: Day of a month(01-31).
  * D: Day of week (1-7, here 1 represents Sunday, 2 for Monday, … and 7 represents Saturday)
  * ID: Day of the week according to ISO year (1-7, here 1 represents Monday, 2 represents Tuesday, and so on.)
  * J: Julian day; i.e. no. of days since Nov 24, 4714 BC.
  * TZ: Time zone in uppercase letters.
  * tz: Time zone in lowercase letters.
  * HH or HH12: Hours (01-12).
  * HH24: Hours(00-23).
  * MI: Minutes (00-59).
  * SS: Seconds (00-59).
  * MS: Milliseconds (000-999).
  * US: Microseconds (000000-999999).
  * SSSS: Seconds past midnight(0-86399).
  * A.M., AM, P.M, PM, a.m, am, p.m, pm: Meridian indicator.
  * AD, A.D, a.d, ad: AD indicator.
  * BC, B.C, b.c, bc: BC indicator.



 **Example #1: How to Convert a String to 'YYYY-MM-DD HH:MI:SS' Format Using TO_TIMESTAMP() function?**

Let’s consider the following query to understand the working of the TO_TIMESTAMP() function:
    
    
    SELECT TO_TIMESTAMP('2022-09-20 12:30:12', 'YYYY-MM-DD HH:MI:SS');

Output clarifies that the TO_TIMESTAMP() function retrieves the timestamp along with the time zone. The returned timestamp is formatted as per the given format.

 **Example #2: How to Convert a String to 'YYYY-MM-DD HH24:MI' Format Using TO_TIMESTAMP() Function?**

In this example, we will utilize the 'YYYY-MM-DD HH24:MI' format, so the given string will be converted accordingly:
    
    
    SELECT TO_TIMESTAMP('2022-09-20 12:30:12', 'YYYY-MM-DD HH24:MI');

The resultant output clarifies that the hours are converted according to the “HH24” format. Since the specified format didn’t utilize the SS, so the resultant timestamp will initialize the seconds with 00.

 **Example #3: How to Convert a String to a Specific Format Using the TO_TIMESTAMP() function?**

If you specify a year in less than four digits within the given string, then the TO_TIMESTAMP() function will convert it to the nearest year. For instance, 97 will be converted to 1997, 22 will be converted to 2022, etc.
    
    
    SELECT TO_TIMESTAMP('21-10-20 12:30:12.014.29282', 'YY/MM/DD HH:MI:SS.MS.US');

The two digit year i.e., ‘21’ has been converted into the nearest year, i.e., 2021. Let’s consider one more example to understand this concept in a better way:
    
    
    SELECT TO_TIMESTAMP('91-10-20 12:30:12.014.29282', 'YY/MM/DD HH:MI:SS.MS.US');

The output authenticates the working of the TO_TIMESTAMP() function.

 **Example #4: How to Use the TO_TIMESTAMP() Function on Table’s Data?**

Let’s create a table named “employee_details” having three columns: emp_id, emp_name, and emp_joining_date:
    
    
    CREATE TABLE employee_details(
    emp_id INT PRIMARY KEY,
    emp_name TEXT,
    emp_joining_date TEXT);

The employee_details table with the respective columns has been created successfully. Let’s insert some records into the employee_details table:
    
    
    INSERT INTO employee_details(emp_id, emp_name, emp_joining_date)
    VALUES (1, 'Joe', '2020-04-01'),
    (2, 'Mike', '2020-04-15'),
    (3, 'Seth', '2021-01-01');

Three records have been inserted into the employee_details table. Let’s use the SELECT statement to see the content of the employee_details table:
    
    
    SELECT * FROM employee_details;

Now we will utilize the TO_TIMESTAMP() function on the employee_details table to convert the emp_joining_date column to a TIMESTAMP:
    
    
    SELECT TO_TIMESTAMP(emp_joining_date, 'YYYY-MM-DD') 
    FROM employee_details;

This is how you can utilize the TO_TIMESTAMP() function on the table’s data.

 **Example #5: Out of Range Value?**

Converting the given string “2021-10-12 25:30:10” to 'YYYY-MM-DD HH24:MI:SS' format using the TO_TIMESTAMP() function will produce unexpected results:
    
    
    SELECT TO_TIMESTAMP('2021-10-12 25:30:10', 'YYYY-MM-DD HH24:MI:SS');

We encountered an error because the string contains an out-of-range value for the hours' field i.e., 25. The value for the ‘HH24’ field must be between 00-23.

This is how the TO_TIMESTAMP() function works in PostgreSQL.

 **Conclusion  
** The **TO_TIMESTAMP()** is a built-in function in Postgres that accepts a string and a format as arguments. Consequently, the TO_TIMESTAMP() function converts the given string to a TIMESTAMP based on the specified format and retrieves a TIMESTAMP along with a time zone. Several scenarios were considered in this write-up to explain how the TO_TIMESTAMP() function works in Postgres.

---
[View this page online](https://www.commandprompt.com/education/postgresql-to_timestamp-function-with-examples/)

---

# PostgreSQL INTERSECT Operator With Examples

> In PostgreSQL, the INTERSECT operator combines the result set of at least two queries. The INTERSECT operator retrieves only common records from the targeted t…

In PostgreSQL, the INTERSECT operator is used to combine the result set of at least two queries. The INTERSECT operator retrieves only those records that are common in all the targeted tables. While working with the INTERSECT operator, you must follow some rules, such as the number of columns and their order being the same, and data types should be compatible.

This post will present an in-depth overview of the INTERSECT Operator with examples. So, let’s begin.

 **How to Use INTERSECT Operator in PostgreSQL?**

The below snippet depicts the basic syntax of the INTERSECT operator:
    
    
    SELECT col_list
    FROM tab_1
    INTERSECT
    SELECT col_list
    FROM tab_2;

The SELECT query will fetch the records from the respective tables, while the INTERSECT operator will combine the common records.

While working with INTERSECT operator, several rules must be followed:

\- Columns specified in the SELECT statement must follow the same order.

\- The number of columns should be the same.

\- Columns type must be compatible.

 **Example #1: How Does the INTERSECT Operator Work in PostgreSQL?**

We have already created two tables in our database, i.e., article_details and recommended_articles. Let’s run the SELECT statement to see the details of each table:
    
    
    SELECT * FROM article_details;

The article_details table has twelve records. Let’s run the SELECT query to fetch the data of the recommended_articles table:
    
    
    SELECT * FROM recommended_articles;

The recommended_article table has three records. Let’s execute the below statement to understand the working of the INTERSECT operator:
    
    
    SELECT *
    FROM article_details
    INTERSECT
    SELECT *
    FROM recommended_articles;

There is only one common record in the article_details and recommended_articles tables. Therefore, the INTERSECT operator returned only one record.

 **Example #2: How to Use INTERSECT Operator on Specific Columns?**

We can use the INTERSECT operator on some specific columns to combine the common records of different tables' columns:
    
    
    SELECT article_title
    FROM article_details
    INTERSECT
    SELECT article_title
    FROM recommended_articles;

The output shows that there are two common articles in the article_details and recommended_articles tables.

 **Example #3: How to Use INTERSECT Operator With ORDER BY Clause?**

Let’s fetch the common records from the targeted tables based on article_title and article_id columns:
    
    
    SELECT article_title, article_id
    FROM article_details
    INTERSECT
    SELECT article_title, article_id
    FROM recommended_articles;

Suppose we want to sort the result set in ascending order concerning the article_id column. For this purpose, we can utilize the ORDER BY clause with the INTERSECT operator:
    
    
    SELECT article_title, article_id
    FROM article_details
    INTERSECT
    SELECT article_title, article_id
    FROM recommended_articles
    ORDER BY article_id ASC;

This time the INTERSECT Operator retrieved the result set in ascending order.

 **Conclusion**

In PostgreSQL, the INTERSECT operator combines the result set of at least two queries. The INTERSECT operator retrieves only common records from the targeted tables. While working with the INTERSECT operator, you need to follow a couple of rules, such as the same number of columns, the same columns’ order, and the data types should be compatible. This post taught us how to use the INTERSECT operator in PostgreSQL with suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-intersect-operator-with-examples/)

---

# How to Import a CSV File to a PostgreSQL Table

> Importing CSV files into Postgres tables or exporting tables from PostgreSQL into CSV files are very common. In PostgreSQL, you can import a CSV file to a tabl…

Importing CSV files into Postgres tables or exporting tables from PostgreSQL into CSV files are very common. In PostgreSQL, you can import a CSV file to a table using the \COPY statement(CLI) or pgAdmin(GUI).

In this write-up, we will learn various ways to import a CSV file to a Postgres table. So, let’s begin.

 **How to Use the \COPY Command in PostgreSQL?**

You can use the \COPY statement to import a CSV(comma separated values) file to a Postgres table. Make sure that the column’s order should be the same in the CSV file and Postgres table. Following will be the syntax of the COPY statement for importing CSV files to the PostgreSQL table:
    
    
    \COPY tab_name(col_list) FROM 'file_path' CSV HEADER;

 **Example:**

We have created a table named author_details whose structure is as follows:
    
    
    SELECT * FROM author_details;

The author_details table has two columns: a_id and author_name. We have created a CSV file that contains the following records:

Our CSV file is located in C:\Windows\Temp\authorInfo.csv. So, we will specify this path in the COPY statement to import the targeted CSV file:
    
    
    \COPY author_details(a_id, author_name) 
    FROM 'C:\Windows\Temp\authorInfo.csv' DELIMITER ',' CSV HEADER;

The above snippet shows that three records have been copied to the targeted Postgres table, i.e., the author_ details table. Let’s run the SELECT command to verify the working of \COPY command:
    
    
    SELECT * FROM author_details;

The CSV file data has been successfully imported to the author_details table.

 **Importing CSV File to a Postgres Table Using pgAdmin4?**

We have already created a table named author_data. Let’s execute the below statement to see the table’s structure:
    
    
    SELECT * FROM author_data;

Now, to import the desired CSV file, right click on the targeted table and select the “Import/Export Data”:

Clicking on the Import data will open the following window:

Firstly, select the Import option, specify the CSV file’s address, select the file format, and specify a delimiter. Now switch to the “Columns” window:

You will see the columns’ names in the columns to import tab. By default, Postgres will import all the columns; however, you can specify the columns of your choice. Clicking on the OK button will lead you to the following window:

Congratulations you have successfully imported the CSV file’s data into the desired Postgres table. You can verify the table’s records using the SELECT query as follows:
    
    
    SELECT * FROM author_data;

This is how you can import a CSV file using pgAdmin.

 **Conclusion**

In PostgreSQL, you can import a CSV file to a table using various methods such as the \COPY statement(CLI) or pgAdmin(GUI). When importing a CSV file into a Postgres table, the columns should have the same order. This post taught us several methods to import a CSV file to a PostgreSQL table using practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-import-a-csv-file-to-a-postgresql-table/)

---

# Export a PostgreSQL Table to a CSV File

> In PostgreSQL, there are multiple ways to export a table into a CSV file, such as the COPY statement or the \COPY command.

While working with databases like PostgreSQL, exporting a table into a CSV file or importing a CSV file into a Postgres table is a very common task. In PostgreSQL, you have multiple ways to export a table into a CSV file, such as copy statement, \copy command, or pgAdmin.

In this write-up, we will learn different methods to export a Postgres table into a CSV file. So, let’s begin.

 **How Does the COPY Statement Work in PostgreSQL?**

Copy statement is the simplest way to export a table into a CSV file. To achieve this purpose, use the following syntax:
    
    
    COPY tab_name TO 'Path/file_name.csv' CSV HEADER;

\- COPY is a statement.

\- tab_name is a table to be exported.

\- Path represents a directory where the table will be exported.

\- File_name.csv is the exported CSV file.

 **Example #1:**

We have created a table named book_info. Let's list down the table details using the SELECT command:
    
    
    SELECT * FROM book_info;

Now run the following command to export the book_info table into a CSV file:
    
    
    COPY book_info TO 'C:\Windows\Temp\book_info.csv' CSV HEADER;

The output shows that five records have been exported. If everything goes fine, you will get the following results:

The output shows that the desired table has been exported to the CSV file successfully.

 **Example #2:**

You can specify a delimiter of your choice to separate the table’s values. For instance, the below statement will provide the “;” separated values:
    
    
    COPY book_info TO 'C:\Windows\Temp\book_info1.csv' DELIMITER ';' CSV HEADER;

Open the CSV file from the targeted location to see the exported values:

The output shows that the desired table has been exported to the CSV file. And this time, values are separated with “;”.

 **Example #3:**

Execute the below statement to export only specific columns of a Postgres table:
    
    
    COPY book_info(book_name) TO 'C:\Windows\Temp\book_info.csv' CSV HEADER;

Let’s open the CSV file to see the exported values:

In this way, you can export only specific columns of a table.

 **How Does the \COPY Command Work in PostgreSQL?**

The \COPY is an inbuilt command that is used for exporting a PostgreSQL table to a CSV file. If you have limited privileges, then you can use the \COPY command because it doesn’t require superuser privileges. Follow the below-given syntax for the client-side export of CSV files:
    
    
    \COPY Tab_Name to 'Path/file_name.csv' CSV HEADER;

 **Example**

For exporting the desired table to a CSV file, execute the \COPY command:
    
    
    \COPY (SELECT * FROM book_info) to 'C:\Windows\Temp\bookInfo.csv' with CSV;

On successful execution of the \COPY command, following data will be exported to the CSV file:

This is how you can export a Postgres Table to a CSV file using the COPY statement or \COPY command.

 **Conclusion**

In PostgreSQL, there are multiple ways to export a table into a CSV file, such as the COPY statement or \COPY command. Using these commands, you can export the entire Postgres table or some specific columns of a table into a CSV file. This post explained the working of the COPY statement and \COPY command with examples.

---
[View this page online](https://www.commandprompt.com/education/export-a-postgresql-table-to-a-csv-file/)

---

# PostgreSQL UNNEST() Function With Examples

> PostgreSQL provides a built-in function named UNNEST() that accepts an array as an argument and expands the given array into a set of rows.

PostgreSQL provides a built-in function named UNNEST() that expands the given array into rows. The UNNEST() function takes an array as an argument/parameter and expands the given array into a set of rows. In simple terms, it converts an array to a table-like structure.

This post will explain how the UNNEST() function works in Postgres with examples. So, let’s get started.

 **How to Use UNNEST() Function in Postgres?**

The below snippet illustrates the syntax of UNNEST() function:
    
    
    UNNEST(arr);

Where “arr” is an array to be expanded. We can use the LIMIT clause, DISTINCT clause, ORDER BY clause, etc., with the UNNEST() function to achieve different functionalities.

 **Example #1: How to Expand/Convert a Numeric Array Into Rows?**

In this example, we will use the UNNEST() function to expand the given array into a set of rows:
    
    
    SELECT UNNEST(ARRAY[1, 5, 72, 100, 514]);

The output proves the working of UNNEST() function as it successfully expanded the array of five elements into five rows.

 **Example #2: How to Expand/Convert a String Array to Rows?**

We will pass an array of string elements to the UNNEST() function:
    
    
    SELECT UNNEST(ARRAY['John', 'Joe', 'Mike', 'Daniel', 'Ambrose']);

The UNNEST() function expanded the string array into different rows.

 **Example #3: How to Expand an Array into a Specific Order?**

We can use the ORDER BY clause with the UNNEST() function to expand the array into a set of rows but in a specific order:
    
    
    SELECT UNNEST(ARRAY[10, 123, 32, 14, 9]) ORDER BY 1;

The output authenticates the working of UNNEST() with the ORDER BY clause.

 **Example #4: How to Expand an Array Into Limited Rows?**

Use the LIMIT clause with the UNNEST() function to expand/convert the given array into limited rows:
    
    
    SELECT UNNEST(ARRAY[10, 123, 32, 14, 9]) LIMIT 3;

In this way, you can use the LIMIT clause with the UNNEST() function to get the limited rows.

 **Example #5: How to Use UNNEST() Function on Tables Data?**

The below query will show you the details of the student_details table:
    
    
    SELECT * FROM student_details;

The output shows that the std_email column is an array of text-type data. Let’s use the UNNEST() function to expand the given array into a set of rows:
    
    
    SELECT UNNEST(std_email) FROM student_details;

This is how the UNNEST() function works on the table’s data.

 **Conclusion**

PostgreSQL provides a built-in function named UNNEST() that accepts an array as an argument and expands the given array into a set of rows. The UNNEST() function can accept the array of any data type, such as text, int, etc., and expands the given array into rows. This post explained the working of the UNNEST() function with examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-unnest-function-with-examples/)

---

# PostgreSQL UNIQUE Constraint With Examples

> Sometimes we have to store the unique records in a table, such as an email address, employee id, etc. To achieve this purpose, the “UNIQUE” constraint is used …

Sometimes we have to store the unique records in a table, such as an email address, employee id, etc. To achieve this purpose, the “UNIQUE” constraint is used in PostgreSQL. The UNIQUE constraint allows us to store the unique rows/records in a table.

This post will explain the working of the UNIQUE constraint through practical examples. So, let’s begin.

 **How Does UNIQUE Constraint Work in PostgreSQL?**

Each time when you insert a new record in a table, the UNIQUE constraint checks whether the value to be inserted already exists in the table or not. If the specified value already exists, then the UNIQUE constraint generates an error stating that the specified value already exists in the table. In PostgreSQL, a unique index is automatically created when we insert a UNIQUE constraint to a table’s column.

 **Example: How to Create and Store a UNIQUE Constraint in PostgreSQL?**

Let’s create a table named car_details with four columns id, car_model, car_color, and reg_number:
    
    
    CREATE TABLE car_details (
    id INT PRIMARY KEY, 
    car_model VARCHAR (30), 
    car_color VARCHAR (30), 
    reg_number VARCHAR (30) UNIQUE
    );

In the above snippet, we utilized the UNIQUE constraint with the reg_number column so it will accept only unique values:

The car_details table has been created successfully. Let’s execute the SELECT command to see the table structure:
    
    
    SELECT * FROM car_details;

Let’s execute the INSERT query to insert a couple of rows into the car_details table:
    
    
    INSERT INTO car_details(id, car_model,car_color,reg_number)
    VALUES(1, 'Alto-2022','black','xyz123'),
    (2, 'SWIFT-2021','blue','abx321');

Let’s insert a duplicate registration number and see how the UNIQUE constraint deals with that record:
    
    
    INSERT INTO car_details(id, car_model,car_color,reg_number)
    VALUES(3, 'Baleno-2022','red','xyz123');

The output shows that the UNIQUE constraint restricts us from inserting a duplicate value into the reg_number column.

 **How Does UNIQUE Constraint Work on Multiple Columns in PostgreSQL?**

Postgres enables us to implement the UNIQUE constraint on more than one column using the following syntax:
    
    
    CREATE TABLE tab_name (
    col_1 data_type,
    col_2 data_type,
    …,
    col_n data_type,
    UNIQUE (col_1, col_2));

The following syntax will work the same way as the above syntax:
    
    
    CREATE TABLE tab_name(
    col_1 data_type UNIQUE,
    col_2 data_type UNIQUE,
    …,
    col_n data_type
    );

Columns col_1 and col_2 will have a unique combination of values throughout the table.

 **Example: How to Use UNIQUE Constraint on Multiple Columns in Postgres?**

Let’s create a table named bike_info that implements UNIQUE constraints on multiple columns:
    
    
    CREATE TABLE bike_info (
    bike_model VARCHAR (50),
    bike_color TEXT,
    reg_num VARCHAR (50) UNIQUE,
    bike_id INT UNIQUE
    );

In this way, you can create multiple columns with unique constraints. Let’s insert some records into the newly created table to understand the working of UNIQUE constraint:
    
    
    INSERT INTO bike_info(bike_model,bike_color,reg_num, bike_id)
    VALUES('BMW K 1200 S','black','xyz456', 12 ),
    ('Ducati 1098s','black','xyz321', 12);

The output shows that the bike_id in the second row violates the unique constraint.

 **Conclusion**

The UNIQUE constraint allows us to store the unique records in a table. Each time when you insert a new record in a table, the UNIQUE constraint checks whether the value to be inserted already exists in the table or not. If the specified value already exists, then the UNIQUE constraint generates an error stating that the specified value already exists in the table. This post explained how to use the UNIQUE constraint in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-unique-constraint-with-examples/)

---

# PostgreSQL CAST Operator- How to Convert One Data Type to Another

> PostgreSQL offers a CAST operator that takes an expression and a data type and converts the given expression into the specified data type.

While working with PostgreSQL, we may encounter a situation where we need to convert one data type into another. For instance, converting a numeric string into an int, a string to date, etc. For this purpose, PostgreSQL provides a CAST operator that assists us in converting one data type to another.

Using practical examples, this post will explain how the CAST operator works in PostgreSQL. So, let’s begin.

 **How to Use the CAST Operator in PostgreSQL?**

The below snippet illustrates the basic syntax of the CAST operator:
    
    
    CAST (exp AS data_type);

Here, exp represents an expression to be evaluated, such as a table’s column, an expression, or a constant. While data_type represents a targeted data type. The given expression will be converted into the targeted data type.

 **Example #1: How to Use CAST Operator to Convert/Cast a String to Integer?**

Run the below statement to convert the given constant string to an integer:
    
    
    SELECT CAST ('572' AS INTEGER);

The output proves that the CAST operator takes a constant string and converts it into the desired data type, i.e., integer.

 **Example #2: How to Use the CAST Operator to Table’s Column?**

We have created a table named team_details. Let’s run the SELECT statement to get the table’s details:
    
    
    SELECT * FROM team_details;

The result set shows that the team_rating column has a TEXT data type. Let’s convert it into INTEGER data type using the CAST operator:
    
    
    SELECT CAST(team_rating AS INTEGER)
    FROM team_details;

The output shows that the data type of team_rating column has been changed to INTEGER data type.

 **Example #3: How to Use CAST Operator For String to Date Type Conversion?**

We have created a table named article_details in our database. Let’s execute the SELECT query to get the table’s details:
    
    
    SELECT * FROM article_details;

The published_date column has a text data type. Let’s convert it into DATE type using the CAST operator:
    
    
    SELECT CAST(published_date AS DATE) FROM article_details;

The data type of published_date column has been converted to the DATE type.

 **Example #4: How to Use a CAST Operator to Convert a String Into a Double Type?**

In our example database, we have created a bike_details table that contains following records:
    
    
    SELECT * FROM bike_details;

The bike_price column has a TEXT data type. Let’s execute the below statement to convert the TEXT data type to DOUBLE PRECISION data type:
    
    
    SELECT CAST(bike_price AS DOUBLE PRECISION) FROM bike_details;

The selected column has been converted into the desired data type i.e. DOUBLE PRECISION.

 **Example #5: Invalid Type Conversion in Postgres?**

Trying to convert an expression that cannot be converted to the specified data type will generate an error. Let’s consider the same bike_details table:
    
    
    SELECT * FROM bike_details;

This time we will try to convert the bike_number column into the DOUBLE PRECISION data type:
    
    
    SELECT CAST(bike_number AS DOUBLE PRECISION) FROM bike_details;

You can see that Postgres generates an error “invalid input syntax”. This is because the bike_number column contains alphanumeric values that cannot be converted into the DOUBLE PRECISION data type.

This is how the CAST Operator works in PostgreSQL.

 **Conclusion**

PostgreSQL provides a CAST operator that assists us in converting one data type to another. For instance, you can convert a numeric string into an integer, string to double precision, string to boolean, etc. The CAST() operator takes an expression/column and a data type. Consequently, it converts the given expression into the specified data type. In this post we considered several examples to explain the working of the CAST() operator.

---
[View this page online](https://www.commandprompt.com/education/postgresql-cast-operator-how-to-convert-one-data-type-to-another/)

---

# PostgreSQL Drop if Exists VS Drop

> The DROP command throws an error if a table to be dropped doesn’t exist while “DROP IF EXISTS” shows a notice instead of throwing an error.

In PostgreSQL, the DROP command drops/deletes a specific database/table. However, Dropping or deleting a table that doesn't exist in the targeted database will result in an error. To tackle such an error, the IF EXISTS parameter can be used with the DROP command.

Using practical examples, this post will show you the difference between the DROP and DROP IF EXISTS commands. So, let’s begin.

 **How to Drop a Table in PostgreSQL?**

Use the DROP TABLE statement to drop the targeted Postgres table. DROP TABLE will have the following syntax:
    
    
    DROP TABLE tab_name;

tab_name is a table to be dropped/deleted.

 **Example #1: How Does DROP Command Work in PostgreSQL?**

Follow the below given stepwise instructions to drop a table in PostgreSQL:

 **Step # 1: Establish a Connection With the Selected Database**

Firstly, open the SQL SHELL and specify the database name after the \c command to connect to a database of your choice:
    
    
    \c example;

As the above snippet depicts, we are successfully connected to the selected database.

 **Step # 2: Check the Available Tables**

Run the “\dt” command to see all the tables available in the “example” database”
    
    
    \dt;

From the available tables, suppose we want to drop the bank_details table.

 **Step # 3: Drop the Selected Table**  
The below snippet explains how the DROP command works in PostgreSQL:
    
    
    DROP TABLE bank_details;

On successful execution of the DROP TABLE command, you will get the following output:

The output demonstrates that the selected table has been dropped successfully.

 **Step # 4: Verify the Table’s Deletion**

The \dt command followed by the table’s name provides the details about the selected table:
    
    
    \dt bank_details;

The output proves that the bank_details table has been dropped from the example database. Let’s try to drop the selected table (i.e. bank_details) one more time and see how the DROP TABLE command works in such a situation:
    
    
    DROP TABLE bank_details;

This time, we encountered an error saying that the desired table doesn’t exist.

 **Example #2: How Does DROP IF EXISTS Command Work in PostgreSQL?**

The IF EXISTS is an option that checks the existence of a table. It can be seen from the above example that an error occurs when we tried to drop a table that doesn't exist. We can avoid such an error using the IF EXISTS option.

Now, it's time to learn the working of the DROP IF EXISTS command.

 **Step #1: Check the Available Tables**

Let’s run the \dt command to get all the relations available in the example database:
    
    
    \dt;

Let’s drop the “emp_data” table.

 **Step # 2: Drop the Selected Table**

Run the DROP IF EXISTS command to drop the emp_data table:
    
    
    DROP TABLE IF EXISTS emp_data;

So far so good, the selected table has been dropped successfully. Let’s try to drop it one more time:
    
    
    DROP TABLE IF EXISTS emp_data;

DROP IF EXISTS retrieves a notice instead of throwing an error.

 **Conclusion**

In PostgreSQL, the DROP command is used to drop/delete a specific database/table. However, Dropping or deleting a table that doesn't exist in the targeted database will result in an error. To tackle such an error, the IF EXISTS parameter is used with the DROP command. The DROP command throws an error if a table to be dropped doesn’t exist, while “DROP IF EXISTS” shows a notice instead of throwing an error. This write-up explained the difference between DROP and “DROP IF EXISTS” with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-drop-if-exists-vs-drop/)

---

# PostgreSQL SELECT DISTINCT Clause With Examples

> In Postgres, the SELECT DISTINCT clause fetches only unique values from a result set returned by a query. It retains only one row from a set of duplicated rows…

In PostgreSQL, the **SELECT DISTINCT** statement is used to fetch only unique values from a table/result-set that is returned by a query. The **DISTINCT** clause retains only one row from a set of duplicated rows. You can use the DISTINCT clause on multiple columns as well. In such a case, the DISTINCT clause will determine the duplicates based on the combination of the targeted columns' values.

This write-up will show you how to fetch the distinct values from a result set returned by a query. So, let’s begin.

 **How to Fetch Unique Records in PostgreSQL?**

Follow the below syntax to fetch the distinct values from a result set:
    
    
    SELECT DISTINCT col_list
    FROM tab_name;

Firstly, specify a column name or list of columns after the SELECT DISTINCT clause. After that, write the targeted table's name in the FROM clause.

 **Example #1: How to Fetch Unique Rows From a Table in PostgreSQL?**

In this example, we will target the programming_languages table, whose details are as follows:
    
    
    SELECT * FROM programming_languages;

From the output, you can notice that there are multiple duplicates in the programming_languages table. Let’s run the SELECT command with the DISTINCT clause to fetch only the DISTINCT rows from the selected table:
    
    
    SELECT DISTINCT language
    FROM programming_languages;

This way, you can fetch the unique rows from a table in PostgreSQL.

 **Example #2: How to Fetch Unique Values From Multiple Columns in PostgreSQL?**

If you apply the DISTINCT clause on multiple columns, then it will skip only those values that are duplicated in all the columns:
    
    
    SELECT DISTINCT id, language
    FROM programming_languages;

There was only one duplicate record that contained the same id and language, i.e., id=2, language=C++, so, the SELECT DISTINCT clause removed only that record. Other than that, the SELECT DISTINCT clause fetched all the values, including duplicates. This is because the id column has only one duplicate value, i.e., 2.

 **Example #3: What Does DISTINCT ON Clause do in PostgreSQL?**

In the case of multiple columns, use the Postgres DISTINCT ON clause to get the first row from the set of duplicate rows, regardless of the combination of the unique column values. However, you must specify the targeted column in the ORDER BY clause; otherwise, an error will occur.
    
    
    SELECT DISTINCT ON (language) id, language
    FROM programming_languages
    ORDER BY language;

This way, you can fetch more than one column and get the unique values based on a specific column.

 **Conclusion**

PostgreSQL uses the SELECT DISTINCT clause to return only unique values from a query’s result set. It retains only one row from a set of duplicated rows. The SELECT DISTINCT clause can be used on multiple columns to fetch the duplicates from multiple columns. However, in such a case, the SELECT DISTINCT clause will skip only those duplicates that are duplicated in all the columns. This write-up explained the working of the SELECT DISTINCT clause with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-select-distinct-clause-with-examples/)

---

# PostgreSQL COALESCE() Function With Examples

> In PostgreSQL, the COALESCE() function handles the null values more efficiently. It accepts unlimited arguments and returns the first non-null argument.

PostgreSQL provides a function named **COALESCE()** that handles the null values more efficiently. The **COALESCE ()** function is used in PostgreSQL to get the first non-null argument/value. In a certain case, where all arguments are null, the **COALESCE()** function will return a null value.

This post will present detailed knowledge about the Postgres **COALESCE()** function with the help of different examples. So, let’s begin.

 **How to Use COALESCE() Function With Examples?**

The below snippet illustrates the syntax of the **COALESCE()** function:
    
    
    COALESCE (arg_1, arg_2, ...);

The syntax shows that the **COALESCE()** function can accept unlimited arguments. It starts the argument evaluation from left to right. Once the **COALESCE()** function locates the first non null value/argument, then, it will stop further evaluation. As a result, it will return only the first non-null value/argument. Let’s understand the working of the Postgres **COALESCE()** function with examples.

 **Example #1: Pass All the Non-Null Arguments to COALESCE()**

In this example, we will assign five non-null arguments to the COALESCE() function as follows:
    
    
    SELECT COALESCE(110, 12, 525, 910, 006);

The **COALESCE()** function finds the non-null argument on the very first index, so it stopped further evaluation and returned the first non-null value, i.e., “110”.

 **Example #2: Pass Null Argument to COALESCE()**

In this example, we will explore how the COALESCE function deals with the NULL arguments:
    
    
    SELECT COALESCE(NULL, 525, 910, 006);

The output shows that the COALESCE() function returns the first non-null value, i.e., ‘525’.

 **Example #3: Pass Multiple Null Argument to COALESCE()**

Let’s explore how the COALESCE() function deals with the multiple NULL arguments:
    
    
    SELECT COALESCE(NULL, NULL, 910, 525, 006);

The COALESCE() function skipped all the NULL values and returned the first non-null value, i.e., ‘925’.

 **Example #4: How to Use COALESCE() Function With Table’s Data?**

We created a table named emp_data in our existing database and retrieved the table’s details using the SELECT statement:
    
    
    SELECT * FROM emp_details;

Let’s calculate the total salary by adding the bonus to the basic salary:
    
    
    SELECT emp_salary + emp_bonus AS "total_salary"
    FROM emp_details;

From the output, it is clear that we got the faulty results. The sum of emp_salary + NULL should be emp_salary; however, we got NULL instead of emp_ salary. To get accurate results, we will use the **COALESCE()** function as follows:
    
    
    SELECT emp_salary + COALESCE(emp_bonus, 0) AS total_salary
    FROM emp_details;

The above snippet served the following functionalities:

\- Performed addition over the emp_salary and emp_bonus columns.

\- Utilized the COALESCE() function to deal with the NULL values.

\- In the COALESCE() function, we passed 0 as the second argument.

\- So, whenever a NULL value occurs in the emp_bonus column, the COALESCE() function will return 0 instead of a NULL value:

The COALESCE() function provides accurate results. This way, the COALESCE() function assists us in dealing with the NULL values.

 **Conclusion**

In PostgreSQL, the **COALESCE()** function handles the null values more efficiently. It accepts unlimited arguments and retrieved the first non-null argument/value. In the case of all NULL arguments, the COALESCE() function returns a null value. It starts the argument evaluation from left to right. Once the **COALESCE()** function locates the first non-null argument, it will stop the further evaluation, and it will return only the first non-null argument. This write-up considered some examples to explain different use cases of the COALESCE() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-coalesce-function-with-examples/)

---

# PostgreSQL DATEADD() Equivalent- How to Add Interval to Datetime

> PostgreSQL doesn’t provide a DATEADD function to add an interval to date time. However, you can achieve the same functionality using the “+” and “-” operators.

SQL provides a DATEADD() function that adds a date or time interval to a specific date and returns the updated date. Similarly, MySQL and MariaDB have DATE_ADD() and ADDDATE() functions to add an interval to a date/time, and SQLite provides a DATE() function that can be used to add an interval to a date/time.

However, PostgreSQL doesn’t provide any equivalent function. Now you must be wondering how to achieve such functionality in PostgreSQL.

Well, nothing to worry about. This post is going to assist you in this regard with the help of practical examples. Let’s start.

 **How to Add Interval to Datetime in PostgreSQL?**

In Postgres, the + or - operators can be used to add or subtract an interval to a Date/time.

 **Example #1: How to Add Days Into a Date/Time in PostgreSQL?**

Suppose we have to add 3 days into the date “2022-08-17”. For this purpose, we utilize + operator as follows:
    
    
    SELECT DATE '2022-08-17' + INT '3';

Three days have been added to the given date successfully.

 **Example #2: How to Subtract Days From a Date/Time in PostgreSQL?**

Let’s subtract three days from “2022-08-17” using “-” operator:
    
    
    SELECT DATE '2022-08-17' - INT '3';

Three days have been subtracted from the specified date.

 **Example #3: How to Add Weeks Into a Date/Time in PostgreSQL?**

We will use the INTERVAL data type to add three weeks to the given date:
    
    
    SELECT DATE '2022-08-17' + INTERVAL '3 WEEKS';

From the output, you can observe that three weeks have been added to the given date.

 **Example #4: How to Add Months Into a Date/Time in PostgreSQL?**

Let’s run the below statement to add two months to the given date:
    
    
    SELECT DATE '2022-08-17' + INTERVAL '2 MONTHS';

The output proved that using INTERVAL data type, you can add/subtract months to the given date.

 **Example #5: How to Add Time Into a Date/Time in PostgreSQL?**

We can also add time to the given date/time by employing the interval data type. In this example, we will add five hours, 12 minutes to the specified date/time:
    
    
    SELECT DATE '2022-08-17' + INTERVAL '2 HOURS 12 MINUTES';

This is how you can add/subtract a date or time in a specific date, time.

 **Example #6: How to Add Date/Time Into a Current Date/Time in PostgreSQL?**

Let’s run the below statement to add an interval into the current date:
    
    
    SELECT CURRENT_DATE + INTERVAL '10 Days 1 Hour 15 Minutes';

In the above query firstly, we utilized the CURRENT_DATE function to get the current date. Next, we utilized the **“+”** operator with the INTERVAL data type to add an interval to the current date:

The output shows that the specified interval has been added to the current date successfully.

 **Example #7: How to Add Date/Time to a Table’s Column in PostgreSQL?**

We have a table named “sale” in our database. Let’s fetch the table’s records using SELECT statement:
    
    
    SELECT * FROM sale;

Suppose we want to find out how long the winter and summer sales will last. To do that, we will subtract the sale_start date from the sale_end date:
    
    
    SELECT sale_end - sale_start
    FROM sale;

As shown in the output, the winter sale will last 36 days, and the summer sale will last 30 days.

That was all the necessary information regarding how to add an interval to date in PostgreSQL.

 **Conclusion**

In Postgres, the + or - operators are used to add or subtract an interval from a Date/time. In other databases like SQL, MySQL, and MariaDB, different built-in functions are used to add an interval to a date/time. However, in PostgreSQL, you can add an interval to date/time simply by using the “+” and “-” operators. This post considered multiple examples to explain how to add an interval to a date/time.

---
[View this page online](https://www.commandprompt.com/education/postgresql-dateadd-equivalent-how-to-add-interval-to-datetime/)

---

# PostgreSQL Letter Case Functions With Practical Examples

> PostgreSQL provides various functions, such as LOWER(), INITCAP(), or UPPER(), to alter a string to lowercase, proper case, and uppercase, respectively.

PostgreSQL offers some built-in functions, such as **LOWER(), INITCAP(), or UPPER(),** to alter a string to lowercase, proper case(the first letter of every word would be capital), and uppercase, respectively. All these functions accept a string expression, table values, etc., as an argument and convert them to the respective case.

This post will present detailed knowledge about the Postgres letter case functions with the help of different examples. So, let’s begin.

 **How to Use the LOWER() Function in Postgres?**

Use the Postgres **LOWER()** function to convert a string, column value, or an expression to lowercase. The below snippet will demonstrate the syntax of the LOWER() case function:
    
    
    LOWER(string_expression | column_values);

Let’s consider the below example to get a profound knowledge of the Postgres **LOWER()** function.

 **Example #1: How to Convert a String in Lowercase?**

Let’s pass a string to the **LOWER()** function to see how the LOWER() function works in Postgres:
    
    
    SELECT LOWER('COMMANDPROMPT.COM');

The output shows that the LOWER() function converted the given string to the lower case.

 **Example #2: How to Use the LOWER() Function on the Table’s Data in Postgres?**

Let’s execute the below statement to see the article_details table:
    
    
    SELECT * FROM article_details;

We will use the LOWER() function to convert the values of the article_title column to the lower case:
    
    
    SELECT LOWER(article_title)
    FROM article_details;

The output shows that the LOWER() function successfully converted the column’s values to the lower case.

 **How Does the INITCAP() Function Work in Postgres?**

Use the Postgres **INITCAP()** function to convert a string_expression or column value to the Proper/title case. The syntax of the Postgres INITCAP() function will be as follows:
    
    
    INITCAP(string_expression | column_values);

 **Example #1: How to Convert a Function in Title Case?**

The below snippet illustrates the working of the Postgres INITCAP() function:
    
    
    SELECT INITCAP('welcome to commandprompt.com');

The INITCAP() function succeeded in converting the specified string into the proper case.

 **Example #2: How to Use the INITCAP() Function on the Table’s Data in Postgres?**

This example explains how to use the INITCAP() function on the Table’s Data:
    
    
    SELECT INITCAP(article_title)
    FROM article_details;

This way, you can use the INITCAP() function on the table’s data.

 **How Does the UPPER() Function Work in Postgres?**

Use the Postgres **UPPER()** function to convert a string_expression or column value to the upper case. Following will be the syntax of the UPPER() function in Postgres:
    
    
    UPPER(string_expression | column_values);

 **Example #1: How to Convert a String in Uppercase?**

The below snippet demonstrates the working of the Postgres UPPER() function:
    
    
    SELECT UPPER('welcome to commandprompt.com');

The **UPPER()** function converts the user-specified string into the uppercase.

 **Example #2: How to Use the UPPER() Function on the Table’s Data in Postgres?**

Let’s understand how to use the UPPER() function on the Table’s Data:
    
    
    SELECT UPPER(article_title)
    FROM article_details;

The output authenticates the working of the UPPER() function.

 **Conclusion**

PostgreSQL provides various functions, such as **LOWER(), INITCAP(), or UPPER(),** to alter a string to lowercase, proper case, and uppercase, respectively. All these functions accept a string expression, table values, etc., as an argument and convert them to the respective case, i.e., uppercase, lowercase, proper case. This write-up explained the working of letter case functions with practical examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-letter-case-functions-with-practical-examples/)

---

# PostgreSQL CURRENT_TIMESTAMP Function With Examples

> PostgreSQL offers multiple date/time functions, such as CURRENT_DATE, NOW(), EXTRACT(), CURRENT_TIMESTAMP, etc. If we talk about the CURRENT_TIMESTAMP function…

PostgreSQL offers multiple date/time functions, such as CURRENT_DATE, NOW(), EXTRACT(), CURRENT_TIMESTAMP, etc. If we talk about the CURRENT_TIMESTAMP function, it retrieves the current date, time, and timezone when a transaction starts.

This write-up will present a thorough overview of the Postgres CURRENT_TIMESTAMP function with examples. So, let’s begin.

 **How to Use CURRENT_TIMESTAMP Function in PostgreSQL?**

Firstly, let’s understand the syntax of the CURRENT_TIMESTAMP function:
    
    
    CURRENT_TIMESTAMP(<precision>);

Here, “precision” is an optional parameter used to round the “seconds” fields up to specific fractional digits. When the precision parameter is omitted, a TIMESTAMP will be returned with a timezone along with full fractional seconds precision.

Now, we will implement the CURRENT_TIMESTAMP function practically to get a better understanding:

 **Example #1: What Does CURRENT_TIMESTAMP Function Return?**

Run the below statement to understand the working of the CURRENT_TIMESTAMP function:
    
    
    SELECT CURRENT_TIMESTAMP;

The output shows that the **CURRENT_TIMESTAMP** returns the current date “2022-09-09”, current time “16:07:06.305565” and time zone “07”.

 **Example #2: How to Use the CURRENT_TIMESTAMP With the Precision Parameter?**

In the above example, you can see that there are six digits after the fractional point in the “seconds” field. However, you can pass a value as a precision parameter to round the seconds up to specific fractional points:
    
    
    SELECT CURRENT_TIMESTAMP(3);

In this example, we specified ‘3’ as a precision argument to the CURRENT_TIMESTAMP. Consequently, we will get the following outcome:

The output shows that the seconds are rounded to three decimal points.

 **Example #3: How to Set Current TIMESTAMP as a Column’s Default Value?**

We created a table named publish_article with three columns article_id, article_name, and publish_date:
    
    
    CREATE TABLE publish_article(
    article_id INT NOT NULL,
    article_name TEXT NOT NULL,
    publish_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP);

In this example, we created a “publish_article” table using the CREATE TABLE command. The table consists of three columns whose details are listed below:

\- An article_id column that will accept integer type data.

\- An article_name column with the TEXT data type.

\- A publish_date column having TIMESTAMP data type. By default, its value would be the current date and time.

The publish_article table has been created successfully. Now, insert the data into the publish_article table with INSERT INTO command:
    
    
    INSERT INTO publish_article (article_id, article_name)
    VALUES (1, 'PostgreSQL VS MySQL'),
    (2, 'What is PostgreSQL');

Two rows have been inserted into the publish_article table successfully. The above screenshot clears that we didn’t insert any value in the publish_date column. Let’s run the SELECT statement to see the data inserted into the publish_article table:
    
    
    SELECT * FROM publish_article;

By default, Postgres assigns the current date and time to the publish_date column. This way, you can specify the CURRENT_TIMESTAMP as a column's default value.

That was all you needed to learn about the Postgres CURRENT_TIMESTAMP() Function.

 **Conclusion**

The CURRENT_TIMESTAMP function retrieves the current date, time, and timezone when a transaction starts. Round the "seconds" fields to specific fractional digits by passing the "precision" argument to the CURRENT_TIMESTAMP function. However, by omitting the precision parameter, the CURRENT_TIMESTAMP will return the current date, time, and time zone with a full fractional second’s precision. This write-up explained what CURRENT_TIMESTAMP is and how to use it in PostgreSQL with examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-current_timestamp-function-with-examples/)

---

# How To Find and Delete Duplicate Rows in PostgreSQL

> In PostgreSQL, we can use the &quot;DELETE USING&quot; statement, subquery, or Postgres immediate table to delete duplicate rows from a table.

Deleting duplicate rows from a table is a little bit tricky. Finding and deleting duplicate rows is pretty easy if the table has a limited number of records. However, if the table has enormous data, then finding and deleting the duplicates can be challenging.

PostgreSQL provides multiple ways to find and delete duplicate rows in PostgreSQL. This post discusses the below-listed methods to find and delete duplicate rows in PostgreSQL:

● How to Find Duplicate Rows in PostgreSQL?

● How to Delete Duplicates in Postgres Using a DELETE USING Statement?

● How to Delete Duplicates Using Subquery?

● How to Delete Duplicates Using Immediate Tables in Postgres?

To illustrate this concept more clearly, let's create a sample table.

 **Creating Sample Table**

Let’s create a table named programming_languages and insert some duplicate rows in it:
    
    
    CREATE TABLE programming_languages(
    id INT,
    language VARCHAR(100) NOT NULL
    );

The programming_languages table has been created successfully. Let’s insert some data into it:
    
    
    INSERT INTO programming_languages(id, language) 
    values(1, 'C'),
    (2, 'C++'),
    (3, 'C'),
    (4, 'Java'),
    (5, 'Python'),
    (6, 'C++'),
    (7, 'C++'),
    (8, 'R'),
    (9, 'Java'),
    (10, 'JavaScript');

Let’s run the SELECT command to see the newly inserted data from the programming_languages table:
    
    
    SELECT * FROM programming_languages;

The output shows that the programming_languages table contains some duplicated records. Since the programming_languages table has limited records, so we can calculate the duplicates easily. However, counting the duplication of rows in large tables is challenging.

 **How to Find Duplicate Rows in PostgreSQL?**

Use the COUNT() function to find the duplicate rows from a table. Execute the below code to find the duplicate rows in the programming_languages table:
    
    
    SELECT language, COUNT(language)
    FROM programming_languages
    GROUP BY language
    HAVING COUNT(language)> 1;

From the programming_languages table, the SELECT statement will fetch the language column and number of occurrences of a language.

The GROUP BY clause will split the result set into groups based on the language column.

The HAVING clause will pick only those languages that occur more than once:

This way, you can find the duplicate rows using the COUNT() function.

 **How to Delete Duplicates in Postgres Using a DELETE USING Statement?**

To delete duplicate rows from a table, use the below statement:
    
    
    DELETE FROM
    programming_languages dup_lang
    USING programming_languages dist_lang
    WHERE dup_lang.id < dist_lang.id
    AND dup_lang.language = dist_lang.language;

The above snippet performs the following tasks:

\- Joined the programming_languages table to itself.

\- Checked if two records (dup_lan.id < dist_lang.id) have the same value in the language column.

\- If yes, then the duplicated record will be deleted.

The output shows that four rows(duplicate) have been deleted from the programming_languages table. Let’s confirm the rows(duplicate) deletion using the below command:
    
    
    SELECT * FROM programming_languages;

The output shows that the programming_languages table contains only unique languages. It proves that the duplicated rows have been deleted successfully.

As you can see from the output, the DELETE USING query deletes the languages with low IDs and retains the languages with high IDs. If you want the languages with high ids instead of low ids then use the “>” sign in the WHERE clause:
    
    
    DELETE FROM
    programming_languages dup_lang
    USING programming_languages dist_lang
    WHERE dup_lang.id > dist_lang.id
    AND dup_lang.language = dist_lang.language;

Let’s confirm the deletion of the rows using the below command:
    
    
    SELECT * FROM programming_languages;

This time the DELETE USING statement deletes the duplicates with high ids.

 **How to Delete Duplicate Rows Using Subquery in PostgreSQL?**

Run the following query for deleting duplicate rows from a table by employing a subquery:
    
    
    DELETE FROM programming_languages
    WHERE id IN (SELECT id FROM 
    (SELECT id, 
    ROW_NUMBER() OVER(PARTITION BY language
    ORDER BY id ASC) AS row_num
    FROM programming_languages) lang
    WHERE lang.row_num > 1 );

The above-given query will perform the following functionalities:

\- Use a subquery in the WHERE clause.

\- Within the subquery, each row of a result set will have a unique integer value assigned by the ROW_NUMBER() function.

\- Subquery will return the duplicate records except for the first row.

\- The DELETE FROM query will delete the duplicates that are returned by the subquery.

The above query will delete the duplicates with low ids. Let’s run the SELECT statement to confirm the working of the above query:
    
    
    SELECT * FROM programming_languages;

As you can see from the output, the result set does not contain any duplicate records. To retain records with the greatest ID, specify the DESC in the ORDER BY clause.

 **How to Delete Duplicate Rows Using Immediate Tables in PostgreSQL?**

In Postgres, you can use the immediate tables to delete duplicate rows. For better understanding, follow the below-listed stepwise procedure:

 **Step 1: Create a Table**

Firstly, you have to create a table having the same structure as the targeted table (programming_languages). To do this, run the below command:
    
    
    CREATE TABLE temp_table (LIKE programming_languages);

Let’s check the newly created table’s structure using the SELECT command:
    
    
    SELECT * FROM temp_table;

The output verifies that the temp_table has the same structure as the programming_languages table.

 **Step 2: Insert Distinct Records to the temp_table**

Let’s insert the distinct rows from the programming_languages(source) table to the newly created table using the following command:
    
    
    INSERT INTO temp_table(id, language)
    SELECT DISTINCT ON (language) id, language
    FROM programming_languages;

Let’s verify the table’s records using the below-given query:
    
    
    SELECT * FROM temp_table;

The output shows that the temp_table has only unique records.

 **Step 3: Drop the Source Table**

Use the DROP TABLE command to drop the source table (i.e. programming_languages):
    
    
    DROP TABLE programming_languages;

The source table has been dropped successfully.

 **Step 4: Rename the temp_table to the programming_languages**

Utilize the ALTER TABLE statement for renaming the temp_table to the programming_languages:
    
    
    ALTER TABLE temp_table 
    RENAME TO programming_languages;

Let’s run the above statement to verify weather the temp_table has been renamed to programming_languages or not:

The temp_table has been altered successfully. Here are the details of programming_languages table:
    
    
    SELECT * FROM programming_languages;

This way you can find and delete the duplicate rows from a table in PostgreSQL.

 **Conclusion**

PostgreSQL offers multiple ways to find and delete duplicate rows. For finding the duplicates, we can utilize the Postgres COUNT() function. While to remove duplicate rows, we can use the “DELETE USING” Statement, subquery, or Postgres immediate Table. This write-up explained each method with practical examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-and-delete-duplicate-rows-in-postgresql/)

---

# How to Use MIN() Function in PostgreSQL

> In PostgreSQL, the MIN() function retrieves a set&#x27;s minimum value. Use the LEAST() function to get the minimum/least value from more than one column

PostgreSQL offers a built-in MIN() function that retrieves a set's minimum value. It takes a column’s name as an argument and returns the least value of the targeted set. The specified column’s type can be a string, number, or any other comparable data type.

Let’s learn the working of the MIN() function through Practical examples.

 **How to Use MIN() Function in Postgres?**

The below snippet will show you the basic syntax of the MIN() function:
    
    
    MIN(exp);

Here, exp represents an expression. Let's implement it practically to gain a deeper understanding of the MIN() function.

 **Example #1: How to Use the MIN() Function on Table’s Data?**

Our database already has a table named bike_details. Here are the table details:
    
    
    SELECT * FROM bike_details;

Let’s find the bike with the minimum price. To do that, we will use the Postgres MIN() Function:
    
    
    SELECT MIN(bike_price)
    FROM bike_details;

The output shows that the bike_details table's most cost-effective bike costs 80000.

 **Example #2: How to Use MIN() Function With a Subquery?**

Suppose we want to fetch all the details about the most cost-effective bike. To do so, we will use the MIN() function with a subquery as follows:
    
    
    SELECT * FROM bike_details
    WHERE bike_price = (
    SELECT MIN(bike_price)
    FROM bike_details
    );

This is how the MIN() function works with the subquery in Postgres.

 **Example #3: How to Use the MIN() Function With GROUP BY Clause?**

The following command will return the bike with the least price from each group. Let’s utilize the GROUP BY clause as follows:
    
    
    SELECT
    bike_model,
    MIN(bike_price)
    FROM bike_details
    GROUP BY bike_model;

From the output, you can observe that this time the MIN() function returned the minimum value for each group.

 **Example #4: How to Use the MIN() Function With HAVING Clause?**

We can specify a special condition with the MIN() function using the HAVING clause:
    
    
     SELECT
     bike_model,
     MIN (bike_price)
     FROM
     bike_details
     GROUP BY
     bike_model
     HAVING MIN(bike_price) >80000;

In this example, we utilized the MIN() function along with the GROUP BY clause to find the bike with the least price from each group. Next, we utilized the HAVING clause specifying that the bike price must be greater than 80000. Here is the final outcome of the above query:

The output shows that the MIN() function retrieves the bikes having the least price in their respective group. However, it skipped the bikes having a price less than or equal to 80000.

 **Example #5: How to Get the MINIMUM Value From Multiple Columns?**

Use the LEAST() function to get the minimum/least value from more than one column. We have modified the bike_details table by inserting a new column in it. The below-given command will show the modified table:
    
    
    SELECT * FROM bike_details;

Let’s utilize the LEAST() function to fetch the least value from the bike_price and bike_new_price columns:
    
    
    SELECT
    bike_model,
    LEAST(bike_price, bike_new_price) AS least_price
    FROM
    bike_details;

In this way, you can find the least value from multiple columns using the LEAST() function.

 **Conclusion**

PostgreSQL provides an in-built function named MIN() that retrieves a set's minimum value. Use the LEAST() function to get the minimum/least value from more than one column. In this post, we have learned how to use the MIN() function with the HAVING clause, GROUP BY clause, and subquery. This write-up considered different examples to demonstrate the working of the MIN() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-min-function-in-postgresql/)

---

# How to Use MAX() Function in PostgreSQL

> PostgreSQL offers a built-in MAX() function that is used to retrieve the maximum value of a set. The MAX() function has multiple real-life implementations, suc…

PostgreSQL offers a built-in **MAX()** function that is used to retrieve the maximum value of a set. The MAX() function has multiple real-life implementations, such as fetching the highest-paid employee, finding a top-ranked student, and so on. So, let’s learn the working of the MAX() function through Practical examples.

 **How to Use MAX() Function in Postgres?**

The below snippet will show you the basic syntax of the MAX() function:
    
    
    MAX(exp);

Here, exp represents an expression. Let’s practically implement the MAX() function to get profound knowledge about it.

 **Example #1: How to Use MAX() Function on Table’s Data?**

Suppose we have a table named bike_details. Let’s run the SELECT statement to get all the records of the bike_details table:
    
    
    SELECT * FROM bike_details;

Let’s find the bike that has the maximum price using the MAX() Function:
    
    
    SELECT MAX(bike_price)
    FROM bike_details;

The output shows that in the bike_details table, the most expensive bike costs 150000.

 **Example #2: How to Use MAX() Function With a Subquery?**

Suppose we want to fetch all the details about the most expensive bike. To do so, we can use the MAX() function with the subquery as follows:
    
    
    SELECT * FROM bike_details
    WHERE bike_price = (
    SELECT MAX (bike_price)
    FROM bike_details
    );

This time, we got detailed information about the desired bike(bike having the highest price).

 **Example #3: How to Use the MAX() Function With GROUP BY Clause?**

The following command will return the bike with the highest price from each group. Let’s utilize the GROUP BY clause as follows:
    
    
    SELECT
    bike_model,
    MAX (bike_price)
    FROM bike_details
    GROUP BY bike_model;

From the output, you can observe that this time the MAX() function returned the maximum value for each group.

 **Example #4: How to Use the MAX() Function With HAVING Clause?**

We can specify a special condition with the MAX() function using the HAVING clause:
    
    
    SELECT
    bike_model,
    MAX (bike_price)
    FROM
    bike_details
    GROUP BY
    bike_model
    HAVING MAX(bike_price) >100000;

In this example, we utilized the MAX() function along with the GROUP BY clause to find the bike from each group that has the highest price. Next, we utilized the HAVING clause specifying that the bike price must be greater than 100000. Here is the final outcome of the above query:

The output shows that the MAX() function retrieves the bikes having the highest price in their respective group. However, it skipped the bikes having a price less than or equal to 100000.

 **Example #5: How to Get the Maximum Value From Multiple Columns?**

Use the GREATEST() function to get the maximum/greatest value from more than one column. We have modified the bike_details table by inserting a new column in it. The below-given command will show the modified table:
    
    
    SELECT * FROM bike_details;

Now, we will utilize the GREATEST() function to fetch the greatest value from the bike_price and bike_new_price columns:
    
    
    SELECT
    bike_model,
    GREATEST (bike_price, bike_new_price) AS greatest_price
    FROM
    bike_details;

This is how the GREATEST() function works in PostgreSQL.

 **Conclusion**

PostgreSQL provides an in-built function named MAX() that is used to retrieve the maximum value of a set. The MAX() function has various use cases, such as fetching the highest-paid employee, finding a top-ranked student, etc. In this write-up, we have learned how to use the MAX() function with the HAVING clause, GROUP BY clause, and subquery. This write-up considered different examples to demonstrate the working of the MAX() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-max-function-in-postgresql/)

---

# How to Use AVG() Function in PostgreSQL

> In PostgreSQL, the AVG() function is used to retrieve the average of a set. The DISTINCT operator is used with the AVG() function to find the average of distin…

PostgreSQL provides a built-in **AVG()** function that is used to retrieve the average of a set. Postgres allows us to compute the average of distinct values using an additional option/operator, DISTINCT. While calculating the average of a set, the AVG() function skips the “NULL” values.

Let’s learn the working of the AVG() function through Practical examples.

 **How to Use AVG() Function in Postgres?**

The below snippet demonstrates the basic syntax of the AVG() function:
    
    
    AVG(col_name);

Let’s implement the AVG() function practically to get profound knowledge.

 **Example #1: How to Use AVG() Function on Table’s Data?**

We have created a table named bike_details. Let’s execute the SELECT command to get all the records of the bike_details table:
    
    
    SELECT * FROM bike_details;

Let’s compute the average of bike_price column using the AVG() Function:
    
    
    SELECT AVG(bike_price)
    FROM bike_details;

Let’s run the below query to get the average up to specific decimal places:
    
    
    SELECT AVG(bike_price)::numeric(10, 3) 
    FROM bike_details;

The above query will return the average of bike_price column in an easily understandable format, i.e., the AVG() will return the result up to three decimal places:

Output proves the working of AVG() function.

 **Example #2: How Does the AVG() Function Deal With NULL Values in Postgres?**

We inserted a new record to the bike_details table. Let’s check the updated table using the below command:
    
    
    SELECT * FROM bike_details;

We inserted a new record against the bike_id 4. Let’s run the below query to find the average of the bike_price column. The bike_details table contains some NULL values. This example will let you understand how the AVG() function deals with the NULL values in Postgres:
    
    
    SELECT AVG (bike_price):: NUMERIC(10, 2) 
    FROM bike_details;

The output shows that the AVG() ignores the NULL values.

 **Example #3: How to Use Distinct Operator With the AVG() Function?**

Specify the DISTINCT operator before the column’s name to compute the average of the distinct values:
    
    
    SELECT AVG(DISTINCT bike_price):: numeric(10,2)
    FROM bike_details;

You will get the following results on successful execution of the above-given query:

The output proves that the AVG() function returns the average of distinct values.

 **Example #4: How to Use the AVG() Function to Compute Groups ' Average?**

Execute the below command to compute the average of the bike_price column based on the groups. To do that, utilize the GROUP BY clause as follows:
    
    
    SELECT
    bike_model,
    AVG (bike_price):: NUMERIC(10, 2)
    FROM bike_details
    GROUP BY bike_model;

From the output, you can observe that this time the AVG() function computed the average of groups.

 **Conclusion**

PostgreSQL offers an in-built function named **AVG()** that returns the average of a set. Postgres allows us to compute the average of distinct values using an option/operator, DISTINCT. While calculating the average of a set, the AVG() function skips the “NULL” values. This write-up considered different scenarios to demonstrate the working of the AVG() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-avg-function-in-postgresql/)

---

# PostgreSQL SUM() Function With Practical Examples

> The SUM() is used to perform the addition on a set of values. Use the DISTINCT option with the SUM() function to calculate the sum of distinct values.

PostgreSQL provides a built-in **SUM()** function that is used to perform the addition on a set of values. Postgres allows us to compute the sum of distinct values using an additional option/operator, DISTINCT. While performing addition, the SUM() function skips the “NULL” values.

Let’s learn the working of the SUM() function through Practical examples.

 **How to Use SUM() Function in Postgres?**

The below snippet illustrates the syntax of the SUM() function:
    
    
    SUM(DISTINCT exp | col_name);

Here, “exp” represents an expression while col_name represents the column name. In the SUM() function, either you can specify an expression to calculate its sum, or you can specify a column name on which you want to perform the addition.

 **Example #1: How to Use SUM() Function on Table’s Data?**

Let’s say we have a table bike_details. We will execute the SELECT query to fetch all the records of the bike_details table:
    
    
    SELECT * FROM bike_details;

Let’s perform addition on the bike_price column using the SUM() Function:
    
    
    SELECT SUM(bike_price) AS total_price
    FROM bike_details;

The output authenticates that the SUM() function returns the sum of the bike_price column.

 **Example #2: How to Calculate the Sum of Distinct Values Using the SUM() Function?**

Specify the DISTINCT option before the column’s name to perform the addition on the distinct values:
    
    
    SELECT SUM(DISTINCT bike_price) AS total_price
    FROM bike_details;

Here is what you will get on successful execution of the above-given query:

This time, the SUM() function returned the sum of distinct values.

 **Example #3: How to Use the SUM() Function to Compute the Sum of Groups?**

Run the following query to perform the addition on the bike_price column based on the groups. Let’s utilize the GROUP BY clause to group the bikes having the same model:
    
    
    SELECT
    bike_model,
    SUM (bike_price) AS total_price
    FROM bike_details
    GROUP BY bike_model;

From the output, you can observe that this time the SUM() function returned the sum in the form of groups.

 **Example #4: How to Use SUM() Function With HAVING Clause in Postgres?**

Let’s perform the addition on the bike_price column based on a specific condition, i.e., bike price >= 115,000. To do that, we will use the Postgres HAVING Clause:
    
    
    SELECT
    bike_model,
    SUM (bike_price) AS total_price
    FROM bike_details
    GROUP BY bike_model
    HAVING SUM(bike_price) > 115000;

In this example, we utilized the SUM() function to calculate the sum of the bike_price column. Next, we utilized the GROUP BY clause to group the bikes based on their model and the HAVING clause to specify a condition.

 **Example #4: How to Use SUM() Function on An Expression in Postgres?**

We modified the bike_details table and added a new column named “price_change”. The updated table will look like this:
    
    
    SELECT * FROM bike_details;

Let’s specify an expression within the SUM() function and see how the SUM() function work:
    
    
    SELECT bike_model, SUM(DISTINCT bike_price + price_change)
    FROM bike_details
    GROUP BY bike_model;

In this example, we perform the addition on the bike_price and price_change column. We utilized the group by clause to show the updated price of each model.

This way, you can use the SUM() function to perform the addition in PostgreSQL.

 **Conclusion**

PostgreSQL offers an in-built function named **SUM()** that is used to perform the addition on a set of values. Postgres allows you to compute the sum of distinct values using an additional option/keyword, DISTINCT. This write-up considered different scenarios to demonstrate the working of the SUM() function in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-sum-function-with-practical-examples/)

---

# How to Use COUNT() Function in PostgreSQL

> The table rows can be counted using PostgreSQL&#x27;s COUNT() function. It is an aggregate function that enables us to count the rows that meet the specified condit…

The table rows can be counted using PostgreSQL's **COUNT()** function. It is an aggregate function that enables us to count the rows that meet the specified condition. There are multiple ways to use the **COUNT()** function, such as COUNT(*), COUNT(col_name), and COUNT(DISTINCT col_name). Each implementation of the COUNT() function serves a different functionality.

Let’s learn the working of the **COUNT()** function through Practical examples.

 **How to Use COUNT(*) Function in PostgreSQL?**

In PostgreSQL, the COUNT(*) function is used to get all the rows, including duplicates and NULL. The below snippet illustrates the syntax of the Postgres COUNT(*) function:
    
    
    SELECT COUNT(*) 
    FROM tab_name;

COUNT(*) function will fetch all the rows(including duplicates and NULL) from the targeted table based on the specified condition.

 **Example: How Does the COUNT(*) Function Work in PostgreSQL?**

We have created a bike_details table that contains some redundant/duplicated data. Here are the details of the bike_details table:

The bike_details table has some duplicates and null values. The following query will calculate the total number of rows in the bike_details table:
    
    
    SELECT COUNT(*) 
    FROM bike_details;

The output shows that the bike_details table has 10 rows. It proves that the COUNT(*) function counted all the rows, including the duplicates and null.

 **How to Use COUNT(col_name) Function in PostgreSQL?**

In PostgreSQL, the COUNT(col_name) function skips the null values and returns the rest of the records, including duplicates. The below snippet depicts the syntax of the Postgres COUNT(col_name) function:
    
    
    SELECT COUNT(col_name)   
    FROM tab_name;

The below-given example will provide you more clarity about the COUNT(col_name) function.

 **Example: How Does the COUNT(col_name) Function Work in PostgreSQL?**

Let’s implement the COUNT(col_name) function on the bike_color column:
    
    
    SELECT COUNT(bike_color)   
    FROM bike_details;

The COUNT(col_name) function returns ‘9’ instead of ‘10’. It proves that the COUNT(col_name) function counted all the rows excluding the ‘null’.

 **How to Use COUNT(DISTINCT col_name) Function in Postgres?**

In PostgreSQL, executing the COUNT() function along with the DISTINCT keyword will skip the duplicated records and return the unique ones only. The below snippet illustrates the syntax of the Postgres COUNT(DISTINCT col_name) function:
    
    
    SELECT COUNT(DISTINCT col_name) 
    FROM tab_name;

Let’s comprehend the working of the COUNT(DISTINCT) function with the below-given example.

 **Example: How Does the COUNT(DISTINCT) Function Work in PostgreSQL?**

Let’s execute the SELECT statement with COUNT(DISTINCT) function to count the unique records of the bike_color column:
    
    
    SELECT COUNT(DISTINCT bike_color) 
    FROM bike_details;

The output shows that there are only three **distinct** colors in the bike_color column.

 **How to Use the Postgres COUNT() Function With GROUP BY Clause?**

Use the GROUP BY clause along with the COUNT() function to calculate the number of items for every group. For instance, grouping the bike colors and calculating the number of items for each group.

 **Example: How Does the COUNT() Function Work With the GROUP BY Clause in Postgres?**

By using the **GROUP BY** clause, let's group the items in the bike_color column and calculate the number of items in each group using the COUNT() function:
    
    
    SELECT bike_color, COUNT(bike_color)
    FROM bike_details
    GROUP BY bike_color;

This is how you can calculate the number of items present in each group.

Similarly, you can use the Postgres WHERE clause or HAVING clause to count the rows based on a specific condition.

 **Conclusion**

The table rows can be counted using PostgreSQL's **COUNT()** function. There are multiple ways to use the **COUNT()** function, such as COUNT(*), COUNT(col_name), and COUNT(DISTINCT col_name). The COUNT(*) function returns all the records, including duplicates and NULL, COUNT(col_name) returns all records excluding the NULL values, while the COUNT(DISTINCT col_name) returns only unique records. This write-up explained various implementations of the COUNT() function using different examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-count-function-in-postgresql/)

---

# How to Use the POSITION() Function in PostgreSQL

> In PostgreSQL, to get the substring’s location in a string, the POSITION() function is used. It returns an integer that represents the substring’s location.

In PostgreSQL, to get the location of a substring within the specific string, the **POSITION()** function is used. It is a case-sensitive function that takes two arguments: a substring to be located and a string from which the targeted substring will be searched. The **POSITION()** function returns a numeric value representing the substring’s location.

This post will show you how to use the Postgres **POSITION()** function to get the location of a substring. So, let’s start.

 **How to Use the POSITION() Function in PostgreSQL?**

The below snippet illustrates the syntax of the **POSITION()** function:
    
    
    POSITION(sub_str IN str);

Here, sub_str is a substring to be searched/located while the str represents a string from which the targeted sub_str will be searched.

 **Note:** The **POSITION()** function will return ‘0’ if the substring doesn’t exist in the targeted string. It will return NULL if the string or substring argument is NULL.

 **Example #1: How to Locate a Substring in a String Using the POSITION() Function?**

Let’s understand how the **POSITION()** function works in PostgreSQL:
    
    
    SELECT POSITION('commandprompt' IN 'Welcome to commandprompt.com');

The **POSITION()** function will find the substring in the given string. Once the substring is found in the targeted string, then the POSITION() function will return the location of that substring:

The output shows ‘12’, indicating that the substring occurs at the 12th index.

 **Example #2: Is POSITION() Function Case Sensitive?**

Let’s consider the following query that depicts the behavior of the **POSITION()** function with respect to case sensitivity:
    
    
    SELECT POSITION('Commandprompt' IN 'welcome to commandprompt.com');

The first letter of the substring is capital, i.e., “Commandprompt” while in the targeted string all the letters are in lowercase, i.e., “welcome to commandprompt.com”. If the **POSITION()** function returned ‘0’, it means the substring was not found. Otherwise, the **POSITION()** function will return the substring’s location:

The **POSITION()** function returned ‘0’, which means that the POSITION() function is a case-sensitive function.

 **Example #3: Multiple Occurrences of the Substring in a String**

Let’s search for a substring that occurs multiple times in the targeted string:
    
    
    SELECT POSITION('com' IN 'welcome to commandprompt.com');

This time we specified ‘com’ as a substring to the POSITION() function. The ‘com’ substring occurs three times in the targeted string. The POSITION() function will return the location of only the first occurrence as shown in the following snippet:

The output shows ‘4’, indicating that the first occurrence of the specified substring is at the 4th index.

 **Example #4: How to Use the POSITION() Function on Table’s Data?**

We created a table named ‘employee_info’. Let’s run the SELECT statement to see the details of the employee_info table:
    
    
    SELECT * FROM employee_info
    ORDER BY employee_id ASC;

Let’s apply the **POSITION()** function on the emplooye_info table to locate the position of a substring “Author”:
    
    
    SELECT POSITION('Author' IN employee_designation)
    FROM employee_info
    ORDER BY employee_id ASC;

The substring “Author” isn't found in the third and fifth row, so the **POSITION()** function returns ‘0’. The rest of the rows contain the desired substring, so the **POSITION()** function returns the location where the substring occurs.

 **Conclusion**

In PostgreSQL, to get the location of a substring within the specific string, the **POSITION()** function is used. It returns a numeric value representing the substring’s location. It is a case-sensitive function that takes two arguments: a substring to be located and a string from which the targeted substring will be searched. This write-up considered various examples to demonstrate the working of the POSITION() function.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-position-function-in-postgresql/)

---

# How to Use NOT IN Operator in PostgreSQL

> In PostgreSQL, the NOT IN operator filters the query results and returns all the values of a result set except the specified values.

In Postgres, the **NOT IN** operator contradicts the working of the [**IN**](<https://www.commandprompt.com/education/how-to-use-in-operator-in-postgresql/>)[ operator](<https://www.commandprompt.com/education/how-to-use-in-operator-in-postgresql/>). The **NOT IN** operator filters the query results and returns all the values of a result set except the specified values. In simple terms, the **NOT IN** operator excludes the specified values and returns the rest of the values.

Through examples, this article will explain how the **NOT IN** operator works in PostgreSQL. So, let’s begin.

 **How Does the NOT IN Operator Work in PostgreSQL?**

The NOT IN operator is used in conjunction with the Postgres [WHERE clause](<https://commandprompt.com/education/how-to-use-where-clause-in-postgresql/>) and can be used on both string and numeric data. It returns all the values of a result set except the specified values. Here is the basic syntax of the Postgres NOT IN operator:
    
    
    WHERE col_name NOT IN (val_1, val_2, val_3, ..., val_N);

Let’s implement it practically to learn how the NOT IN operator works in PostgreSQL.

 **Example #1: How to Use NOT IN Operator With the Numeric Data?**

A table has already been created named “article_details”. Let’s execute the SELECT query to fetch the table’s records:
    
    
    SELECT * FROM article_details;

The article_details table has 12 rows. Suppose we have to retrieve all the articles except two whose ids are 4 and 8. To achieve this purpose, we will use the **NOT IN** operator as follows:
    
    
    SELECT *
    FROM article_details
    WHERE article_id NOT IN(4,8);

The **NOT IN** operator returned all the values that were not specified in the NOT IN operator.

 **Example #2: How Does the NOT IN Operator Work With the String Data?**

Let’s consider the same article_details table and this time, use the NOT IN operator on the string data as follows:
    
    
    SELECT *
    FROM article_details
    WHERE article_title NOT IN('PostgreSQL CREATE TABLE','PostgreSQL IN Operator');

As a result of NOT IN operator, the specified article titles were excluded, and the rest of the details were returned.

That was all the necessary information regarding Postgres NOT IN operator.

 **Conclusion**

In PostgreSQL, the **NOT IN** operator filters the query results and returns all the values of a result set except the specified values. The NOT IN operator is used in conjunction with the Postgres WHERE clause and can be used on both string and numeric data. This write-up goes through a couple of examples to demonstrate the working of the NOT IN operator.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-not-in-operator-in-postgresql/)

---

# How to Get Top N Rows in PostgreSQL

> To get the top n rows of a table, the LIMIT clause is used in PostgreSQL. It assists us in getting the subset of rows generated by a query.

In PostgreSQL, a **LIMIT** clause allows us to get/fetch the top n rows. The **LIMIT** clause allows us to extract a subset of rows from a resultant table returned by a query. **LIMIT** is an optional clause in Postgres; however, if we have to fetch the first N rows, then the **LIMIT** clause must be used.

This post will explain how to get the first N rows in PostgreSQL through practical examples. So, let’s begin.

 **How to Get/Fetch Top N Rows in Postgres?**

As the name suggests, the LIMIT clause is used to fetch limited records from a result set. The below snippet demonstrates the basic syntax of the LIMIT clause:
    
    
    SELECT col_list 
    FROM tab_name
    ORDER BY ASC | DESC
    LIMIT no_of_rows;

Let’s comprehend the above syntax stepwise:

\- col_list represents a single or multiple columns to be selected.

\- tab_name represents a table from which the data will be fetched.

\- ORDER BY is an optional clause that sorts the table’s records in a particular order.

\- The LIMIT clause determines how many rows to fetch.

 **Example #1: How to Fetch Top Five Rows of a Table in Postgres?**

We have a table named “article_details” that consists of three columns: article_id, article_title, and published_date. Let’s run the SELECT statement to fetch the table’s data:
    
    
    SELECT *
    FROM article_details;

The article_details table has twelve unsorted records. Suppose we want to get the top five articles regarding their ids. To achieve this, let’s run the below query:
    
    
    SELECT *
    FROM article_detail
    ORDER BY article_id ASC
    LIMIT 5;

The LIMIT clause succeeded in fetching the top five records with respect to the article_id column.

 **Example #2: How to Fetch Top Five Recently Published Articles?**

Consider the same article_details table having three columns as shown in the previous example. This time we need to fetch the top five articles concerning their published date:
    
    
    SELECT *
    FROM article_details
    ORDER BY published_date DESC
    LIMIT 5;

Since we want to fetch the top five recently published articles, so we sorted the published_date column in descending order. Next, we utilized the LIMIT clause to specify the number of records to be fetched:

Notice that the LIMIT clause successfully fetched the top five recently published articles.

That was all the basics regarding how to get top N rows in PostgreSQL. You can get detailed information about the LIMIT clause from this [article](<https://commandprompt.com/education/how-to-use-limit-clause-in-postgresql/>).

 **Conclusion**

To get the top n rows of a table, the LIMIT clause is used in PostgreSQL. The LIMIT clause allows us to extract a subset of rows from a resultant table returned by a query. It is an optional clause; however, if we have to fetch the first N rows, then the LIMIT clause must be used. This article uses a couple of examples to demonstrate how to get top N rows in PostgreSQL using the LIMIT clause.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-top-n-rows-in-postgresql/)

---

# PostgreSQL SMALLINT Data Type With Examples

> In PostgreSQL, the SMALLINT is used to store small integer values. It takes 2 bytes of storage and can store integers between -32,768 to +32,768.

PostgreSQL offers different data types to deal with integer values, **SMALLINT** is one of them. A SMALLINT data type takes two bytes of storage and can store integers between -32,768 and +32,768. It is used to store small values like someone's age, the number of pages in a book, etc.

So, let’s learn how the SMALLINT data type works with the help of examples.

###  **Why SMALLINT?**

The below-listed points describe the need for the SMALLINT data type:

\- The INTEGER/INT is a data type commonly used data type in PostgreSQL to store the integers. However, If we have to store the small numeric values like people’s age, then we can use the SMALLINT data type instead of the INTEGER data type.

\- The SMALLINT takes a minimum storage size to store a value. So, it is preferred that if you have a small numeric value, then use the SMALLINT data type.

\- If the value to be stored exceeds the limit of the SMALLINT data type, then use the INTEGER data type.

\- The BIGINT data type should be used only if the value to be stored doesn’t fit in the range of INTEGER data type.

 **Note:** PostgreSQL will throw an error if you insert an out-of-range value.

###  **How to Use SMALLINT in Postgres?**

Let’s consider a couple of examples to understand how the SMALLINT data type works in PostgreSQL.

###  **Example #1: Create a Table Having SMALLINT Data Type**

Here is the code to create a column with SMALLINT data type:
    
    
    CREATE TABLE student_info(
    std_id SMALLINT NOT NULL,
    std_age SMALLINT,
    std_name TEXT 
    );

Here, we [created a table](<https://www.commandprompt.com/education/different-methods-to-create-a-table-in-postgresql/>) named student_info that consists of three columns: std_id, std_age, and std_name. The data type of std_id and std_age columns is SMALLINT, while std_name has a TEXT data type:

The above snippet shows that the table named student_info has been created successfully. Let’s verify the table’s creation using the [SELECT](<https://commandprompt.com/education/how-to-use-select-query-in-postgresql/>) query:
    
    
    SELECT * FROM student_info;

The table named student_info with three columns has been created successfully.

###  **Example #2: Insert SMALLINT Data Into Student_info Table**

Let’s execute the [INSERT INTO](<https://commandprompt.com/education/how-to-use-insert-query-in-postgresql/>) command to insert data into the student_info table:
    
    
    INSERT INTO student_info(std_id, std_age, std_name)
    VALUES (1, 18, 'Mike'),
    (2, 17, 'Joe'),
    (3, 19, 'Ambrose'),
    (4, 18, 'Natalia'),
    (5, 17, 'Stephanie'),
    (6, 18, 'Michael'),
    (7, 19, 'John'),
    (8, 20, 'Naomi'),
    (9, 20, 'Trish'),
    (10, 18, 'Jordan');

Ten records have been inserted into the student_info table successfully. Let’s execute the SELECT statement to check the newly inserted data:
    
    
    SELECT * FROM student_info;

All the records have been inserted into the student_info table successfully.

That was all the basics you should learn before starting with the SMALLINT data type.

###  **Conclusion**

In PostgreSQL, the **SMALLINT** is one of the integer data types that is used to store small integer values. The SMALLINT data type takes only two bytes of storage and can store integers between -32,768 to +32,768. Using some examples, this write-up demonstrated what SMALLINT is, what is the need for SMALLINT data type, and how to use it in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-smallint-data-type-with-examples/)

---

# PostgreSQL VARCHAR Data Type With Examples

> VARCHAR(n) or CHARACTER VARYING(n) is a data type in PostgreSQL that stores textual data within a limited range. It can store n number of characters.

PostgreSQL offers various data types to deal with textual data such as CHARACTER/CHAR, TEXT, and **VARCHAR**. The VARCHAR(n) data type stores the character type data in a limited range. The maximum range of VARCHAR is 65,535 bytes and a string that exceeds this range can’t be stored in the VARCHAR data type.

With the help of examples, this post will explain how to use the VARCHAR data type in PostgreSQL.

###  **What is VARCHAR and How to Use it in PostgreSQL?**

VARCHAR(n) or CHARACTER VARYING(n) is a data type in PostgreSQL that stores textual data. It can store ‘n’ number of characters. The syntax of the VARCHAR data type will be as follows:
    
    
    var_name VARCHAR(n);

Where n represents the size of the string(number of characters to be stored). ‘n’ must be a positive integer. If you didn’t specify the size (n) in the VARCHAR data type then it will act as the TEXT data type.

 **Note:** If you try to insert a string that exceeds the specified length/size then PostgreSQL will throw an error.

Now let’s have a look at the examples given below to get a profound understanding of the VARCHAR data type.

###  **Example #1: Create a Table With VARCHAR data Type**

Let’s create a table named employee_profile using the CREATE TABLE command.
    
    
    CREATE TABLE employee_profile(
    emp_name VARCHAR(30) NOT NULL,
    emp_designation VARCHAR(50) NOT NULL,
    emp_address VARCHAR(100) NOT NULL
    );

We created a table named employee_profile that consists of three columns: emp_name, emp_address, emp_designation. All three columns are of VARCHAR data type:

\- The emp_name column can store thirty characters, emp_designation can store fifty characters, while the emp_address column can store hundred characters:

The table “employee_profile” has been created. Let’s verify the table formation using the SELECT statement:
    
    
    SELECT * FROM employee_profile;

The output verifies that the employee_profile table contains three columns of VARCHAR data type.

###  **Example #2: Insert VARCHAR Data Into employee_profile Table**

Let’s insert some data to the employee_profile table using the INSERT INTO command:
    
    
    INSERT INTO employee_profile(emp_name, emp_designation, emp_address)
    VALUES ('Ambrose', 'Web Designer', 'ambrose123@abc.com'),
    ('Paul', 'Web Designer', 'paul123@abc.com'),
    ('Seth', 'Web Developer', 'seth123@abc.com'),
    ('MIKE', 'Web Developer', 'mike123@abc.com'),
    ('Stephanie', 'HR Manager', 'hr@abc.com');

Five records have been inserted into the employee_profile table. Let’s check the newly inserted table’s data using the SELECT query:
    
    
    SELECT * FROM employee_profile;

This is how the VARCHAR data type works in PostgreSQL.

###  **Example #3: Value Too Long Error**

If you try to insert a string that is greater than the specified length then you will face an error:
    
    
    INSERT INTO employee_profile(emp_name, emp_designation, emp_address)
    VALUES
    ('Natalia', 'Human Resources Information Systems (HRIS) Professional', 'hr@abc.com');

The range for the emp_designation column is 50 characters; however, in the above query, we tried to insert a value that is greater than the specified range. Consequently, we will encounter the following error:

The output proved that you can’t insert a value that exceeds the specified range.

That was all the necessary information regarding the Postgres VARCHAR data type.

###  **Conclusion**

 **VARCHAR(n)** or **CHARACTER VARYING(n)** is a data type in PostgreSQL that stores textual data in a limited range. It can store n number of characters. A string that exceeds the specified range cannot be stored in the VARCHAR data type. This write-up explained what VARCHAR data type is and how to use it in PostgreSQL with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-varchar-data-type-with-examples/)

---

# How to Show Tables in PostgreSQL?

> Execute the “\dt” command from psql tool or use the pg_catalog schema with the aid of the SELECT query from the pgAdmin to show tables of the selected database…

In PostgreSQL, SQL SHELL (psql) and pg_catalog schema are used to show the tables. Execute the **“\dt”** command from the psql tool or use the **pg_catalog** schema with the aid of the [**SELECT**](<https://commandprompt.com/education/how-to-use-select-query-in-postgresql/>) query from the pgAdmin to show tables of the selected database.

Let’s learn how to show tables in PostgreSQL with the help of examples.

###  **How to Show Tables in PostgreSQL Using SQL SHELL(psql)?**

To show tables using psql, the **“\dt”** command is used. This section will present stepwise instructions to show the Postgres tables using psql:

###  **Step 1: Open psql**

Let’s open the psql tool and fill in the necessary details like user name, password, etc., to connect to the PostgreSQL:

### 

###  **Step 2: Access the Database Using \c Command**

Once you are logged in, specify the database name after the “\c” command to access the desired database:
    
    
    \c example;

The command mentioned above will connect us to the “example” database:

Congratulations! You are connected to the desired database.

###  **Step 3: Show the List of Tables Using “\dt” Command**

To see the available tables/relations within the example database, execute the “\dt” command as follows:
    
    
    \dt;

The output shows that there are total “18” tables in the “example” database.

###  **Step 4: Show the Tables Details Using “\dt+” Command**

To show the tables with more details like table’s size, access method, description, etc., execute the “\dt+” command as follows:
    
    
    \dt+;

This is how you can show the tables using the SQL SHELL(psql).

###  **How to Show Tables in PostgreSQL Using pgAdmin?**

In PostgreSQL, you can use the pg_catalog schema with the collaboration of the SELECT query to show the tables. By default, the pg_catalog will show all the relations, including systems tables; however, you can use the [WHERE](<https://commandprompt.com/education/how-to-use-where-clause-in-postgresql/>) clause to filter the tables of your choice.

###  **Step 1: Open the Query Tool**

Firstly, open the pgAdmin and then right-click on the selected database and select the “Query Tool” as follows:

Clicking on the query tool will open the query editor as shown in the below screenshot:

### 

###  **Step 2: Show Tables Using pg_catalog**

Let’s execute the query given below to show all the tables, including system relations:
    
    
    SELECT *
    FROM pg_catalog.pg_tables;

The output shows that the pg_catalog fetched all the relations, including system tables.

###  **Step 3: Show Only User-defined Tables Using pg_catalog**

Execute the query given below to show all the tables present in the example database:
    
    
    SELECT *
    FROM pg_catalog.pg_tables
    WHERE schemaname NOT IN ('pg_catalog','information_schema');

In the WHERE clause, we specified a condition to skip the system’s tables. The query mentioned above will show all the tables except the system tables:

The pg_catalog schema succeeded in showing all the tables present in the “example” database. This is how you can show the tables of a database using pg_catalog schema.

###  **Conclusion**

Execute the **“\dt”** command from the psql tool or use the **pg_catalog** schema with the aid of the **SELECT** query from the pgAdmin to show tables of the selected database. This write-up demonstrated the working of the “\dt” command, “\dt+” command, and pg_catalog schema with the help of different examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-show-tables-in-postgresql/)

---

# How to Use EXTRACT() Function in PostgreSQL

> The EXTRACT() function in PostgreSQL extracts a specific field, like a day, month, minutes, hours, etc., from an INTERVAL or TIMESTAMP.

The **EXTRACT()** function in PostgreSQL extracts a specific field, like a day, month, minutes, hours, etc., from a date or time value. It accepts a ‘source’ and a ‘field’ as arguments and returns an extracted field from the given source. The returned value will be a double precision value.

This write-up will discuss the working of the **EXTRACT()** function using practical examples. So, let’s begin.

###  **How to Use EXTRACT() Function in PostgreSQL?**

To comprehend the concept of the **EXTRACT()** function, firstly, we need to understand its syntax:
    
    
    EXTRACT(Field FROM Source);

In the extract function, the first argument is a field that specifies which field should be extracted from the given source(date/time value). FROM is a keyword, while the second argument is a source that will be one of the following types: INTERVAL or TIMESTAMP. If we pass a DATE type value to the **EXTRACT()** function, then the **EXTRACT()** function will cast/convert it into a TIMESTAMP value.

The valid field formats are listed below:

\- MILLENNIUM, CENTURY, DECADE, YEAR, DOY(Day of Year between 1 and 366), ISODOY(week number of the year based on ISO 8601), or QUARTER.

\- MONTH, WEEK, DOW(Day of Week 0 represents Sunday while 6 represents Saturday), ISODOW(ISO-based Day of Week 7 represents Sunday while 1 represents Monday), or DAY.

\- HOUR, MINUTE, SECONDS, EPOCH(Total seconds since 1970-01-01), MICROSECONDS, or MILLISECONDS.

\- TIMEZONE, TIMEZONE_HOUR, or TIMEZONE_MINUTE.

 **Note:** DOW, ISODOW, DOY, ISODOY, TIMEZONE, TIMEZONE_HOUR, and TIMEZONE_MINUTE are invalid field formats for the INTERVAL.

###  **Example #1: How to Extract a DAY From TIMESTAMP?**

Let’s execute the below-mentioned command to extract a day from the specified TIMESTAMP:
    
    
    SELECT EXTRACT('DAY' FROM TIMESTAMP '2022-08-29 02:28:15');

The **EXTRACT()** function retrieved the day successfully.

###  **Example #2: How to Extract a YEAR From TIMESTAMP?**

To extract a year from the given TIMESTAMP, we will execute the below-mentioned query:
    
    
    SELECT EXTRACT('YEAR' FROM TIMESTAMP '2022-08-29 02:28:15');

The **EXTRACT()** function extracted the year from the given timestamp.

###  **Example #3: How to Extract a QUARTER From TIMESTAMP?**

In this example, we will utilize the **EXTRACT()** function to extract the quarter from the given TIMESTAMP:
    
    
    SELECT EXTRACT('QUARTER' FROM TIMESTAMP '2022-08-29 02:28:15');

There are four quarters in a calendar year. August lies in the third quarter, so the EXTRACT() function returns 3.

###  **Example #4: How to Extract a DOY From TIMESTAMP?**

Let’s execute the **EXTRACT()** function to extract the day of the year from the given TIMESTAMP:
    
    
    SELECT EXTRACT('DOY' FROM TIMESTAMP '2022-08-29 02:28:15');

The output shows that it’s the 241st day of the year.

###  **Example #5: How to Extract a DAY From the Current Date?**

In Postgres, the CURRENT_DATE retrieves the latest/current date as shown in the following snippet:
    
    
    SELECT CURRENT_DATE;

Output shows that it's the 29th of august 2022. Let’s execute the following query to extract the day from the current date:
    
    
    SELECT EXTRACT('DAY' FROM CURRENT_DATE);

In the **EXTRACT()** function, we specified the ‘DAY’ as the first argument and the CURRENT_DATE function as the second argument. Consequently, we will get the following outcome:

The **EXTRACT()** function successfully extracted the specified field from the current date.

###  **Example #6: How to Extract a Year From a TIMESTAMP Using the Table’s Data?**

We have created a table named bike_details. Let’s execute the SELECT statement to fetch its details:
    
    
    SELECT * FROM bike_details;

Suppose the need of the moment is to fetch the launching year of each bike. To do this, we will utilize the **EXTRACT()** function as follows:
    
    
    SELECT EXTRACT('YEAR' FROM bike_launch_date)
    FROM bike_details;

From the bike_launch_date column, the **EXTRACT()** function successfully extracted the launching year for each bike.

This way, you can specify any valid field in the **EXTRACT()** function to extract any specific part/field from the given TIMESTAMP.

###  **Example #7: How to Extract a YEAR From an Interval?**

In the **EXTRACT()** function, we will specify a **YEAR** as the first argument and an interval as the second argument:
    
    
    SELECT EXTRACT('YEAR' FROM INTERVAL '10 years 6 months 15 days 5 hours 12 minutes 14 second');

On executing the query mentioned above, the following output will appear:

This is how you can extract a year from an INTERVAL.

###  **Example #8: How to Extract HOURS From an Interval?**

This example will demonstrate how to extract a day of the week from an interval:
    
    
    SELECT EXTRACT('HOUR' FROM INTERVAL '10 years 6 months 15 days 5 hours 12 minutes 14 second');

The output verifies the working of the **EXTRACT()** function.

###  **Example #9: How to Extract CENTURY From an Interval?**

Let’s extract a century from the given INTERVAL using the **EXTRACT()** function:
    
    
    SELECT EXTRACT('CENTURY' FROM INTERVAL '2022 years 8 months 29 days 3 hours 55 minutes 14 second');

The output indicates that it is the 20th century in the specified INTERVAL.

###  **Example #10: How to Extract MONTH From an Interval Using Table’s Data?**

Suppose we have to extract the month from the employee_example table. First, we will check the table details using the following statement:
    
    
    SELECT * FROM employee_example;

Now, let’s utilize the **EXTRACT()** function to extract the MONTH from the joining_date column:
    
    
    SELECT EXTRACT('MONTH' FROM joining_date)
    FROM employee_example;

This way, you can extract any field from the specified INTERVAL using the **EXTRACT()** method.

###  **Conclusion**

The **EXTRACT()** function in PostgreSQL extracts a specific field, like a day, month, minutes, hours, etc., from an INTERVAL or TIMESTAMP. There are multiple valid field formats that are used to extract a date or time from an INTERVAL or TIMESTAMP. This write-up demonstrated the working of the **EXTRACT()** function along with examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-extract-function-in-postgresql/)

---

# How to Split a String Using SPLIT_PART() Function in PostgreSQL

> PostgreSQL offers a built-in function named SPLIT_PART() that splits the given string based on the specified delimiter. It returns the ‘n’ number of substrings…

PostgreSQL offers a built-in function named **SPLIT_PART()** that splits the given string based on the specified delimiter. It returns the ‘n’ number of substrings. The **SPLIT_PART()** function splits the strings from left-to-right.

This post will demonstrate the working of the **SPLIT_PART()** function in PostgreSQL. Each concept will be explained with practical examples. So, let’s start.

###  **How to Split a String Using SPLIT_PART() Function in PostgreSQL?**

The **SPLIT_PART()** function accepts three parameters: a string, a delimiter, and position. The basic syntax of the **SPLIT_PART()** will look like this:
    
    
    SPLIT_PART(str, delimiter, position);

The below-listed points explain the argument’s details:

\- str represents a string to be split/broken.

\- The delimiter is a string that will be used to break the specified string into substrings.

\- While position specifies the parts/substrings to be returned, and it must be a positive number.

Let’s consider some examples to clarify the points mentioned above.

###  **Example #1: How to Use SPLIT_PART() Function in Postgres?**

In this example, we will pass three arguments to the **SPLIT_PART()** function: a string, a comma as a delimiter, and 3 as a position:
    
    
    SELECT SPLIT_PART('You can find fish, turtles, cats, and dogs in a pet store.', ',', 3);

The **SPLIT_PART()** function will split the given string into n number of substrings based on the specified delimiter, i.e., **“,”**. We specified 3 in place of the position parameter, so the **SPLIT_PART()** function will return the third substring:

The output shows that the **SPLIT_PART()** function splits the string into parts and returns a substring that is present at the third position.

###  **Example #2: How to Use the SPLIT_PART() Function on Table’s Data?**

In this example, we will learn how to use the SPLIT_PART() function on the table's data. Firstly, we will execute the SELECT statement to fetch the table’s data:
    
    
    SELECT * FROM article_details;

Suppose we have to fetch the day and month from the published_date column. To do so, we will use the SPLIT_PART() function as follows:
    
    
    SELECT SPLIT_PART(published_date :: TEXT, '-', 2) AS month,
    SPLIT_PART(published_date :: TEXT, '-', 3) AS day
    FROM article_details;

In the above query we performed the following tasks:

\- The SPLIT_PART() function accepts string type data so firstly we convert the date type values into the TEXT data type using the **::** operator.

\- Next, we specified “-” as a delimiter.

\- In the published_date column, the date is specified in YYYY-MM-DD format. So, we specified 2 and 3 in place of the position parameter to get the month and day, respectively.

This way, you can utilize the SPLIT_PART() function on the table’s data.

###  **Conclusion**

PostgreSQL offers a built-in function named **SPLIT_PART()** that splits the given string based on the specified delimiter. It returns the ‘n’ number of substrings. It accepts three parameters: a string to be split/broken, a delimiter based on which the given string will be split, and a position that specifies the substrings to be returned. This post narrated the working of the SPLIT_PART() function using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-split-a-string-using-split_part-function-in-postgresql/)

---

# How to Use CONCAT Function in PostgreSQL

> In PostgreSQL, the CONCAT() function accepts multiple strings as arguments and concatenates them to a single string. Strings can be char, text, or varchar.

In PostgreSQL, **CONCAT()** is a built-in function that concatenates multiple strings. It accepts multiple strings as arguments and concatenates them into one string. PostgreSQL offers another built-in function named **CONCAT_WS()** that concatenates multiple strings and adds a separator between them.

Let’s learn the working of **CONCAT()** and **CONCAT_WS()** functions using some examples.

###  **How to Use CONCAT() Function in PostgreSQL?**

Firstly, let’s understand the basic syntax of the **CONCAT()** function:
    
    
    CONCAT(string_1, string_2, ..., string_N);

The string can be of any type, i.e., char, text, or varchar. You can specify any number of strings in the **CONCAT()** function. Moreover, the CONCAT() function can accept an array as an argument. The array must be marked with the VARIADIC keyword in such a case.

###  **Example #1: How to Concatenate Multiple Strings Using CONCAT() Function?**

Execute the below query to concatenate several strings using the **CONCAT()** function:
    
    
    SELECT CONCAT('Welcome', ' to', ' commandprompt.com');

We specified three strings in the **CONCAT()** function. On successfully executing the above statement, we will get a single concatenated string:

This is how the CONCAT() function works in Postgres.

###  **Example #2: How to Concatenate Multiple Columns Data Using the CONCAT() Function?**

We have a table named “article_details” that contains the following records:
    
    
    SELECT * FROM article_details;

Suppose we have to combine the values of two columns: article_title and published_date. To do that, we will utilize the CONCAT() function as follows:
    
    
    SELECT CONCAT(article_title, ' ', published_date)
    FROM article_details;

The CONCAT() function will concatenate the values of both these columns. Values will be separated with white space:

As shown in the output, both columns have been successfully concatenated. However, the concatenated values are hard to understand. To get user-friendly output, we can specify a string in place of white space:
    
    
    SELECT CONCAT(article_title, ' published on ', published_date)
    FROM article_details;

Now, the concatenated strings are more understandable.

###  **Example #3: How to Use the CONCAT() Function With Built-in Functions?**

PostgreSQL offers a wide range of built-in functions that can be used with the CONCAT() function to achieve different functionalities. For example, if we want to concatenate only the publishing year instead of the complete date, then we can use the DATE_PART() function with the CONCAT() function:
    
    
    SELECT CONCAT(article_title, ' published in ', DATE_PART('YEAR', published_date))
    FROM article_details;

In this example, we utilized the DATE_PART() function that will extract the publishing year from the published_date column:

In this way, you can use any built-in function with the **CONCAT()** function to achieve different functionalities.

###  **How to Use CONCAT_WS() Function in PostgreSQL?**

 **CONCATE_WS()** is an extension of the **CONCAT()** function that allows us to add a separator between the concatenated strings. In the CONCAT_WS() function, the term “WS” represents “with a separator”. So, the COCAT_WS() function accepts multiple strings along with a separator and returns a concatenated string separated with a specific separator. Here is the syntax of the Postgres CONCAT_WS() function:
    
    
    CONCAT_WS(separator, string_1, string_2,..., string_n);

In place of a separator, you can use any separator/string. Let’s understand this concept using an example.

###  **Example: How to Use CONCAT_WS() Function on Table’s Data?**

In this example, we will separate the concatenated values with a comma:
    
    
    SELECT CONCAT_WS(', ', article_title, published_date)
    FROM article_details;

In this query, we specified **“,”** as a separator. So, the concatenated string will be separated by a comma:

This time, the values of both columns are separated with a comma. This is how the **CONCAT_WS()** function works in PostgreSQL.

That was all the necessary information regarding **CONCAT()** and **CONCAT_WS()** functions.

###  **Conclusion**

 **CONCAT()** and **CONCAT_WS()** are built-in functions in PostgreSQL that concatenate several strings. It accepts multiple strings as arguments and concatenates them into one string. COCAT_WS **()** accepts multiple strings along with a separator and returns a concatenated string separated with a specific separator. This post described the working of the CONCAT() and CONCAT_WS() functions using suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-concat-function-in-postgresql/)

---

# How to Use the UNION Clause/Operator in PostgreSQL

> In PostgreSQL, the UNION clause/operator combines the result sets of two or more queries. It doesn’t return the duplicated rows in the combined set.

In PostgreSQL, the **UNION** clause/operator is used to combine/merge the result set of at least two queries. The **UNION** clause/operator doesn’t return the duplicate rows in the combined set. The UNION ALL operator/clause is used to retain the duplicated rows.

This write-up will illustrate the working of the UNION operator/clause with the help of different examples. So let’s begin!

 **How to Use the UNION Clause/Operator in PostgreSQL?**

The UNION operator assists us in combining the data of similar tables. The below-listed rules must be followed to avail the functionality of the UNION operator:

\- The Column’s number and the column’s order must be the same for all the queries to be combined.

\- The data type must be the same/compatible.

\- The length of each result set can vary i.e. it’s not necessary to have the result set of the same length.

The syntax of the UNION operator will be as follows:
    
    
    SELECT col_list_1
    FROM tbl_expresssion_1
    UNION
    SELECT col_list_2
    FROM tbl_expresssion_2

In this example, the col_list_1 and col_list_2 represent the column’s list to be selected from the respective tables. The UNION operator will be used between the queries to be combined.

 **Example: How to Combine Result Sets of Two SELECT Queries Using UNION Operator?**

We already have two tables: article_details and recommended_articles. Let’s populate each table one by one:
    
    
    SELECT * FROM article_details;

The SELECT statement successfully fetched all the columns of the article_details column.

Let’s run the below query to describe the rocommeded_articles table:
    
    
    SELECT * FROM recommended_articles;

The output shows that the recommended_articles table has three records.

Let’s run the following query to combine two tables: article_details and recommended_article:
    
    
    SELECT * FROM article_details
    UNION
    SELECT * FROM recommended_articles;

The UNION operator succeeded in combining the result sets of article_details and recommended_article. From the output, you can clearly observe that the UNION operator didn’t retain the duplicated rows in the resultant table.

 **How to Use the UNION Operator With ORDER BY Clause?**

In the previous example, we witnessed that the table rows were out of order. You can specify the order of the table records by using the [ORDER BY](<https://commandprompt.com/education/how-to-use-order-by-clause-in-postgresql/>) clause. The below snippet shows the updated syntax of the UNION operator:
    
    
    SELECT col_list_1
    FROM tbl_expresssion_1
    UNION
    SELECT col_list_2
    FROM tbl_expresssion_2
    ORDER BY col_name ASC|DESC;

Using the ORDER BY clause, you can sort the result set in ascending/descending order.

 **Example: How Does the ORDER BY Clause Work With the UNION Operator in PostgreSQL?**

Let’s implement the below-given query to sort the combined result set in the ascending order:
    
    
    SELECT * FROM article_details
    UNION
    SELECT * FROM recommended_articles
    ORDER BY article_id ASC;

The output authenticates the working of ORDER BY clause and UNION operator. As we get the combined result set in ascending order(sorted according to article_id).

 **How Does the UNION ALL Clause/Operator Work in PostgreSQL?**

The UNION ALL operator combines at least two tables and retains the duplicated rows. Let’s execute the following query to combine the article_details table with the recomended_articles table and retain the duplicated rows of both these tables:
    
    
    SELECT * FROM article_details
    UNION ALL
    SELECT * FROM recommended_articles
    ORDER BY article_id ASC;

The output shows that the UNION ALL operator/clause keeps the duplicated rows as well.

 **Conclusion**

In PostgreSQL, the **UNION** clause/operator combines the result set of at least two queries. It doesn’t return the duplicated rows in the combined set. In Postgres, the **UNION ALL** operator is used to retain the duplicated rows. The ORDER BY clause can be used with the UNION and UNION ALL operators to sort the combined set in a particular order. This write-up went through different examples to explain the usage of UNION and UNION ALL operators in a better way.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-union-clauseoperator-in-postgresql/)

---

# PostgreSQL ROUND() Function With Examples

> PostgreSQL provides a built-in function named the ROUND() function that accepts either one or two arguments/values. It rounds a number to the nearest integer.

Rounding off a number up to specific decimal places is a very common task. PostgreSQL offers a ROUND() function that takes either one or two arguments/values. If the ROUND() function takes only one value, then it will skip the fractional part and round the given number to the nearest integral value.

On the other hand, if the ROUND() function takes two parameters/values, then the second parameter specifies the number of decimal places. For example, if the second parameter’s value is 2, then the given value will be rounded off to two decimal places.

This write-up will present detailed knowledge about the ROUND() function with the help of examples. So, let’s begin.

 **How to Use ROUND() Function in PostgreSQL?**

To avail the functionalities of the ROUND() function, you have to follow the below syntax:
    
    
    ROUND(Number [ , n]);

Here, in this syntax, the “Number” represents a numeric value to be rounded. While “n” is an optional parameter that determines the number of decimal points.

 **Example #1: How to Use the ROUND() Function in PostgreSQL?**

This example illustrates the working of the ROUND() function that accepts only one value/parameter:
    
    
    SELECT ROUND(72.125);

The output verifies that the ROUND() function successfully rounded the given number to the nearest integral value. The fractional value was less than 5, so the given number was rounded downward.

 **Example #2: How to Round a Number to an Integer Using ROUND() Function?**

Let’s take another example of the ROUND() function that accepts only one parameter to understand its working in a better way:
    
    
    SELECT ROUND(72.725);

This time, the fractional value was greater than 5 (i.e., .725). Therefore the ROUND() function rounded the given number upwards, i.e., 73.

 **Example #3: How to Round a Numeric Value up to Two Decimal Points?**

The task is to round the given number up to two decimal places, so we will pass two parameters to the ROUND() function:
    
    
    SELECT ROUND(72.1214, 2);

The output verifies that the given number has been rounded up to two decimal places. Let’s consider another example for a profound understanding of the ROUND() function.

 **Example #4: How to Round a Numeric Value up to Three Decimal Points?**

Let’s pass ‘3’ as a second parameter to the ROUND() function to get a number rounded up to three decimal places:
    
    
    SELECT ROUND(72.12765, 3);

\- In this example, the original number is “72.12765”, the task is to round the given number up to three places.

\- The fourth number after the decimal is 6, which is greater than 5.

\- So the ROUND() function will not only round the given number up to 3 places but also round the third place digit upward i.e., “.127” will be rounded to “.128”:

The output authenticates the working of the ROUND() function.

 **How to Round the Table’s Data Using the ROUND() Function?**

The ROUND() function is equally effective in rounding the table’s data. Suppose we have a table staff_details whose details are as follows:
    
    
    SELECT * FROM staff_details;

Let’s say we have to round all the values of a column “staff_salary”. To do that, execute the below query:
    
    
    SELECT staff_name,
    ROUND(staff_salary)
    FROM staff_details;

The above query will fetch the staff_name and staff_salary from the staff_details table. The ROUND() function is applied to the staff_salary column. Therefore the salary will be rounded to the nearest integral value:

The output shows that the ROUND() function succeeded in rounding the values of the staff_salary column.

 **Conclusion**

PostgreSQL provides a built-in function named the ROUND() function that accepts either one or two arguments/values. If the ROUND() function accepts only one argument/value, then it will skip the fractional part and round the given number to the nearest integral value. Else if the ROUND() function accepts two arguments/values, then the second parameter specifies the number of decimal places up to which the given value will be rounded. This write-up explained how the ROUND() function works in PostgreSQL using some examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-round-function-with-examples/)

---

# How to Convert a String to a Number in PostgreSQL

> Specify a string followed by “::” and then write the data type to convert the given string into the targeted type like integer, decimal, or double precision.

In PostgreSQL, the **“::”** operator and CAST operator are used for converting/casting one type to another. Using the TO_NUMBER(), CAST(), and **“::”** operator, we can convert a string into a numeric type such as an integer, double, or decimal.

The objective of this write-up is to learn how to convert a string into a number using different examples. So, let’s get started!

 **What is the Need for Converting a String into a Number in PostgreSQL?**

Suppose we have a numeric value residing in the string data type (i.e., numeric string), and the need of the moment is to serve number-specific processing. To do so, firstly, we will convert the given strings into numbers. For example, if ‘250’ and '190’ are stored as strings and we have to perform some arithmetic operations on them.

To do so, we will first convert these strings into numeric data types, and then we can perform any operation on these numbers.

 **How to Convert/Cast a String Into a Number Using CAST Operator?**

Follow the below syntax to convert a string into a decimal using the CAST operator:
    
    
    SELECT CAST ('expression' AS DECIMAL);

In the above syntax, the expression represents any numeric string. With the aid of AS clause, the CAST operator will convert the given string to a numeric type.

 **Example: How to Use CAST Operator in Postgres?**

Let’s run the below statement to convert the string to a number using the CAST operator:
    
    
    SELECT CAST ('5000.005' AS DECIMAL);

The output shows that the given string has been successfully converted into the numeric data type using the CAST operator.

 **How to Use “::” Operator in PostgreSQL?**

Use the below syntax for the ‘string to number’ conversion using the **“::”** operator:
    
    
    SELECT 'expression' :: DECIMAL;

The above syntax will convert the given string to the decimal/numeric type.

 **Example: Practical Implementation of the “::” Operator**

Consider we have to convert a string “5000.005” to a number type. To do so, use the “::” operator as follows:
    
    
    SELECT '5000.05' :: DECIMAL;

The output verifies that the given string “5000.05” has been successfully converted into a numeric type using the “::” operator.

 **How to Convert a String/Text to an Integer Using CAST Operator?**

Here is the syntax for converting a string into an integer using the CAST operator in PostgreSQL:
    
    
    SELECT CAST ('expression' AS INTEGER);

In this syntax, the expression represents any numeric string. With the collaboration of the AS clause, the CAST operator will convert the given string into the integer type.

The CAST operator will generate an error if we try to convert an invalid expression/string into an integer. For example, converting ‘100XYZ’ to integer type will cause an error (because XYZ can’t be converted into a number).

 **Example #1: How to Use CAST Operator to Convert a String into an Integer/Number?**

Execute the below statement to cast a string value “5000” into an int data type:
    
    
    SELECT CAST ('5000' AS INTEGER);

The output shows that the given string has been successfully converted into an integer data type.

 **Example #2: How to Use CAST Operator on Table’s Data?**

Suppose we have a table named emp_data. Let’s fetch the table’s data using the SELECT query:
    
    
    SELECT * FROM emp_data;

You can observe that the data type of emp_salary column is text. Let’s say we need to perform the addition on the “emp_salary” column. To do that, we will use the Postgres built-in function SUM():
    
    
    SELECT SUM(emp_salary)   
    AS total 
    FROM emp_data;

When we executed the above query, we encountered an error. Because we can’t perform the addition on the string data.

Suppose we have to perform addition on the emp_salary column. To do that, firstly, we will convert the emp_salary column to the integer data type using the CAST operator:
    
    
    SELECT SUM(CAST(emp_salary AS INTEGER)) 
    AS total 
    FROM emp_data;

Here, firstly, we utilized the CAST operator to convert the emp_salary column to the desired data type. Next, we utilized a built-in SUM() function to calculate the sum of all the data present in the emp_salary column:

This is how you can use the CAST operator on the table’s data to perform different operations.

 **How to Convert/Cast a String to an INT Using ‘::’ Operator in PostgreSQL?**

The **“::”** operator works the same as the cast operator. Let’s follow the below syntax for converting a string/text to int data type in Postgres:
    
    
    SELECT 'Expression':: INTEGER;

Here, the expression represents any numeric string. The **‘::’** operator will convert the given string into the integer type.

 **Example #1: How Does the ‘::’ Operator Work in Postgres?**

Let’s convert “5000” to an integer type using the **“::”** operator:
    
    
    SELECT '5000'::INTEGER;

The output proved that the given string had been successfully converted into the integer type.

 **Example #2: How to Use the :: Operator on Table’s Data?**

In this example, we will calculate the sum of the emp_salary column. But to do that, firstly, we will utilize the “::” operator to convert the emp_salary column into integer data type, and then we will perform addition on that column:
    
    
    SELECT SUM(emp_salary :: INTEGER) 
    AS total 
    FROM emp_data;

The above query performs the following functionalities:

\- The **::** operator will convert the column’s type from string to int.

\- The SUM() function will perform addition on the emp_salary column.

Following will be the resultant outcome:

Output proved that this time the SUM() function succeeded in finding the sum of the selected column.

 **How to Use CAST Operator for String to Double Conversion?**

In Postgres, if we specify the below-given syntax:
    
    
    SELECT CAST ('expression' AS DOUBLE);

We will encounter an error “double doesn’t exist”.

 **Example #1: How Does the CAST Operator Work in PostgreSQL?**

Let’s first use the “DOUBLE” as a data type to convert the ‘5000.005’ to the double type:
    
    
    SELECT CAST ('5000.005' AS DOUBLE);

The output verified that PostgreSQL generated an error when we tried to convert the given string into the double type.

Therefore, to convert a string into a double type, we must use the “DOUBLE PRECISION” as a data type as shown below:
    
    
    SELECT CAST ('expression' AS DOUBLE PRECISION);

 **Example #2: How to Use the CAST Operator to Perform Conversion From String to Double Precision?**

Let’s specify the “DOUBLE PRECISION” as a conversion type to convert the given string into double precision:
    
    
    SELECT CAST('5000.005' AS DOUBLE PRECISION);

The output clarifies that the string “5000.005” has been converted into the double precision type successfully.

 **How to Perform String to Double Conversion Using ‘::’ Operator in PostgreSQL?**

The **“::”** will throw a “double doesn’t exist” error if we specify “DOUBLE” as a conversion type. So, we will use the DOUBLE PRECISION as a conversion type to convert the given string into a double type value:
    
    
    SELECT 'expression' :: DOUBLE PRECISION;

 **Example: How to Use the ‘::’ Operator to Convert a String Into a Double Precision Value?**

Let’s execute the below statement to convert “5000.005” to a double precision value:
    
    
    SELECT '5000.05' :: DOUBLE PRECISION;

The output authenticates that the string “5000.005” has been successfully converted into the double precision type.

 **How to Use TO_NUMBER Function in Postgres?**

In Postgres, TO_NUMBER() is a built-in function that converts a string/text into a number. The syntax of the TO_NUMBER() is given below:
    
    
    TO_NUMBER(str, format);

Here, “str” represents a string that will be converted into a number based on the specified “format”. There are multiple valid formats for the TO_NUMBER() function that can be used according to the given situation. You can learn more about the valid formats of the TO_NUMBER() function in a dedicated article - **How to Use TO_NUMBER() Function in PostgreSQL**

 **Example: How Does the TO_NUMBER() Function Work in PostgreSQL?**

Let’s convert the “-1214.72” into a number using TO_NUMBER():
    
    
    SELECT TO_NUMBER('-1214.72', 'S9999D99');

In this example, “-1214.72” is a string to be converted while “S9999D99” is a format based on which the given string will be converted. Here is the detailed description of the specified format:

\- S represents a sign (i.e. plus or minus).

\- Four 9’s represent that there are four digits after the specified sign.

\- The D symbol after the four 9’s represents that there are four digits after the specified sign (i.e. minus).

\- The last two 9’s represent that there are two more digits after the fraction/period.

The output shows that the TO_NUMBER() function successfully converted the given string into a number.

 **Conclusion**

Using the TO_NUMBER(), CAST(), and “::” operator, we can convert a string into a numeric type such as an integer, double, or decimal. Specify a string followed by the “::” operator and then write the targeted type to convert the given string into the targeted data type, such as integer, decimal, or double precision. Or Use the CAST operator with the collaboration of the AS clause to convert a string to a number like an integer, decimal, or double. This post considered different examples for the string-to-number conversion in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-convert-a-string-to-a-number-in-postgresql/)

---

# How to Use TO_NUMBER() Function in PostgreSQL

> TO_NUMBER() is used to convert a character string to a number. The TO_NUMBER() function accepts two parameters, a “string” and a “format”.

In Postgres, **TO_NUMBER()** is a built-in function that converts a string/text into a number. The **TO_NUMBER()** function accepts two parameters, i.e., the first parameter is a “string” that needs to be converted. While the second parameter represents a “format” based on which the targeted string will be converted.

This write-up will explain the working of the **TO_NUMBER** function with the help of different examples. So, let’s start.

 **How to Use the TO_NUMBER() in PostgreSQL?**

The basic syntax of the **TO_NUMBER()** function will be as follows:
    
    
    TO_NUMBER(str, format);

Here, **TO_NUMBER()** is a built-in Postgres Function that requires the following parameters:

\- “str” represents a string/text to be converted.

\- The second parameter must be a valid format. The targeted string/text will be converted into a number according to the given format.

Here is the list of valid formats for the **TO_NUMBER()** function:

\- **“.”** (dot/period) represents a decimal.

\- D represents a decimal that utilizes a locale.

\- 0 represents a number with leading 0’s.

\- 9 represents one digit.

\- Comma **“,”** represents a group separator.

\- G represents a group separator that utilizes locale.

\- RN represents a roman value between the range ‘1-3999’.

\- FM(Fill mode) deletes the leading/trailing spaces.

\- S represents a sign.

\- SG represents the plus/minus sign.

\- PL represents a plus sign for numbers greater than 0(positive numbers).

\- MI represents a minus sign for the numbers less than 0(negative numbers).

\- PR represents a negative value within angle brackets.

\- L represents a currency symbol.

\- TH/th represents the ordinal number suffix.

Now, let’s understand the working of the **TO_NUMBER()** function by implementing it practically.

 **Example #1: How to Use the TO_NUMBER Function in Postgres?**

Suppose we have a string “572,7212.016-”. Let’s convert the given string into a numeric value using the following statement:
    
    
    SELECT TO_NUMBER('572,7212.016-', '999G9999D999S');

In the above example, “573,7212.016-” is a string that needs to be converted into a number. We utilized the “999G9999D999S” format to convert the user-specified string into a number. The stepwise description of the specified format is as follows:

\- Three 9’s at the start represent that there are three digits at the start of the string.

\- G at the fourth position represents that three will be a group separator **“,”** at the fourth position.

\- The four 9’s after the G symbol represent that there are four more digits after the group separator.

\- D after four 9’s represents that there will be a decimal point after four digits.

\- Three 9’s after the D represent that there will be three digits after the fractional part.

\- S at the end represents a sign. Since we have a negative number, we will get a minus sign.

The output clarified that the TO_NUMBER function successfully converted the given string into a number.

 **Example #2: How to Convert a String into an Integer/Numeric Value(Skip the Floating Points)?**

Suppose we have to convert a string(“572,7212.016-”) into a number, but we don’t need the decimal part of the given string:
    
    
    SELECT TO_NUMBER('-512,7512.014', 'S999G9999');

In this example, the TO_NUMBER() function will convert the given string (i.e., 572,7212.016-) into a number. Since we didn’t specify the D symbol and 9 in place of decimal/period and digits that come after the period. Therefore, the TO_NUMBER() function will return only the integral part and skip the fractional part.

The output authenticates the working of the TO_NUMBER() function as it succeeded in converting the given string into a number.

 **Example #3: How to Convert a String(Cash Amount) into a Number?**

Consider a string containing a special symbol (i.e., a currency symbol). Let’s utilize the TO_NUMBER() function to convert any string into a number:
    
    
    SELECT TO_NUMBER('$512,7512', 'L999G9999');

In the TO_NUMBER() function, the L symbol represents a currency symbol.

From the output, it is clear that the TO_NUMBER() function succeeded in converting the given string to a number.

 **Example #4: How to Convert a String(Containing Leading and Trailing Spaces) into a Number?**

In the TO_NUMBER() function, the FM symbol is used to trim the leading and trailing spaces from a string. Let’s convert a string type value ‘ -1214 ' into a number type value:
    
    
    SELECT TO_NUMBER(' -1214 ', 'FMS9999');

In the format parameter, we specified the FM at the start that will skip the leading and trailing spaces. Next, we utilized the S symbol to specify a symbol, and at the end, four 9’s represent that there will be four digits after the (minus) sign.

The output proves the working of the TO_NUMBER() function.

 **Conclusion**

 **TO_NUMBER()** is a built-in Postgres function that converts a string/text into a number. The **TO_NUMBER()** function accepts two parameters: the first one represents a “string” that needs to be converted. While the “format” parameter specifies the conversion criteria for the given string. There are multiple valid formats for the TO_NUMBER() function whose usage depends on the situation. This write-up explained how the **TO_NUMBER()** function works in PostgreSQL with the help of several examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-to_number-function-in-postgresql/)

---

# PostgreSQL BOOLEAN Data Type With Examples

> In PostgreSQL, the BOOLEAN or BOOL data type takes only 1 byte to store a value in a database, and it returns one of two probable values: True or False.

PostgreSQL offers a **BOOLEAN** data type with three states: TRUE, FALSE, or NULL. It requires only 1 byte to store a value in a database, and it returns one of two probable values: True or False. In Postgres, the **BOOLEAN** data type is abbreviated as **BOOL**.

The **BOOLEAN** data type is used when you have to get some sort of approval, like YES or NO. Some popular use cases of **BOOLEAN** data type include “checking the availability of something”, “age restriction approval”, and so on.

This write-up will teach you how to use the **BOOLEAN** data type using some examples. So, let’s begin.

 **How Does the BOOLEAN Data Type Work in PostgreSQL?**

In PostgreSQL, there are some valid literal values for BOOLEAN true and false. These values must be enclosed in single quotations. However, the constant values True and False work fine with or without single quotes.

\- The valid literal values for the BOOLEAN true include **true, ‘t’, ‘true’, ‘y’, ‘yes’, and ‘1’**.

\- The valid literal values for the BOOLEAN false include **false, ‘f’, ‘false’, ‘n’, ‘no’, and ‘0’**.

Let’s consider different examples to understand the working of **BOOLEAN** data type in a better way.

 **Example #1: How to Create a Column With BOOLEAN Data Type?**

Let’s [create a table](<https://www.commandprompt.com/education/different-methods-to-create-a-table-in-postgresql/>) named book_details that includes three columns: book_id, book_name, and is_available. We will set the data type of book_id as INT, book_name as TEXT, and is_available as BOOLEAN:
    
    
    CREATE TABLE book_details ( 
    book_id INT PRIMARY KEY, 
    book_name TEXT, 
    is_available BOOLEAN NOT NULL 
    );

The table named book_details has been created successfully. Let’s verify the existence of the book_details table using the below command:
    
    
    SELECT * FROM book_details;

From the output, you can observe that the table columns with their respective data types have been created successfully.

 **Example #2: How to Insert BOOLEAN Values Using Different Literal Values to a Table?**

Let’s insert the data into the newly created table named book_details. We will utilize various literal values to insert the boolean values into a table:
    
    
    INSERT INTO book_details (book_id, book_name, is_available) 
    VALUES 
    (1, 'The Great Gatsby', TRUE), 
    (2, 'The Picture of Dorian Gray', FALSE),
    (3, 'Great Expectations', 't'), 
    (4, 'Wuthering Heights', 'f'), 
    (5, 'The Kite Runner', '1'), 
    (6, 'The Catcher in the Rye', '0'),
    (7, 'The Lord of the Rings', 'y'), 
    (8, 'His Dark Materials', 'n'), 
    (9, 'To Kill a Mockingbird', 'yes'), 
    (10, 'The Grapes of Wrath', 'no'),
    (11, 'Frankenstein', 'TRUE'), 
    (12, 'Think and Grow Rich', 'FALSE');

Twelve rows have been inserted into the book_details table successfully. Let’s execute the SELECT query to verify data insertion:
    
    
    SELECT * FROM book_details;

All the records have been inserted into the book_details table successfully.

 **Example #3: How to Fetch All the Records That are True?**

Let’s fetch only those books that are available in stock. We can use one of the following valid literal values true, ‘t’, ‘true’, ‘y’, ‘yes’, or ‘1’:
    
    
    SELECT * FROM book_details
    WHERE is_available = true;

The SELECT query succeeded in fetching all those books that are available in stock. We utilized the constant value “true” to fetch the available books. However, you can use any other valid literal like ‘t’, ‘1’, ‘y’, etc, to fetch the books that are in stock.

 **Example #4: How to Fetch All the Records That are False?**

We can use one of the following valid literal values: false, ‘f’, ‘false’, ‘n’, ‘no’, or ‘0’. This example will fetch only those books that are unavailable’:
    
    
    SELECT * FROM book_details
    WHERE is_available = '0';

The SELECT query fetched all those books that are not in stock.

 **Example #5: How to Set The Default Value of a Boolean Column?**

Use the **SET DEFAULT** clause with the aid of ALTER TABLE and ALTER COLUMN commands to set the default value of an existing boolean column. In this example, we will set the default value of the is_available column as FALSE:
    
    
    ALTER TABLE book_details
    ALTER COLUMN is_available
    SET DEFAULT FALSE;

The output verified that the default value of the is_available column had been set as False successfully. Let’s insert 13 into the book_id column and ‘Lord of the Flies’ into the book_name column:
    
    
    INSERT INTO book_details (book_id, book_name)
    VALUES (13, 'Lord of the Flies');

We didn’t insert anything in the is_available column against the book_id 13:

One row has been added to the book_details table. Let’s execute the SELECT query to show the details of the selected table:
    
    
    SELECT * FROM book_details;

At the time of data insertion against book_id 13, we didn’t specify the value for the is_available column. However, we can see in the output that Postgres inserted false in the is_available column for book_id = 13.

 **Conclusion**

In PostgreSQL, the BOOLEAN or BOOL data type takes only 1 byte to store a value in a database, and it returns one of two probable values: True or False. In PostgreSQL, there are some valid literal values for BOOLEAN true and false. For example, true, ‘t’, ‘true’, ‘y’, ‘yes’, and ‘1’ are valid literal values for the BOOLEAN true. While the valid literal values for the BOOLEAN false include false, ‘f’, ‘false’, ‘n’, ‘no’, and ‘0’. This post provided detailed knowledge about the BOOLEAN data type with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-boolean-data-type-with-examples/)

---

# PostgreSQL BIGINT Data Type With Examples

> BIGINT is a numeric data type in PostgreSQL that stores the integer values. It stores a value between -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807.

**BIGINT** is a numeric data type in PostgreSQL that stores the integer type values. One of the following data types is used to store a whole number in PostgreSQL: SMALLINT, INTEGER, or **BIGINT**. All these data types differ in storage size and range. If we talk about the **BIGINT** data type, it is used to store large values.

This write-up will present an in-depth sight of the Postgres **BIGINT** data type. So, let’s start!

 **What is the Need For BIGINT Data Type in PostgreSQL?**

In Postgres, the most common data type to store a numeric value is INT or INTEGER. So, a question that thrills our minds is what is the need for **BIGINT** when we already have an INT data type to store the numeric values? Well! The below-listed points can fix your queries:

\- The SMALLINT requires 2, INT requires 4, and BIGINT requires 8 Bytes of storage size.

\- The SMALLINT data type stores a number within the range -32,768 to +32,767.

\- The INT/INTEGER stores values between -2,147,483,648 to +2,147,483,647.

\- The BIGINT data type stores the values between -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807.

Considering the figures given above, we can conclude that the BIGINT data type is used to store the larger numeric values. For instance, you have to store a numeric value that is out of the range of the INTEGER data type. In such cases, you can use the BIGINT data type.

 **Note:** Use the **BIGINT** data type only when you have a valid cause(when you require more storage) to use it. This is because the **BIGINT** data type consumes more storage and slows down the database performance.

Up till now, this write-up explained why and when to use the **BIGINT** data type in PostgreSQL. Now without wasting any time, we will jump into the practical implementation of the BIGINT data type.

 **Example #1: How to Create a Column With BIGINT Data Type?**

Let’s create a table named **“bigint_example”** with three columns: id, name, and amount. Let’s set the data type of the id column as INT, TEXT for the name column, and BIGINT for the amount column:
    
    
    CREATE TABLE bank_details( 
    id INT PRIMARY KEY,
    name TEXT NOT NULL,
    amount BIGINT NOT NULL 
    );

The table named bank_details has been created. Let’s verify the table creation using the SELECT command:
    
    
    SELECT * FROM bank_details;

Three columns with the desired data types have been created successfully.

 **Example #2: How to Insert BIGINT Data to a Table in Postgres?**

Let’s insert some data into the newly created table named bank_details:
    
    
    INSERT INTO bank_details(id, name, amount)
    VALUES
    (1, 'JPMorgan Chase & Co.', 3000000000000),
    (2, 'Bank of America Corp.', 2520000000000), 
    (3, 'Wells Fargo & Co.', 1780000000000), 
    (4, 'Citigroup Inc.', 1670000000000),
    (5, 'U.S. Bancorp', 564000000000);

The output shows that five records have been inserted into the bank_details table. Let’s verify/check the table’s data using SELECT statement:
    
    
    SELECT * FROM bank_details;

The output verifies that all the data has been inserted into the bank_details table.

 **Conclusion**

 **BIGINT** is a numeric data type in PostgreSQL that stores the integer type values. It stores a value between -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807. However, it is recommended that the **BIGINT** data type should be used only when you have a valid cause(when you require more storage) to use it. This is because the **BIGINT** data type consumes more storage and slows down the database performance. This write explained how to use the BIGINT data type in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/postgresql-bigint-data-type-with-examples/)

---

# What Does DROP TABLE CASCADE do in PostgreSQL

> In PostgreSQL, the CASCADE option is used with the DROP TABLE command to drop/delete a table along with its dependent objects.

In PostgreSQL, the CASCADE option is used with the DROP TABLE command to drop the tables that have dependent objects. In PostgreSQL, the DROP TABLE drops single or multiple tables. However, the DROP TABLE command can’t drop a table that contains dependent objects.

So, how to drop/delete a table that has dependent objects? Well! Thanks to the CASCADE option that allows us to drop a table along with its dependent objects.

This article will explain the Postgres DROP TABLE CASCADE statement with the help of examples. So, let’s get started!

 **What is the Need For the CASCADE Option in PostgreSQL?**

In PostgreSQL, a database can have multiple tables, and each table can have a relation with other tables. So, any table that has some dependent objects can’t be deleted/dropped using the DROP TABLE statement. The below example will assist you in understanding the need for the CASCADE option.

 **Example: How to Drop a Table That has Dependent Objects Using DROP TABLE Statement?**

We have already created “company_details” and “employee_info” tables in our database. Let’s execute the \d command to get all the details of the selected tables:
    
    
    \d company_details;

From the above snippet, you can observe that the company_id column is referred as a foreign key in the employee_info table.

Let’s describe the “employee_info” table using the “\d” command:
    
    
    \d employee_info;

The above snippet shows that the employee_info table depends on the company_details table.

Now, let’s try to drop the company_details table using the DROP TABLE:
    
    
    DROP TABLE comapny_details;

When we executed the DROP TABLE command, we encountered an error that says can’t drop a table that has dependent objects.

 **How to Drop a Table That has Dependent Objects in PostgreSQL?**

Use the **CASCADE** option with the DROP TABLE command to remove a table along with its dependent objects. The syntax of the **DROP TABLE** command with the **CASCADE** option will be as follows:
    
    
    DROP TABLE tab_name CASCADE;

Here, tab_name represents a table that needs to be dropped.

 **Example: How Does the DROP TABLE CASCADE Work in PostgreSQL?**

Let’s execute the DROP TABLE command with the aid of the CASCADE option to drop a table that has dependent objects:
    
    
    DROP TABLE company_details CASCADE;

The output clarifies that the CASCADE option succeeded in dropping the table with its dependent objects. The notice depicts that the dependent objects have also been removed from the table that is being dropped.

Let’s verify the table deletion using the below-given command:
    
    
    \d company_details;

The output shows that the company_details table has been successfully dropped from the database.

Let’s execute the below command to describe the employee_info table:
    
    
    \d employee_info;

The output shows that the company_id is no more a foreign key.

 **Conclusion**

In PostgreSQL, the CASCADE option is used with the DROP TABLE statement to drop/delete a table and its dependent objects. To do so, specify the DROP TABLE command followed by the table name and then write the CASCADE to drop a table along with its dependent objects. This write-up discussed the working of the DROP TABLE command with the CASCADE option using multiple examples.

---
[View this page online](https://www.commandprompt.com/education/what-does-drop-table-cascade-do-in-postgresql/)

---

# How to Alter Column Type in PostgreSQL

> To alter column’s type in PostgreSQL, use the “SET DATA TYPE” or “TYPE” keyword with the ALTER TABLE and ALTER COLUMN commands.

The “SET DATA TYPE'' or “TYPE” keyword is used with the collaboration of ALTER TABLE and ALTER COLUMN commands to alter/change the column type in PostgreSQL. Multiple ALTER COLUMN commands will be used along with the ALTER TABLE command to alter the type of multiple columns in a single statement.

This write-up will present a comprehensive guide on how to alter the column type in PostgreSQL. So, let’s begin.

 **How to Alter Column Type in PostgreSQL?**

Here is a simple syntax for altering a single column type in PostgreSQL:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_name [SET DATA] TYPE modified_data_type;

\- Specify the table name to be altered after the ALTER TABLE command.

\- Specify the column name to be altered after the ALTER COLUMN command. Next, specify either the “SET DATA TYPE” or “TYPE” keyword followed by the modified data type.

 **Example: How to Alter the Column Type From TEXT to VARCHAR in PostgreSQL?**

We have created a bike_details table in our database. Let’s run the SELECT query to fetch its details:
    
    
    SELECT * FROM bike_details;

Suppose we have to alter the type of bike_number column from text to varchar. To do so, we will execute the below-given statement:
    
    
    ALTER TABLE bike_details
    ALTER COLUMN bike_number TYPE VARCHAR;

The output shows that the bike_details table has been altered successfully.

Let’s run the SELECT command to see the updated table:
    
    
    SELECT * from bike_details;

The output shows that the column type has been altered successfully.

 **How to Alter Multiple Column Type in PostgreSQL?**

You have to use several ALTER COLUMN commands to alter the data type of multiple columns. Following will be the syntax for multiple ALTER COLUMN commands:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_name_1 [SET DATA] TYPE modified_data_type,
    ALTER COLUMN col_name_2 [SET DATA] TYPE modified_data_type,
    ...
    ALTER COLUMN col_name_N [SET DATA] TYPE modified_data_type;

 **Example #1: How to Alter the Data Type of Multiple Columns?**

Suppose we have to alter the data type of the bike_model column from text to varchar and bike_number column from varchar to text. We will run the below-given query to alter the data type of both columns in a single statement:
    
    
    ALTER TABLE bike_details
    ALTER COLUMN bike_model SET DATA TYPE VARCHAR,
    ALTER COLUMN bike_number SET DATA TYPE TEXT;

The output shows that the query returned successfully, and the bike_details table has been updated successfully.

Let’s run the SELECT statement to see the altered type of the selected columns:
    
    
    SELECT * FROM article_details;

The output verified that the data type of the targeted columns had been altered successfully.

 **Example #2: How to Alter Column Type From VARCHAR to INT in PostgreSQL?**

Let’s execute the ALTER TABLE command to modify the type of bike_model column from VARCHAR to INT:
    
    
    ALTER TABLE bike_details
    ALTER COLUMN bike_model SET DATA TYPE INT;

The output shows that Postgres threw an error when we tried to cast the VARCHAR to INTEGER. This is because Postgres doesn’t allow the implicit type casting from VARCHAR/TEXT to INTEGER data type. In PostgreSQL, the USING clause is used to cast the VARCHAR/TEXT data type to INTEGER data type.

Let’s execute the below command to alter the type of bike_model column from VARCHAR to INTEGER:
    
    
    ALTER TABLE bike_details
    ALTER COLUMN bike_model SET DATA TYPE INT
    USING bike_model::INTEGER;

The output shows that the bike_details table has been altered. Let’s run the SELECT query to see the updated table:

The output proves that the data type of bike_model has been altered from VARCHAR to INTEGER.

 **Conclusion**

To alter the column’s type in PostgreSQL, use the “SET DATA TYPE” or “TYPE” keyword with the ALTER TABLE and ALTER COLUMN commands. Multiple ALTER COLUMN commands will be used along with the ALTER TABLE command to alter the type of multiple columns in a single statement. This write-up went through some examples to explain how to alter column type in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-alter-column-type-in-postgresql/)

---

# How to Use DATE_PART() Function in PostgreSQL

> DATE_PART() function in PostgreSQL is used to extract/retrieve a specific part(like a month, year, hour, minutes, etc.) from a TIMESTAMP/Source.

**DATE_PART()** is a built-in function in PostgreSQL that is used to extract/retrieve a specific part(like a month, year, hour, minutes, etc.) from a date or time. It takes two parameters, a “field” and a “source”. The field determines which date/time part will be extracted/pulled out from the given source.

In this write-up, we are going to learn the functionality of the **DATE_PART()** function with the help of some examples. So, let’s start!

 **How to Use DATE_PART() Function in PostgreSQL?**

The DATE_PART() function allows us to extract the desired subfield(such as year, month, seconds, minutes, etc.) from the given date or time value. The syntax of the DATE_PART() will be as follows:
    
    
    DATE_PART(field, source);

Here, the source represents a Time, or Interval while the field represents a date/time part to be extracted from the source. The field’s value must be one of the following:

Day, Month, Year, Decade, Quarter, Century, Hour, Minute, Second, Microsecond, Millisecond, DOW(Day of Week), DOY(Day of Year), Epoch, ISOYear, ISODow, timezone_minute, timezone_hour, or time zone.

 **Example #1: How to Use DATE_PART() to Extract a Day From a TIMESTAMP?**

In this example, we have a timestamp “2022-08-16”, and the task is to extract the day from the given timestamp:
    
    
    SELECT DATE_PART('DAY', TIMESTAMP '2022-08-16');

The output shows that the DATE_PART() function successfully extracts the day part from the given TIMESTAMP. The month and year can also be extracted from the given TIMESTAMP by specifying the "MONTH" and "YEAR" as field values, respectively.

 **Example #2: How to Extract a Century From a TIMESTAMP?**

Let’s pass the “CENTURY” as the first argument to the DATE_PART() function to extract the century from the given TIMESTAMP:
    
    
    SELECT DATE_PART('CENTURY', TIMESTAMP '2022-08-16');

The output proves that the DATE_PART() function successfully extracted the century from the given TIMESTAMP.

 **Example #3: How to Extract a Quarter From a TIMESTAMP?**

Passing the “QUARTER” as a field value will extract the current quarter from the given TIMESTAMP:
    
    
    SELECT DATE_PART('QUARTER', TIMESTAMP '2022-08-16');

There are four quarters in a year and one quarter is equal to three months. In the given TIMESTAMP, the current month is 8, which lies in the third quarter. So, the DATE_PART() function will return the following output:

The output verifies the working of the DATE_PART() function.

 **Example #4: How to Extract a Week From a TIMESTAMP?**

Let’s pass the “WEEK” as a first argument to the DATE_PART() function to get the current week from the given TIMESTAMP:
    
    
    SELECT DATE_PART('WEEK', TIMESTAMP '2022-08-16');

The output authenticates the working of the DATE_PART() function.

 **Example #5: How to Extract a ‘DAY OF WEEK’ From a TIMESTAMP?**

Pass DOW as a first argument to the DATE_PART() function to extract the day of the week from the given TIMESTAMP:
    
    
    SELECT DATE_PART('DOW', TIMESTAMP '2022-08-16');

The output authenticates that the DATE_PART() function produces an accurate result (it's the second day of the week i.e., Tuesday).

 **Example #6: How to Extract a Minutes From a TIMESTAMP?**

To extract the minutes from the given TIMESTAMP, pass the “MINUTES” as the first argument to the DATE_PART() function:
    
    
    SELECT DATE_PART('MINUTE', TIMESTAMP '2022-08-16 11:11:21');

The output shows that the DATE_PART() function provides accurate results.

 **Example #7: How to Use DATE_PART() Function on Table’s Data?**

We created a table named bike_details in our database. Here are the details about the bike_details table:
    
    
    SELECT * FROM bike_details;

Suppose we have to fetch only month from the launch date. We will execute the below query to get the MONTH from the 'bike_launch_date' column:
    
    
    SELECT DATE_PART('MONTH', bike_launch_date) FROM bike_details;

The output proved that the DATE_PART() function succeeded in fetching the month part from the selected column. In this way, you can use the DATE_PART() function to fetch any part of the date/time from a table.

 **Conclusion**

In PostgreSQL, **DATE_PART()** is a built-in function that extracts/retrieves a specific part(like a month, decade, hour, minutes, etc.) from a given TIMESTAMP. Pass a field(like a month, decade, hour, minutes, etc.) as a first argument and a TIMESTAMP as a second argument to the DATE_PART() function. The field determines which date/time part will be extracted from the specified source/timestamp. This write-up described the usage of the DATE_PART() function with the help of different examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-date_part-function-in-postgresql/)

---

# How to Format a Date in PostgreSQL

> In PostgreSQL, the NOW() and CURRENT_DATE functions are used with the collaboration of the TO_CHAR() function to get the current date in a specific format.

To get a date into a specific format, the **TO_CHAR()** function is used. Generally, the **TO_CHAR()** function is used to convert a timestamp, an interval, a numeric value, a double-precision, or an integer to a string.

In PostgreSQL, the CURRENT_DATE and NOW() functions are used to obtain the current date in YYYY-MM-DD format. To retrieve the current date in a particular format, use the Postgres TO_CHAR() function.

This write-up will thoroughly explain how to get a date into a specific format in Postgres. So, let’s get started!

 **How to Get a Date Into a Specific Format?**

Follow the below syntax to format a date using the TO_CHAR() function:
    
    
    TO_CHAR('date_value'::DATE, 'date_format');

Here, the date_vale represents a date to be converted while the date_format represents a format based on which the date_value will be formatted.

 **Example: How to Format a Date in “dd Month, yyyy” Format?**

To format the given date into the specified format, run the following command:
    
    
    SELECT TO_CHAR('2022-09-01'::DATE, 'dd Month, yyyy');

This way, you can get a date into a specific format.

 **How Does NOW() Function Work in PostgreSQL?**

The NOW() function retrieves the latest time, date, and time zone. To get only the date part, we have to cast the date-time value to a date. To do that, follow the below syntax:
    
    
    NOW()::DATE;

 **Example: How to Get the Current Date Using NOW() Function?**

Let’s run the below statement to retrieve today’s date:
    
    
    SELECT NOW()::DATE;

This is how the NOW() function works in Postgres.

 **What is the CURRENT_DATE Function and How to Use it in Postgres?**

In PostgreSQL, the CURRENT_DATE function can be used to retrieve the latest date.
    
    
    CURRENT_DATE;

 **Example: How Does the CURRENT_DATE Function Work in Postgres?**

Run the below command to retrieve the current date:
    
    
    SELECT CURRENT_DATE;

The output shows that the CURRENT_DATE function successfully fetched the current date.

 **How to Get a Current Date into a Particular Format Using TO_CHAR() Function?**

The above examples proved that both NOW() and CURRENT_DATE functions return the date in “YYYY-MM-DD” format. To convert/retrieve the date into a particular format, use the Postgres TO_CHAR() function. The below snippet illustrates the basic syntax of the **TO_CHAR()** function:
    
    
    TO_CHAR(expression, format);

\- In the above snippet, the expression parameter represents a value to be formatted.

\- The “format” argument represents a format according to which the given expression will be formatted.

 **Example #1: How to Get a Date in the “DD/MM/YYYY” Format?**

Let’s display the current date in “DD/MM/YYYY” format using the TO_CHAR() function:
    
    
    SELECT TO_CHAR(CURRENT_DATE, 'DD/MM/YYYY');

The output shows that the TO_CHAR() function converted the current date into “DD/MM/YYYY” format.

 **Example #2: How to Get a Date in the User’s Specified Format?**

Specify “MONTH DD, YYYY” as a second parameter to the TO_CHAR() function to get the date in the specified format:
    
    
    SELECT TO_CHAR(CURRENT_DATE, 'MONTH DD, YYYY');

This time, the TO_CHAR() function will return the complete name of the month in capital letters. Next comes the current day of the month and, finally, the year in YYYY format:

The output authenticates the working of the TO_CHAR() function.

 **Example #3: How to Get a Date in the “mon dd, yy” Format?**

Specifying the “mon dd, yy” format as the second parameter in the TO_CHAR() function will return the abbreviated name of the month in small letters. Then the day and year in “dd” and “yy” format, respectively:
    
    
    SELECT TO_CHAR(CURRENT_DATE, 'mon dd, yy');

This is how the TO_CHAR() function works in PostgreSQL.

 **Example #4: How to Get the Current Date in the Day Month Year Format?**

We utilized the CURRENT_DATE function in the above examples to retrieve the prevailing date. However, we can use the NOW() function instead of the CURRENT_DATE function to get the current date as shown in the below snippet:
    
    
    SELECT TO_CHAR(NOW()::DATE, 'dd Month, yyyy');

This is how you can use the NOW() and CURRENT_DATE functions with the collaboration of the TO_CHAR() function to get the current date in a specific format.

 **Example #5: How to Format Table’s Data Into a User-Specified Format?**

We have a table named bike_details whose records are shown in the below snippet:
    
    
    SELECT * FROM bike_details;

Let’s apply the TO_CHAR() function on the bike_launch_date column to get the specified dates into **“dd Month, yyyy”** format:
    
    
    SELECT TO_CHAR(bike_launch_date::DATE, 'dd Month, yyyy')
    FROM bike_details;

This is how you can format a date in Postgres using the TO_CHAR() function.

 **Conclusion**

To get a date into a specific format, the **TO_CHAR()** function is used. In PostgreSQL, the NOW() and CURRENT_DATE functions are used with the collaboration of the TO_CHAR() function to get the current date in a specific format. The NOW() and CURRENT_DATE functions return the date in YYYY-MM-DD format. However, to get the date in a specific format, the TO_CHAR() function is used. In this write-up, we go through multiple examples to explain the concept of the NOW(), CURRENT_DATE, and TO_CHAR() functions in a better way.

---
[View this page online](https://www.commandprompt.com/education/how-to-format-a-date-in-postgresql/)

---

# PostgreSQL DATE Data Type With Examples

> PostgreSQL supports the DATE data type that stores the date values in YYYY-MM-DD format. PostgreSQL utilizes 4 bytes to store a date value in the storage.

PostgreSQL provides a **DATE** data type that allows us to store the date values in YYYY-MM-DD format. The **DATE** data type takes 4 bytes to store a date value in the storage. The **DATE** data type stores a date between 4713 BC to 5874897 AD.

This write will help you to understand how to use the **DATE** data type to insert or store a date value in PostgreSQL. So, let’s begin!

 **How to Use the DATE Data Type in PostgreSQL?**

Let’s understand the usage of the **DATE** data type with suitable examples.

 **Example #1: How to Create a Column With DATE Data Type?**

Let’s create a table named book_info and add three columns: book_id, book_name, and published_date. The data types of these columns will be INT, VARCHAR, and DATE, respectively. To do that, execute the below query:
    
    
    CREATE TABLE   book_info( 
      book_id INT   PRIMARY KEY, 
      book_name VARCHAR NOT NULL, 
      published_date DATE
      );

\- Firstly, we utilized the “ **CREATE TABLE** ” command followed by the table name to create a table.

\- Next, we specified the column names along with their data types.

\- We specified “ **book_id INT PRIMARY KEY** ” to create a column named book_id having integer data type, which would be a PRIMARY KEY.

\- Next, we specified **“book_name VARCHAR NOT NULL”** to create a column named book_name having data type **VARCHAR,** which wouldn’t accept a null value.

\- Finally, we created a column **published_date** that will accept the date type values.

On successfully executing the above-given query, you will get the following output:

The “book_info” table has been created successfully. Now, let’s populate the table’s structure using the SELECT command:
    
    
    SELECT * FROM book_info;

The **book_info** table has been created successfully. Let’s consider another example to learn how to insert the date type values into a table.

 **Example #2: How to Insert a Date Into a Table in Postgres?**

In this example, we will insert the data into the book_info table. To do that, let’s execute the INSERT INTO statement:
    
    
    INSERT INTO book_info (book_id, book_name, published_date)
    VALUES (1, 'The Little Prince', '1954-07-29'),
     (2, 'The Lord of the Rings', '1943-06-04'),
     (3, 'The Kite Runner', '2009-05-29'),
     (4, 'The Great Gatsby', '1925-04-10'),
     (5, 'East of Eden', '1952-09-19');

In the book_info table, we have three columns: book_id, book_name, published_date that will accept integer, string, and date type values, respectively.

The output shows that five records have been inserted into the **book_info** table. Let’s verify the record insertion using the SELECT statement:
    
    
    SELECT * FROM book_info;

The output verified that all the records, including the date values, have been successfully added to the book_info table.

 **How to DEFAULT Keyword With DATE Data Type in PostgreSQL?**

Postgres provides a **DEFAULT** keyword that assists us in setting a default date value. Use the following syntax while table creation to specify the current date as a default value:
    
    
    col_name DATE NOT NULL DEFAULT CURRENT_DATE;

\- col_name represents a column to be created.

\- DATE is a data type.

\- NOT NULL is a keyword that enforces a column not to accept the null values.

\- DEFAULT is a keyword used with the DATE data type to set a default date value.

\- CURRENT_DATE is a Postgres function that returns the current date.

Let’s understand it practically!

 **Example #1: How to Create a Column With Current Date as a Default Value in Postgres?**

Let’s execute the query below to set the current date as default for the published_date column:
    
    
    CREATE TABLE submit_article( 
       article_id INT PRIMARY KEY, 
       article_name VARCHAR NOT NULL, 
       submission_date DATE NOT NULL DEFAULT CURRENT_DATE
       );

The above snippet served the following functionalities:

\- Created a table named submit_article.

\- Created three columns: article_id, article_name, and submission_date having data types INT, VARCHAR, and DATE, respectively.

\- The DEFAULT keyword is used while creating the submission_date column to set the current date as a default value.

The output verified that the submit_article had been created successfully. Let’s run the SELECT statement to see the table’s structure:
    
    
    SELECT * FROM submit_article;

There are three columns in the submit_article table: aritcle_id, article_name, and submission_date.

 **Example #2: How to Insert a Date Into a Table in Postgres?**

Let’s insert some rows into the submit_article table using the INSERT INTO command:
    
    
    INSERT INTO submit_article (article_id, article_name)
     VALUES (1, 'Postgres FETCH Clause'),
       (2, 'Postgres WHERE Clause'),
       (3,'Postgres BETWEEN Operator');

In this example, we inserted article ids and article names using the insert command. Here is what we will get on successful execution:

We didn’t insert any value in the submission date column. However, from the output, you can observe that PostgreSQL inserted the current date in the submission_date column. This is how the DEFAULT keyword works with the DATE data type.

 **Conclusion**

PostgreSQL supports the DATE data type that stores the date values in YYYY-MM-DD format. Postgres utilizes 4 bytes of storage to store a date value. To store the current date as a default value, use the DEFAULT keyword and CURRENT_DATE function along with the DATE data type. This write-up explained the various use cases of the DATE data type with the help of suitable examples.

---
[View this page online](https://www.commandprompt.com/education/postgresql-date-data-type-with-examples/)

---

# How to Get Current Date Minus 1 Day in PostgreSQL

> In PostgreSQL, the CURRENT_DATE function is used to fetch the current date. To get the current date minus 1 day, we must subtract “1” from the CURRENT_DATE

In PostgreSQL, the CURRENT_DATE is a built-in function that provides the current/prevailing date. It doesn’t take any parameters. The CURRENT_DATE -1 is used to fetch the day before the current date. In Postgres, we must subtract “1” from the current date to fetch the day before today i.e., ‘CURRENT_DATE - 1’.

So, let’s learn how to find the day before the current date in PostgreSQL with the help of examples. In this write-up, you will learn the below-listed learning outcomes regarding the current date minus 1 day:

\- How to Fetch the Current Date in Postgres?

\- How to Get/Fetch the Current Date Minus 1 Day in Postgres?

\- How to Insert Current Date Minus 1 Day to a Postgres Table?

So, let’s get started!

 **How to Fetch the Current Date in Postgres?**

The CURRENT_DATE function is used to fetch the system’s current date and doesn’t require any parameter, as shown in the following syntax:
    
    
    CURRENT_DATE;

The CURRENT_DATE function returns the date in YYYY-MM-DD format.

Let’s open the SQL SHELL, fill in the required information, provide the super user password and run the below statement to get the system’s current date:
    
    
    SELECT CURRENT_DATE;

The output shows that the CURRENT_DATE returns the accurate date.

 **How to Get/Fetch the Current Date Minus 1 Day in Postgres?**

Up till now, you have learned how to fetch the current date. However, this write-up focuses on finding the day before the current date. To do so, you must subtract 1 from the current date as shown below:
    
    
    CURRENT_DATE   - 1;

Let’s implement this concept practically into the SQL SHELL:
    
    
    SELECT CURRENT_DATE - 1;

This command will subtract the 1 day from the system’s current day. In our system, the current date is “2022-08-13”. So, the “CURRENT_DATE - 1” will return “2022-08-12”:

By comparing this output with the previous one, you will come to know that the CURRENT_DATE - 1 provides an accurate result (i.e. current date - 1).

 **How to Insert Current Date Minus 1 Day to a Postgres Table?**

We can utilize the “CURRENT_DATE - 1” to insert a day before today into a specific table. Suppose we already have a table named article_details whose details are as follows:
    
    
    SELECT * FROM article_details;

Let’s insert two more rows into the article_details table. We will pass the system’s current date as the published date in the first row. While in the second row, we will pass the current date minus 1 as the published date:
    
    
    INSERT INTO   article_details(article_id, article_title, published_date)
    
    
    VALUES ('12', 'PostgreSQL   BETWEEN Operator', CURRENT_DATE),
    
    
    ('11', 'PostgreSQL   FETCH Clause', CURRENT_DATE - 1);

The output shows that two rows have been inserted into the article_details table successfully. Let’s see how the updated table looks:

The output verified that the system’s current date and ‘current date -1’ had been successfully inserted into the targeted table.

 **Conclusion**

To get the current date minus 1 day, we have to subtract “1” from the current date. In PostgreSQL, the CURRENT_DATE is an inbuilt function that is used to fetch the prevailing date. It doesn’t take any parameters. It returns a date value in YYYY-MM-DD format, and the returned date will be according to the system’s current date. This post explained the basics of the Postgres CURRENT_DATE function with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-current-date-minus-1-day-in-postgresql/)

---

# How to Get Database Size and Table Size in PostgreSQL

> In PostgreSQL, built-in functions like pg_database_size(), and pg_relation_size() are used to get the database and table size respectively.

In PostgreSQL, built-in functions like pg_database_size(), and pg_relation_size() are used to get the database and table size respectively. The pg_size_pretty() function can be used with the collaboration of the pg_database_size(), pg_relation_size() to present the database/table size in a human-readable format.

This post will present a thorough understanding of pg_database_size(), pg_relation_size(), and pg_size_pretty() functions with examples.

 **How to Find the Database Size Using pg_database_size?**

Use the pg_database_size() function to get the Database size. The syntax of the pg_database_size() function will be as follows:
    
    
    pg_database_size('database_name');

 **Example #1: How to Use the pg_database_size() function in PostgreSQL?**

We already have a database named “example”. Let’s execute the below-given command to see the total size of the selected database:
    
    
    SELECT pg_database_size('example');

The output shows that the pg_database_size() function successfully returned the size of the selected database.

 **Example #2: How to Use the pg_size_pretty() Function With the pg_database_size() Function?**

The database size in the above-given example is not easily readable. Let’s use the pg_size_pretty() function to convert the resultant database size into human-readable format:
    
    
    SELECT pg_size_pretty(pg_database_size('example'));

Now, the size is more understandable. This is how the pg_size_pretty() function assists us in formatting the database size.

 **Example #3: How to Fetch the Size of All Databases in Postgres?**

Let’s execute the below statement to find the size of all the databases:
    
    
    SELECT pg_database.datname, 
    pg_database_size(pg_database.datname) AS size 
    FROM pg_database;

In this example, we utilized the pg_database.datname, with the SELECT query to fetch/collect all the databases available in the server. Next, we conjugated them with pg_database_size() and AS SIZE to get the size of all databases. Following will be the output:

The output proved that the pg_database_size successfully fetched the sizes of all the databases. Let’s utilize pg_size_pretty() function to convert the resultant sizes into human-readable format:
    
    
    SELECT pg_database.datname, 
    pg_size_pretty(pg_database_size(pg_database.datname)) AS size 
     FROM pg_database;

This is how you can fetch the size of all the databases using a single statement.

 **How to Find the Tables Size Using pg_relation_size?**

Use the pg_relation_size() function to get the table size. The basic syntax of the pg_relation_size() function will be as follows:
    
    
    pg_relation_size('table_name');

 **Example #1: How to Use the pg_relation_size() function in PostgreSQL?**

We already have a table named “bike_details”. Let’s run the below statement to see the total size of the targeted table/relation:
    
    
    SELECT pg_relation_size('bike_details');

The output shows that the pg_relation_size() function successfully returned the accurate size of the targeted relation.

 **Example #2: How to Use the pg_size_pretty() Function With the pg_relation_size() Function?**

This example will teach you how to fetch the table’s size in a human-readable format:
    
    
    SELECT pg_size_pretty(pg_relation_size('bike_details'));

Now, users can clearly understand that the selected table carries 8192 bytes.

 **Example #3: How to Get the Total Size of a Table Including Indexes/Additional Objects?**  
The pg_relation_size() function fetches only the table’s size, and it omits the size of indexes/additional objects. To fetch the total size of a table including indexes/additional objects, the pg_total_relation_size() function is used in PostgreSQL:
    
    
    SELECT pg_size_pretty (pg_total_relation_size ('bike_details'));

The output verified the working of pg_total_relation_size() function as it calculates the table size accurately.

 **Conclusion**

In PostgreSQL, built-in functions like pg_database_size(), pg_relation_size(), and pg_total_relation_size() are used to get the database and table size. The pg_total_relation_size() function is used to fetch the total size of a relation including indexes/additional objects. The pg_size_pretty() function can be used with the collaboration of the pg_database_size(), pg_relation_size() to present the database/table size in a human-readable format. In this write-up, you have learned how to get the size of a database or a table in PostgreSQL with the help of different examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-database-size-and-table-size-in-postgresql/)

---

# How to Get Current Date and Time in PostgreSQL

> PostgreSQL offers multiple functions to get the current date and time with or without the time zone, such as NOW(), CURRENT_TIMESTAMP, LOCALTIMESTAMP, etc.

PostgreSQL offers multiple methods to find the current date and time with or without the time zone. In PostgreSQL, the NOW() and CURRENT_TIMESTAMP functions are used to obtain the prevailing/current time, date, and time zone. To obtain the date and time without a time zone, the LOCALTIMESTAMP and the NOW() function(with special implementation) are used.

The CURRENT_TIME function and LOCALTIME function are used to attain the current time with or without a time zone.

This write-up will present a detailed understanding of the several functions to get the current date and time in PostgreSQL.

 **How to Get Present/Current Date and Time in PostgreSQL Using NOW() Function?**

In Postgres, the NOW() function is used to achieve the prevailing time, date, and time zone. Using the server database's time zone settings, it returns the current/up-to-date time and date. Following will be the syntax for the NOW() function:
    
    
    NOW();

PostgreSQL allows us to run the NOW() function either from SQL SHELL or from the pgADMIN.

 **Example #1: How to Use NOW() Function in Postgres?**

Let’s open the pgAdmin’s query tool and run the Postgres NOW() function to understand its working:
    
    
    SELECT NOW();

The output authenticates the working of the NOW() function, as it successfully returned the current time, date, and time zone.

 **Example #2: How to Skip the Time Zone Using NOW() Function in PostgreSQL?**

We have to cast the NOW() function explicitly to get the time and date without time zone restrictions. The below-given example will assist you in this regard:
    
    
    SELECT NOW()::TIMESTAMP;

The output shows that this time the NOW() function returns a timestamp without a time zone.

 **How to Use CURRENT_TIMESTAMP() Function in Postgres?**

In PostgreSQL, the CURRENT_TIMESTAMP function is used to obtain the current/up-to-date time, date, and time zone.

 **Example: How Does the CURRENT_TIMESTAMP Function Work in PostgreSQL?**

Let’s consider the below snippet to get a profound understanding of the CURRENT_TIMESTAMP function:
    
    
    SELECT CURRENT_TIMESTAMP;

The output shows that the CURRENT_TIMESTAMP successfully returns the current date, time, and time zone.

 **How to Fetch Current Time Using CURRENT_TIME Function?**

In PostgreSQL, the CURRENT_TIME function is used to get the current time along with the time zone.

 **Example: How Does CURRENT_TIME Function Work in PostgreSQL?**

The example illustrated below will explain the working of the CURRENT_TIME function:
    
    
    SELECT CURRENT_TIME;

The output authenticates that the targeted function succeeded in returning the present time and time zone.

 **How to Obtain Current Date and Time Using LOCALTIMESTAMP Function?**

This function provides us the current date and time without time zone:

 **Example: How to Use LOCALTIMESTAMP Function in PostgreSQL?**

The below snippet will let you know the working of the LOCALTIMESTAMP function:
    
    
    SELECT LOCALTIMESTAMP;

The output proves that the LOCALTIMESTAMP returns the current date and time without a time zone.

 **How to Get Present/Current Time Using LOCALTIME Function?**

In Postgres, the LOCALTIME function doesn’t return a time zone. Instead, it returns only the current time.

 **Example: How to Use LOCALTIME Function in PostgreSQL?**

The below-given piece of code will return the up-to-date/current time:
    
    
    SELECT LOCALTIME;

Output shows that the LOCALTIME function returns the time only.

 **PostgreSQL CURRENT_DATE Function**

In PostgreSQL, the CURRENT_DATE function can be used to retrieve the latest date.
    
    
    CURRENT_DATE;

 **Example #1: How Does the CURRENT_DATE Function Work in Postgres?**

Run the below command to retrieve the prevailing date:
    
    
    SELECT CURRENT_DATE;

The output shows that the CURRENT_DATE function successfully fetched the current date.

 **Example #2: How to Use the CURRENT_DATE Function on Table’s Data?**

Let’s say we have a table named bike_details in our database that contains the following data:

Let's suppose we want only those bikes whose launch date equals the current date. Let’s run the below-given query:
    
    
    SELECT * FROM bike_details WHERE (bike_launch_date = CURRENT_DATE);

The output shows that the result set contains only those bikes whose launch date is equal to the current date. This is how you can use the CURRENT_DATE function on a table.

 **Conclusion**

In Postgres, the NOW(), CURRENT_TIMESTAMP, and LOCALTIMESTAMP return the current time and date. The CURRENT_TIME function and LOCALTIME function are used to attain the latest time with or without a time zone. This write-up explained the usage of different date and time functions using some examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-get-current-date-and-time-in-postgresql/)

---

# How to Use LIKE Operator in PostgreSQL

> PostgreSQL provides two wildcards: percent % and underscore _ that are used with the aid of the LIKE operator to perform pattern matching.

**PostgreSQL** provides a **LIKE** operator that performs pattern/text matching using wildcards. The **LIKE** operator returns true(Boolean value) if a perfect match is found in the targeted text.

PostgreSQL provides two wildcards, percent (%) and underscore(_), that are used with the aid of the **LIKE** operator. If you didn’t specify a wildcard in the **LIKE** operator, then it will act as an equal operator.

This write-up will discuss both wildcards(% and _) with the help of examples. So, let’s start!

 **How to Use the LIKE Operator/Clause in PostgreSQL?**

The wildcard percent “%” in Postgres is used to specify zero, one, or more than one character/number. While the wildcard underscore “_” is used to specify a single character/number. To avail maximum functionalities, both these operators/clauses can be used combinedly.

There are several syntaxes of the Postgres **LIKE** operator; you can use any of the below-mentioned syntaxes depending on the situation:

 **Syntax 1: How to Find a Value That Starts With “XYZ” Using Like Operator/Clause?**

The below syntax will be used to search for a value that starts with “XYZ”.
    
    
    SELECT FROM   tab_name
    WHERE col_name LIKE 'XYZ%';

Following is a step-by-step explanation of the above syntax:

\- The above syntax illustrates that the string must start with XYZ.

\- The percent “%” wildcard at the end represents that there can be zero or more characters after the specified value i.e. XYZ.

 **Note:** Here, XYZ is just an exemplary value. It can be any string or a number.

 **Syntax 2: How to Use Like Operator/Clause to Find a Substring?**

The following syntax of the LIKE operator is used to search a substring at any position; let’s say XYZ is the targeted substring:
    
    
    SELECT FROM   tab_name
    WHERE col_name LIKE '%XYZ%';

In the above syntax, the percent % wildcard at the start and end represents that there can be zero, one, or more characters/numbers at the beginning or at the end of the string. However, the string must contain a substring “XYZ''.

 **Syntax 3: How to Use Like Operator to Find a Value That Ends With a Specific Character/Number?**

Follow the below-given syntax for the LIKE operator to find a value that ends with a specific value, character, or number:
    
    
    SELECT FROM   tab_name
    WHERE col_name LIKE '%5';

Here, “%5” shows that there can be anything at the start of the string. However, the string must end with 5.

 **Syntax 4: How to Find a Value at a Specific Position Using Like Operator/Clause?**

The underscore “_” wildcard is used to find a value at a specific position:
    
    
    SELECT FROM   tab_name
    WHERE col_name LIKE '_Z';

The underscore **“_”** at the start shows that at the beginning, there must be only a single character and the second character must be “Z”.

 **Syntax 5: How to Find a Value at a Specific Position and That Ends With a Specific Character?**

Now, we have to consider two conditions simultaneously, i.e., X should be the second character in the string, and the string must end with Y. To do so, we will use both wildcards combinedly with the aid of the LIKE operator as shown in the below syntax:
    
    
    SELECT FROM   tab_name
    WHERE col_name LIKE '_X%Y';

Let’s illustrate the above syntax stepwise:

\- The underscore at the beginning represents that there can be any character at the start of a string.

\- The second position must hold an “X”.

\- The % sign shows that there can be zero, one, or more characters in between X and Y.

\- The string must end with the character “Y”.

 **Syntax 6: How to Find a String That Has At Least Two Characters Using Like Operator/Clause?**

Follow the below-given syntax for the **LIKE** operator to get a substring of at least two characters:
    
    
    SELECT FROM   tab_name
    WHERE col_name LIKE '%_%_%';

As we have discussed earlier, the underscore “_” is used to specify a single character, while the “%” is used to specify zero or more characters. In this syntax, we utilized two underscore wildcards, **“_”** and three percent wildcards, **“%”**. So, the **LIKE** operator will fetch all the strings of length two or more.

Similarly, you can use these wildcards with the collaboration of the LIKE operator to perform different functionalities.

 **Example #1: How to Select All the Teams Whose Names Start With “S” Using Like Operator?**

We already have a table named team_details that contains the following data:
    
    
    SELECT * FROM team_details;

Suppose we have to fetch only those teams whose names start with ‘S’; to do so, we will execute the following query:
    
    
    SELECT * 
    FROM team_details 
    WHERE team_name LIKE 'S%';

In this example, we utilized % wildcard along with the LIKE operator to fetch those teams whose names start with S. The output authenticates the working of percent wildcard and LIKE clause.

 **Example #2: How to Select All the Teams Whose Names Contain a Small “s”?**

To fetch the team names that contain a letter s, we will enclose the targeted letter within the percent wildcards:
    
    
    SELECT * 
    FROM team_details 
    WHERE team_name LIKE '%s%';

The output authenticates the working of the LIKE clause in PostgreSQL.

 **Example #3: Select the Teams Whose Second Letter is “a”**

Suppose we have to fetch those teams whose names start with any letter, but the second letter must be “a”. To do so, we will combine both the wildcards as follows:
    
    
    SELECT * 
    FROM team_details 
    WHERE team_name LIKE '_a%';

The underscore _ wildcard represents that the first letter can be anything. Next comes “a” which represents the second letter must be a. While the percent wildcard at the end shows that there can be single or multiple letters followed by the letter a.

The output clarified that the LIKE clause succeeded in fetching those teams whose names start with any letter, but their second letter is “a”.

In this way, you can use any wildcard with the collaboration of the LIKE operator/clause to achieve various functionalities.

 **Conclusion**

To perform pattern matching in PostgreSQL, the LIKE operator uses two wildcards (percent % and underscore _). The wildcard percent “%” in Postgres is used to specify zero, one, or more than one character/number. While the wildcard underscore “_” is used to specify a single character/number. To avail maximum functionalities, both these operators/clauses can be used combinedly. This post considered several examples to explain the working of the LIKE operator/clause in a better way.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-like-operator-in-postgresql/)

---

# How to Use DATE_TRUNC() Function in PostgreSQL

> In PostgreSQL, the DATE_TRUNC() function trims unnecessary values from the date and time and returns a result with specific precision.

In PostgreSQL, the **DATE_TRUNC()** function trims unnecessary values from the date and time and returns a result with specific precision. In simple terms, **DATE_TRUNC()** extracts a TIMESTAMP/INTERVAL and truncates it to a specific level of precision.

This post will explain the usage of the **DATE_TRUNC()** function in Postgres through practical examples. So, let’s begin!

 **How to Use DATE_TRUNC() Function in Postgres?**

The **DATE_TRUNC()** function takes a date part (like a year, month, etc.) and a TIMESTAMP as parameters. The **DATE_TRUNC()** function truncates the TIMESTAMP according to the specified date-part and returns the truncated part with a specific precision level.

 **Basic Syntax of DATE_TRUNC() Function**

The below snippet explains the syntax of the DATE_TRUNC function:
    
    
    DATE_TRUNC(date_part, Field);

● The Field argument represents an INTERVAL or TIMESTAMP value to be truncated.

● The date_part is the main argument of the **DATE_TRUNC()** function based on which the **TIMESTAMP** specified in the field argument will be truncated. The date_part accepts one of the following values:

\- Microsecond, millisecond, second, minute, or hour.

\- Decade, century, or millennium.

\- Day, week, month, quarter, or year.

If you pass any of the values mentioned above to the **DATE_TRUNC()** function, then the TIMESTAMP will be rounded off to a whole value. For instance, if you pass month as an argument to the **DATE_TRUNC()** function, then all the values that came after the month will be reset to their initial values.

For example, seconds, minutes, etc., will be rounded to 00, while the months, years, etc., will be rounded to 01.

 **How Does the DATE_TRUNC() Function Work in PostgreSQL?**

In this write-up, we will use the **‘2022-08-02 11:12:14’** TIMESTAMP in all the examples.

 **Example 1: How to Truncate a TIMESTAMP Value to Year?**

We will pass the “Year” as a first argument to the DATE_TRUNC() function and a TIMESTAMP ‘2022-08-02 11:12:14’ as a second argument:
    
    
    SELECT DATE_TRUNC('Year', TIMESTAMP '2022-08-02 11:12:14');

From the output, you can clearly observe that the Year’s value remains the same, i.e., 2022. However, the remaining values of the specified TIMESTAMP have been reset to their initial values.

 **Example 2: How to Truncate a TIMESTAMP Value to Month?**

Specifying the month in the DATE_TRUNC() function will truncate all the instances of the TIMESTAMP that occurs after the Month:
    
    
    SELECT DATE_TRUNC('Month', TIMESTAMP '2022-08-02 11:12:14');

On successful execution of the **DATE_TRUNC** function, the day, hours, minutes, and seconds have been reset to their initial values.

 **Example 3: How to Truncate a TIMESTAMP Value to Decade?**

Let’s pass the DECADE as a date-part argument to the DATE_TRUNC() function and see how it works in PostgreSQL:
    
    
    SELECT DATE_TRUNC('Decade', TIMESTAMP '2022-08-02 11:12:14');

From the output, you can clearly observe that everything that comes after the decade has been reset to their initial values.

 **Example 4: How to Truncate a TIMESTAMP Value to Day?**

This example will let you know how to pass the day as a first parameter to the **DATE_TRUNC()** function:
    
    
    SELECT DATE_TRUNC('Day', TIMESTAMP '2022-08-02 11:12:14');

The output clarifies that everything that comes after the day date-part has been reset to their initial values.

 **Example 5: How to Use the DATE_TRUNC() Function on Table’s Data?**

Let’s run the below statement to fetch the bike_details table:
    
    
    SELECT * FROM bike_details;

Let’s implement the DATE_TRUNC function on the bike_details table to truncate the year from the bike_launch_date column:
    
    
    SELECT DATE_TRUNC('YEAR', bike_launch_date) FROM bike_details;

The output shows that the Year’s value remains the same. However, the remaining values, such as the month, day, etc., have been reset to their initial values.

 **Conclusion**

The **DATE_TRUNC()** function in Postgres truncate a date or time value to a specific precision. It takes a date part (like a decade, year, month, etc.) and a TIMESTAMP as parameters, and then it truncates the TIMESTAMP according to the specified date part. Finally, it returns the truncated part with a specific precision level. This write-up explained how the date_trunc() function works in PostgreSQL with the help of multiple examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-date_trunc-function-in-postgresql/)

---

# How To Replace a String Using REPLACE() Function in PostgreSQL

> The REPLACE() is a very convenient function that is used to search and replace all the appearances of a string with a new substring/text.

Replacing a record like an email, address, phone number, etc., is a very common task. In PostgreSQL, the REPLACE() function finds a string/substring and replaces it with a new string/substring. The REPLACE() function takes three parameters i.e. an original string, a substring that you want to replace, and a new substring that will replace the old substring.

The aim of this post is to explain the usage of REPLACE() function with the help of examples. So, let’s get started!

 **How To Replace a String Using REPLACE() Function in PostgreSQL?**

The REPLACE() is a very convenient function to search and replace all the appearances of a string with a new substring/text. The basic syntax of the REPLACE() function will be as follows:
    
    
    REPLACE(origianl_string, old_substring, new_substring );

From the above snippet, you can observe that the REPLACE() function accepts three parameters. All three parameters are self-explanatory i.e. it takes a string, an old_substring that needs to be replaced, and a new_substring that will replace the old_substring.

 **Example#1: Basic Usage of the Postgres REPLACE() Function**

This example will give you a basic idea of the REPLACE() function:
    
    
    SELECT REPLACE ('johnjacobs@gmail.com', 'j', 'J');

In this example, we replaced all the occurrences of the small “j” with the capital “J”

 **Example #2: How to Replace a Substring With a new Substring Using the REPLACE() Function**

Let's replace the “com” with the “org”:
    
    
    SELECT REPLACE ('johnjacobs.com', 'com', 'org');

The output shows that the REPLACE() method successfully replaced the “com” with “org”.

 **How to Replace Text/String in a Table’s Column Using the REPLACE() Function**

Suppose we need to replace a substring within the table’s column. To do that, you need to follow the below syntax:
    
    
    UPDATE tab_name
    SET col_name = REPLACE(col_name, old_string, new_string)
    WHERE condition;

In this syntax, tab_name, and col_name represents the name of the targeted table and column, respectively. REPLACE() is a function, old_string represents a string that needs to be replaced, while the new_string is a string that will replace the old_string.

 **Example #1: How to Use REPLACE() Function to Replace a Substring Within the Table’s Column?**

We have a table named bike_details in our database whose details are as follows:
    
    
    SELECT * FROM bike_details;

Suppose we have to update the bike_color column i.e. we need to replace the Red color with White. To do that, let’s execute the below query:
    
    
    UPDATE bike_details
    SET bike_color = REPLACE(bike_color, 'Red', 'White');

Let’s execute the SELECT statement to see the updated table.
    
    
    SELECT * FROM bike_details;

The output clarified that in the bike_details table, all the occurrences of the “Red” substring had been replaced with the “White” substring.

 **Example #2: How to Use REPLACE() Function to Replace Specific Occurrences of a Substring Within the Table’s Column?**

You can use the WHERE Clause to replace only specific occurrences as we did in the below-given example:
    
    
    UPDATE bike_details
    SET bike_color = REPLACE(bike_color, 'Blue', 'Red')
    WHERE bike_id = 8;

Let’s run the below-given query to verify the replaced/updated values of the bike_details table:
    
    
    SELECT * FROM bike_details;

The output proves that this time the REPLACE() function replaces only one substring whose id is equal to 8.

 **Conclusion**

The REPLACE() is a very convenient function that searches for the desired string and replaces all the appearances of that string with a new string/text. The REPLACE() function takes three parameters i.e. an original string, a substring that you want to replace, and a new substring that will replace the old substring. This write-up explained how to use the REPLACE() function in PostgreSQL with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-replace-a-string-using-replace-function-in-postgresql/)

---

# How to Find Length of a String in PostgreSQL

> In PostgreSQL, the LENGTH() function is used to find the length of a string. It takes a string as a parameter and returns the total number of characters.

In PostgreSQL, the **LENGTH()** function is used to calculate the string’s length. It returns the total number of characters. PostgreSQL facilitates us with two more length functions named **OCTET_LENGTH()** and **BIT_LENGTH()**. The **OCTET_LENGTH()** and **BIT_LENGTH()** functions return the string length in the form of bytes and bits, respectively.

This post will demonstrate the working of length functions with the help of multiple examples.

 **PostgreSQL: LENGTH() Function**

Here is the basic syntax of the Postgres LENGTH() function:
    
    
    LENGTH(str);

In the above snippet, the **LENGTH()** is a function, while str represents a string accepted by the LENGTH() function. The string can be text, a single character, char type, varchar, or ‘character varying’ type.

 **Example #1:** **How Does the LENGTH() Function Work in PostgreSQL?**

Let’s pass “commandprompt.com” to the LENGTH() function and see what the output will be:
    
    
    SELECT LENGTH('commandprompt.com');

The output clarifies that the LENGTH() function generated the desired result.

 **Example #2: Pass an Empty String to the LENGTH() Function**

Postgres allows us to pass an empty string to the LENGTH() function:
    
    
    SELECT LENGTH('');

The output shows the appropriateness of the LENGTH() function.

 **Example #3: Pass NULL to the LENGTH()**

Let’s pass the NULL as a parameter to the LENGTH() function:
    
    
    SELECT LENGTH(NULL);

The output shows that this time the LENGTH() function returns a null value.

 **Example #4: Pass a White Space to the LENGTH() Function**

You can pass a white space as a parameter to the LENGTH() function as shown in the below snippet:
    
    
    SELECT LENGTH(' ');

The LENGTH() function returns 1, which shows that the LENGTH() function considers the white space as a character.

 **Example #5: Pass a Currency Symbol to the LENGTH Function**

Let’s pass the currency symbol '₩' to the LENGTH() function:
    
    
    SELECT LENGTH('₩');

The output shows that the LENGTH() function returns an accurate number.

 **Example #6: How to Use LENGTH() Function on Table’s Data?**

We have created a table named submit_article in our database. Let’s fetch the table details using the SELECT query:
    
    
    SELECT * FROM submit_article;

The article_name column holds the string type data. Let's calculate the length of each string using the LENGTH() function:
    
    
    SELECT LENGTH(article_name) FROM submit_article;

Using the LENGTH() function, we will find the length of each string in the article_name column:

This is how the LENGTH() function works on table’s data.

 **PostgreSQL: OCTET_LENGTH() Function**

The OCTET_LENGTH() function takes a string/text as an argument and returns the total bytes present in the targeted string. The below syntax is used to get the string’s length in the form of bytes:
    
    
    OCTET_LENGTH(str);

In example 5 of the previous section, we passed the currency symbol to the LENGTH() function. As a result, the LENGTH() function returns 1. Now let’s pass the same symbol to the OCTET_LENGTH() function, Consequently, you will observe a clear difference.

 **Example: Find the String’s Length in Bytes?**

Let’s run the following query to get the string’s length in the form of Bytes:
    
    
    SELECT OCTET_LENGTH('₩');

Although '₩' is a single character. However, it takes 3 bytes therefore, the OCTET_LENGTH() function returns 3(bytes) instead of 1(character).

 **PostgreSQL: BIT_LENGTH() Function**

The BIT_LENGTH() function takes a string/text as an argument and returns the total bits present in the targeted string.

 **Example: How to Find the Number of Bits in PostgreSQL?**

In this example, we will pass the same currency symbol to the BIT_LENGTH() function:
    
    
    SELECT BIT_LENGTH('₩');

The output shows that the '₩' sign consists of 24 bits.

 **Conclusion**

The **LENGTH()** function in PostgreSQL finds the length of a specific string. It receives a string as an argument/parameter and returns the total number of characters. PostgreSQL provides two more length functions named OCTET_LENGTH() and BIT_LENGTH(). The OCTET_LENGTH() and BIT_LENGTH() functions return the string length in the form of bytes and bits, respectively. This write-up explained how to find the string’s length in Postgres.

---
[View this page online](https://www.commandprompt.com/education/how-to-find-length-of-a-string-in-postgresql/)

---

# How to Describe a Table in PostgreSQL

> PostgreSQL provides several ways to describe a table. For example, the “\d” command, “\dt” command, and information_schema.

In PostgreSQL, describing a table means checking the table’s structure or getting all the information about a table. PostgreSQL offers several ways to describe a table. For example, executing the “\d” or “\dt” command from the SQL SHELL or using information_schema in pgAdmin 4.

Let’s learn how to describe a table in PostgreSQL with the help of examples.

 **How to Describe a Table in PostgreSQL Using SQL SHELL(psql)?**

Let’s go through the below-listed steps to learn how to describe a table in Postgres using **SQL SHELL**.

 **Step 1: Run “\c” Command to Establish a Connection With a Database**

Firstly, open psql, provide the required details, and run the “\c” command followed by database name to connect to a specific database:
    
    
    \c example;

The above snippet shows that you are successfully connected to the desired database.

 **Step 2: Run “\d” Command to Describe All Tables Including System Schemas**

Let’s execute the “\d” command to see all the available relations within the example database:
    
    
    \d;

The \d command fetches all the relations, including those that belong to system schemas.

 **Step 3: Run “\dt” Command to Describe User-defined Tables**

In the above output, we observed that the “\d” command fetched all the tables, including the system’s schemas. To describe only user-defined tables, run the “\dt“ command:
    
    
    \dt;

The above snippet shows that the “\dt” fetched only user-defined tables and skipped the system schemas.

 **Step 4: Run “\d” Command With Table Name to Describe a Specific Tables**

Suppose we have to describe the bike_details table. To do so, we can run the **“\d”** command followed by the table name i.e. **“bike_details”** :
    
    
    \d bike_details;

Executing the “\d” command with the table name successfully described the table details such as column name, data type, primary key, default value, and so on.

 **How to Describe a Table in PostgreSQL Using pgAdmin 4?**

 **PostgreSQL** offers a build-in schema named information_schema that is common to every database. The basic syntax of the information_schema will be as follows:
    
    
     SELECT col_1, col_2, ..., col_N
     FROM information_schema.COLUMNS
     WHERE Condition;

\- The [SELECT](<https://commandprompt.com/education/how-to-use-select-query-in-postgresql/>) query will select/fetch all the specified columns.

\- col_1, col_2, … are the columns to be selected.

\- The information_schema is an inbuilt schema used to describe the table’s information.

\- [WHERE](<https://commandprompt.com/education/how-to-use-where-clause-in-postgresql/>) is an optional clause that is used to specify a condition.

\- Condition represents criteria based on which the selected tables will be described.

The below-given examples will explain this concept with more clarity.

Firstly, you have to open the query tool to run the queries from pgAdmin. To do that, right-click on the selected database and then click on the **“Query Tool”** as shown below:

Clicking on the Query Tool will open the below-given window:

Here, in the query editor, you can execute any command/query of your choice.

 **Example #1: How to Describe More Than One Table Using information_schema?**

Execute the following command to describe several tables using pgAdmin:
    
    
    SELECT * 
    FROM information_schema.COLUMNS;

The above-given output proved that the information schema successfully described all the tables.

 **Example #2: How to Describe a Specific Table?**

Execute the below-given query to describe a specific table using pgAdmin:
    
    
    SELECT * 
    FROM information_schema.COLUMNS
    WHERE TABLE_NAME = 'bike_details';

The output clarified that the information schema, with the aid of the SELECT statement, successfully described all the details of the selected table.

 **Example #3: How to Describe Column Names of a Table?**

Run the below-mentioned query to describe column names of a table in PostgreSQL:
    
    
    SELECT COLUMN_NAME
    FROM information_schema.COLUMNS
    WHERE TABLE_NAME = 'bike_details';

The **SELECT** statement successfully fetched the column names with the help of the information schema.

 **Conclusion**

To describe a Postgres table, the **“\d”, “\dt”,** and **information_schema** are used in PostgreSQL. In PostgreSQL, describing a table means checking the table’s structure or getting all the information about a table. In this write-up, we have learned how to describe single or multiple tables using some suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-describe-a-table-in-postgresql/)

---

# How to Delete Multiple Rows From a Table in PostgreSQL

> In PostgreSQL, the DELETE statement is used with the collaboration of the WHERE clause and IN operator to delete multiple rows from a table.

In PostgreSQL, the DELETE FROM keyword is used to delete one, multiple, or every single row of a table. To delete multiple rows, the [IN operator](<https://commandprompt.com/education/how-to-use-in-operator-in-postgresql/>) with the collaboration of the [WHERE clause](<https://commandprompt.com/education/how-to-use-where-clause-in-postgresql/>) is used in the DELETE statement. PostgreSQL provides an optional parameter named RETURNING that can be used with the DELETE statement to return the currently deleted rows.

This post aims to explain how to delete multiple rows in Postgres with the help of examples. So, let’s get started.

 **How to Delete Multiple Rows in PostgreSQL?**

Use the below syntax to delete multiple rows of a Postgres table:
    
    
    DELETE FROM tab_name
    WHERE col_name IN (row_1, row_2, ..., row_N);

\- Firstly, use the DELETE query followed by the FROM keyword, and then specify the table name from which you want to delete the rows.

\- Next, specify a column name in the WHERE clause.

\- Next, specify the IN operator followed by two parentheses. Within parentheses, specify the list of rows that you want to delete.

 **Example: How to Delete Multiple Rows Using DELETE Query?**

We already have a table in our database named article_details whose details are as follows:
    
    
    SELECT * FROM article_details;

Executing the below-given query will delete multiple rows from the selected table:
    
    
    DELETE FROM article_details
    WHERE article_id IN (2, 4, 7);

The output shows that three rows have been deleted from the article_details table. Let’s verify rows deletion using the SELECT statement:
    
    
    SELECT * FROM article_details;

From the output, you can observe that only three rows are left in the articles_details table. The rows having article ids 2, 4, and 7 have been deleted from the selected table.

 **How to Use RETURNING Clause With DELETE Query?**

With the DELETE statement, an optional clause named RETURNING can be used that returns the currently deleted rows. Here is the syntax of the DELETE statement with the RETURNING clause:
    
    
    DELETE FROM tab_name
    WHERE col_name IN (row_1, row_2,   ..., row_N)
    RETURNING *;

 **Example: How to Use the RETURNING Clause With the DELETE Statement in PostgreSQL?**

In this example, we will delete and return two rows from the article_details table:
    
    
    DELETE FROM   article_details
    WHERE article_id IN (3, 5)
    RETURNING *;

The RETURNING clause returned the recently deleted rows of the selected table. Let’s execute the below command to see the updated table:
    
    
    SELECT * FROM article_details;

The output shows that the articles having ids 3 and 5 didn’t exist in the table.

 **Conclusion**

In PostgreSQL, the DELETE statement is used with the collaboration of the WHERE clause and IN operator to delete multiple rows from a table. Firstly, use the DELETE query followed by the FROM keyword. Afterward, specify the targeted table’s name. Next, specify a column name in the WHERE clause, and finally, specify the IN operator followed by two parentheses. Within parentheses, specify the list of rows that you want to delete. This write-up shows how to delete multiple rows from a Postgres table with the help of several examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-delete-multiple-rows-from-a-table-in-postgresql/)

---

# PostgreSQL Indexes: B-Tree

> What and how to use B-Tree indexes in PostgreSQL

Though most databases offer the capability to index the data within tables, PostgreSQL takes it to another level by offering a wide array of index types as well as custom indexes. 

## What is an Index?

An index is a secondary data structure that provides optimized information on the location of specific data within a table (heap). For example, you may have the following table structure:
    
    
    CREATE TABLE test_index (id BIGSERIAL PRIMARY KEY, first_name TEXT);

This will create a table with the name test_index containing the columns id and first_name. The id column is automatically generated as a BIGINT using the pseudo-type BIGSERIAL and it is our PRIMARY KEY. The PRIMARY KEY will ensure that each row has a UNIQUE id and that no NULL values are present. When the PRIMARY KEY is specified it also creates a secondary data structure, the PRIMARY KEY, which is also an index. 

We can see this by describing the structure of the table:

> Table "public.test_index"

> [...] 

> Indexes:

> "test_index_pkey" PRIMARY KEY, btree (id)

When reviewing the table structure you can see that PostgreSQL automatically created an index with the name “test_index_pkey.” It is designated as the PRIMARY KEY and is using a b-tree index on the column id.

## What good is an index?

The core purpose of an index is to provide faster access to the rows in the table that you are looking for. We can test this by adding data to our table:
    
    
    INSERT INTO test_index(id,first_name) VALUES (generate_series(1,1000000), 'My First_Name');

Using the INSERT statement we have added one million rows using BIGSERIAL (which will autoincrement) and a text value of ‘My First_name’ for each row. This will provide us with enough data to test the immediate value of an index. Let’s query PostgreSQL and ask for the rows with the id of value 50 - 100:

> Index Scan using test_index_pkey on test_index (cost=0.42..9.50 rows=54 width=22) (actual time=0.011..0.021 rows=51 loops=1)

>  **Index Cond: ((id >= 50) AND (id <= 100))**

> Planning Time: 0.136 ms

> Execution Time: 0.039 ms

Using the SELECT with the EXPLAIN command we can see that the query utilized the index that was created with the PRIMARY KEY and that the query took a total execution time of 0.039ms. To show the benefit of the index, let’s run the exact same query with index scans disabled. This will mimic the behavior of not having an index on the table.

> Planning Time: 0.160 ms

> Execution Time: 51.803 ms

As you can see, even with a fast NVME ssd (my laptop), sequentially scanning through 1 million records to retrieve only 50 is quite a bit slower than utilizing an index.

## Indexing options

PostgreSQL offers the widest array of index options available to a database. The index type most used is B-Tree and we will only be discussing it. Other articles may explore types such as GIN.

### B-tree

In [computer science](<https://en.wikipedia.org/wiki/Computer_science>), a **B-tree** is a self-balancing [tree data structure](<https://en.wikipedia.org/wiki/Tree_data_structure>) that maintains sorted data and allows searches, sequential access, insertions, and deletions in [logarithmic time](<https://en.wikipedia.org/wiki/Logarithmic_time>). The B-tree generalizes the [binary search tree](<https://en.wikipedia.org/wiki/Binary_search_tree>), allowing for [nodes](<https://en.wikipedia.org/wiki/Node_\(computer_science\)>) with more than two children.[[2]](<https://en.wikipedia.org/wiki/B-tree#cite_note-FOOTNOTEComer1979-2>) Unlike other [self-balancing binary search trees](<https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree>), the B-tree is well suited for storage systems that read and write relatively large blocks of data, such as [databases](<https://en.wikipedia.org/wiki/Database>) and [file systems](<https://en.wikipedia.org/wiki/File_system>).[1]

A practical advantage of B-Tree is that it is widely used, widely understood, and supports five comparison operators. They are:

  * Less than: <
  * Less than or equal: <=
  * Equal: =
  * Greater than or equal: >= 
  * Greater than: >



You can read more about the PostgreSQL B-tree [operator class here](<https://www.postgresql.org/docs/current/xindex.html#XINDEX-BTREE-STRAT-TABLE>).

### What about text?

By default a B-Tree index will not provide operators for text based data types including varchar, text and char. This can make searching text using an operator such as LIKE , ~ (REGEX) or = possible.
    
    
    UPDATE test_index SET first_name = ‘Joshua’ WHERE id = 50;

The UPDATE we just executed will change exactly one row. We are changing the column first_name from ‘My First_name’ to ‘Joshua’ WHERE id = 50. Now let’s SELECT only that single column:

> [...]

> Planning Time: 0.078 ms

> Execution Time: 45.385 ms

> Now we add a B-tTree index with text_pattern_ops and run the query again:

> CREATE INDEX first_name_idx on test_index(first_name text_pattern_ops);

> EXPLAIN ANALYZE SELECT * FROM test_index WHERE first_name = 'Joshua';

> Index Scan using first_name_idx on test_index

> [...]

> Planning Time: 0.255 ms

> Execution Time: 0.052 ms

The other two text pattern operators are varchar_pattern_ops and bpchar_pattern_ops for use with the data types varchar and char respectively.

### Case insensitive searching

A common problem this can solve is case-insensitive searching. By default PostgreSQL will not use an index if you were to use an operator such as ~* or ILIKE. You can work around this problem by using a functional index.
    
    
    CREATE INDEX lower_first_name_idx ON test_index(LOWER(first_name));
    
    
    SELECT * FROM test_index WHERE lower(first_name) = ‘Joshua’;

> [...]

> Planning Time: 0.079 ms

> Execution Time: 0.112 ms

### Partial Indexes

By default PostgreSQL will index an entire data set within a column or columns. There may be times when this is not necessary. Consider a situation where you know that 99% of the time you are pulling data from only the first 100 ids in our table. You could define an index like this:
    
    
    CREATE INDEX fifty_and_under_idx ON test_index (id) WHERE id BETWEEN 1 AND 50;

>  **Index Scan using fifty_and_under_idx** on test_index  
> [...]

> Index Cond: (id = 35)

> Planning Time: 0.844 ms

> Execution Time: 0.066 ms

PostgreSQL chose the fifty_and_under_idx instead of the PRIMARY KEY because the cost of using the fifty_and_under_idx is cheaper. It is a smaller index and therefore uses less memory, less cpu resources and is faster to provide the required data.

### Index only scans and Covering Indexes

In older versions of PostgreSQL, a B-tree index only contained pointers to the heap (table) of where a particular set of data could be accessed. This can cause performance issues because we first need to scan the index and then retrieve the data from the table. While Index scans are relatively cheap due to how they store data, table scans can be very expensive because the data can be at any place within the table. Though current enterprise methods of storage have alleviated much of this (SSD/NVME) performance impact, it still exists as we need to search for the data twice. 

An Index Only or Covering index allows the storing of specific data within the index. When this type of index is utilized we only need to retrieve data from the index itself and we do not need to retrieve the data from the table. However, specific conditions must be satisfied for these types of indexes to work. From the PostgreSQL docs[2]:

  1. The index type must support index-only scans. B-tree indexes always do. GiST and SP-GiST indexes support index-only scans for some operator classes but not others. Other index types have no support. The underlying requirement is that the index must physically store, or else be able to reconstruct, the original data value for each index entry. As a counterexample, GIN indexes cannot support index-only scans because each index entry typically holds only part of the original data value.
  2. The query must reference only columns stored in the index. For example, given an index on columns x and y of a table that also has a column z, these queries could use index-only scans:


    
    
    SELECT x, y FROM tab WHERE x = 'key';
    
    
    SELECT x FROM tab WHERE x = 'key' AND y < 42;

but these queries could not:
    
    
    SELECT x, z FROM tab WHERE x = 'key';
    
    
    SELECT x FROM tab WHERE x = 'key' AND z < 42;

Using an example from our table:
    
    
    CREATE INDEX id_first_name_idx ON test_index (id,first_name);
    EXPLAIN ANALYZE SELECT * FROM test_index WHERE id < 50 AND  first_name = 'Joshua';

>  **Index Only Scan** using id_first_name_idx on test_index (cost=0.42..6.70 rows=1 width=22) (actual time=0.008..0.008 rows=0 loops=1)

> Index Cond: ((id < 50) AND (first_name = 'Joshua'::text))

> Heap Fetches: 0

> Planning Time: 0.146 ms

> Execution Time: 0.025 ms

  1. <https://en.wikipedia.org/wiki/B-tree#:~:text=A%20B%2Dtree%20index%20creates,pages%20at%20the%20lowest%20level>
  2. <https://www.postgresql.org/docs/current/indexes-index-only-scans.html>

---
[View this page online](https://www.commandprompt.com/education/postgresql-indexes-b-tree/)

---

# EnterpriseDB (EDB) vs PostgreSQL

> An objective analysis of EnterpriseDB PostgreSQL offering vs Community/Ecosystem PostgreSQL

When considering how to deploy PostgreSQL one must consider the pros and cons of different deployment methods of PostgreSQL. The three most common on-prem/full OS capable deployments are your Linux distribution, packages from postgresql.org, and EnterpriseDB PostgreSQL. We will not be discussing managed cloud options as all popular cloud options are forks, they are not PostgreSQL (though often they are compatible).

### Linux Distributions

The majority of people running Postgraduate are running Linux and likely Debian, Ubuntu or some version of RHEL (whether the free versions or not). The good news is that the PostgreSQL community provides direct support for these distributions. The recommended way to running PostgreSQL is from native packages for your operating system. These packages can be found here:

  * [Debian](<https://www.postgresql.org/download/linux/debian/>)
  * [Ubuntu](<https://www.postgresql.org/download/linux/ubuntu/>)
  * [RHEL and flavors](<https://www.postgresql.org/download/linux/redhat/>)
  * [All others](<https://www.postgresql.org/download/>)



### EnterpriseDB

EnterpriseDB is one of the oldest PostgreSQL companies in existence. In fact in North America there is only one that is older, [Command Prompt](<https://commandprompt.com/>) and EnterpriseDB was once upon a time a client of Command Prompt. They have become one of the largest code contributors to PostgreSQL in the world and with the acquisition of 2ndQuadrant they now hold a brain trust of intellectual property that is second to none in product development for PostgreSQL. This includes fascinating tools such as BDR which provides Multi-Master capabilities for PostgreSQL. Unfortunately, they have chosen to keep BDR closed source which denies a wider community the ability to help them increase the value of the software.

Though closed source, they are the preferred providers of the MacOS and Windows installers and are referenced on Postgresql.org. The advantage to these distributions is that like a Linux distribution they contain a vast array of software to allow the lift to use PostgreSQL to be much less than installing and configuring all the components individually.

## EnterpriseDB vs PostgreSQL community

The PostgreSQL community is far larger than EnterpriseDB with a worldwide ecosystem that is second to only Linux. EnterpriseDB does offer some fantastic tools that help solve real problems for PostgreSQL, some Open Source, some not.

### Connection Pooling

A connection pooler is a piece of software that you place in front of a database to manage connections. This is sometimes necessary due to how resource intensive it is to drop and create database connections. As PostgreSQL is process based, this is even more expensive (though it is true that it has become much more efficient in recent releases). The use of a connection pooler, especially if on a different machine than the database can greatly increase the efficiency of app servers and provide more resources for use on the database server itself.

#### EDB

  * Open Source: Yes
  * [Pgbouncer](<https://www.pgbouncer.org/>)



#### Ecosystem/Community standard

  * Open Source: Yes
  * [PgBouncer](<https://www.pgbouncer.org/>)
  * Open Source: Yes
  * [PgPool-II](<https://pgpool.net/mediawiki/index.php/Main_Page>)



### High Availability

There is no question that high availability in today’s world is one of the most important features of a database. The only feature more important is a proper resiliency and data retention capability (backups). The three options offered below are not the only options available (by far). Many middleware stacks offer HA built in for application resilience. There is also proxy software that can provide similar capabilities with the added benefit of features such as Read/Write split.

#### EDB

  * Open Source: No
  * [Failover Manager](<https://www.enterprisedb.com/docs/efm/latest/>)



#### Ecosystem/Community standard

  * Microsoft/Citus
    * Open Source: Yes
    * [pg_auto_failover](<https://github.com/citusdata/pg_auto_failover>)
  * Zolando
    * Open Source: Yes
    * [patroni](<https://github.com/zalando/patroni>)



### Replication Management

Replication management is a difficult category to define. On the one hand it means utilities to easily manage the replication features of PostgreSQL. On the other hand, PostgreSQL provides everything needed to manage such features. One could argue that this doesn’t need a separate category outside of perhaps the monitoring of the features which PostgreSQL does not adequately support.

#### EDB

  * Open Source: Yes
  * [Replication Manager](<https://repmgr.org/>)



#### Ecosystem/Community standard

  * EnterpriseDB
    * Open Source: Yes
    * [Replication Manager](<https://repmgr.org/>)



### Backups

There are few tools in a database suite more important than backups. Backups are the lifeblood of making sure a database is not only available but resilient. The PostgreSQL project provides three utilities for backups: pg_dump, pg_dumpall, and pg_basebackup. They are all good tools but they are limited when discussing larger databases and the need for features such as differential or incremental backups.

#### EDB

  * Open Source: Yes
  * [Barman](<https://pgbarman.org/>)



#### Ecosystem/Community standard

  * Open Source: Yes
  * [PgBackrest](<https://pgbackrest.org/>)



### Management and Monitoring

When PostgreSQL it is important to properly manage and monitor the server. There are a number of ways to do this. A lot of experienced DBAs prefer using a direct SQL console such as psql. However, a lot of newer users prefer systems such as PgAdmin for administration, and Zabbix or Nagios for monitoring. There is definitely no right answer on this particular topic as the right tool will integrate into existing workflows or operation centers. Command Prompt utilizes[ Zabbix](<https://www.zabbix.com/>) to provide enterprise class monitoring and alerting for its clients. Further the majority of Command Prompt operations staff is more comfortable with psql than a graphical tool such as PgAdmin.

### EDB

  * Open Source: No
  * [PostgreSQL Enterprise Manager](<https://www.enterprisedb.com/products/postgres-enterprise-manager-best-gui-tools-database-management>)
    * Note: It is based on the already extremely capable [PgAdminIV](<https://www.pgadmin.org/>)



### Ecosystem/Community Standard

  * Open Source: Yes
  * [PgAdminIV](<https://www.pgadmin.org/>)



Command Prompt understands that sometimes a closed source version of software provides better features than the Open Source counterparts. However, it is Command Prompt’s considerable experience over 25 years of providing expert PostgreSQL professional services and support that there are a minute number of closed source opportunities for PostgreSQL. The ecosystem and community is vibrant and continuing to solve the problems that enterprises face in a collaborative and Open Source way.

---
[View this page online](https://www.commandprompt.com/education/enterprisedb-vs-postgresql/)

---

# How to Insert Multiple Rows to a Table in PostgreSQL

> The INSERT INTO statement is used to insert single or multiple rows into a table. To insert multiple rows in a table, the comma-separated syntax is used.

In PostgreSQL, the INSERT INTO command inserts one or multiple rows into a Postgres table. Multi-row insertion requires the use of comma-separated syntax. PostgreSQL provides a RETURNING clause that can be used with the INSERT query to return the currently inserted rows.

This write-up will teach you how to insert multiple rows in a table with the help of examples. So, let’s start!

 **How to Insert Multiple Rows to a Table in PostgreSQL?**

Specify the comma-separated values in the **INSERT** query to add/insert multiple rows in a specific table. Use the following syntax for inserting multiple rows to a table in Postgres:
    
    
    INSERT INTO tab_name (col_list)
    VALUES
    (val_list_1),
    (val_list_2),
    ...
    (val_list_n);

Let’s understand what the above syntax says:

● Use the INSERT INTO query followed by the table name, into which you want to insert the rows.

● Next, specify a column or list of columns in the parentheses.

● Finally, specify a VALUES keyword followed by the list of values to be inserted in multiple rows.

 **Example #1: How to Insert Multiple Rows to a Table in PostgreSQL?**

We have already created a table named article_details whose details are as follows:
    
    
    SELECT * FROM article_details;

The output shows that the article_details table has three columns: article_id, article_title, and published_date. Let’s run the INSERT INTO statement to insert five new rows to the selected table:
    
    
    INSERT INTO 
    article_details(article_id, article_title, published_date)
    VALUES
      ('5', 'PostgreSQL WHERE Clause', '2022-07-01'),
      ('2', 'PostgreSQL LIKE Operator','2022-07-15'),
      ('1', 'PostgreSQL CREATE TABLE','2022-07-15'),
      ('7', 'PostgreSQL DROP TABLE','2022-07-18'),
      ('4', 'PostgreSQL TRUNCATE TABLE','2022-08-05');

You can check/verify the inserted data by executing the below-given query:
    
    
    SElECT * FROM article_details;

The output clarifies that five rows have been inserted into the targeted table successfully.

 **Example #2: How to Insert and Return Multiple Rows in PostgreSQL?**

Postgres provides an optional clause named RETURNING that can be used with the INSERT statement to return the currently inserted data:
    
    
    INSERT INTO 
    article_details(article_id, article_title, published_date)
    VALUES
      ('3', 'PostgreSQL INSERT Query', '2022-07-01'),
      ('6', 'PostgreSQL DELETE Query','2022-07-15')
      RETURNING *;

The output shows that the RETURNING clause returns the newly inserted rows. Let’s execute the below command to see the updated table:
    
    
    SELECT * FROM article_details;

PostgreSQL maintains the insertion order. However, the [ORDER BY](<https://www.commandprompt.com/education/how-to-use-order-by-clause-in-postgresql/>) clause can be used to sort the table’s data in a specific order. Let’s run the following command to sort the rows in ascending order:
    
    
    SELECT * FROM article_details
    ORDER BY article_id ASC;

The output verified that the ORDER BY clause sorted the rows in ascending order (based on article_id).

 **Conclusion**

To insert multiple rows in a table, the comma-separated syntax is used. To do that, use the INSERT INTO query followed by the table name into which you want to insert the rows. Next, specify a column or list of columns in the parentheses. Finally, specify a VALUES keyword followed by the list of values to be inserted in multiple rows. PostgreSQL provides a returning clause that can be used with the INSERT query that returns the currently inserted rows. This write-up shows how to insert multiple rows into a Postgres table with the help of several examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-insert-multiple-rows-to-a-table-in-postgresql/)

---

# How to Use FETCH Clause in PostgreSQL

> PostgreSQL provides a FETCH clause that is used to fetch/retrieve a part of rows returned by any query. It performs the same functionality as the LIMIT clause.

PostgreSQL provides a FETCH clause (not to be confused with FETCH with the use of CURSORS) that is used to fetch/retrieve a part of rows returned by any query. The FETCH clause performs the same functionality as the [LIMIT](<https://commandprompt.com/education/how-to-use-limit-clause-in-postgresql/>) clause. The LIMIT clause is not a standard SQL command, while the FETCH clause is a standard SQL command, so it provides more flexibility/compatibility.

This write-up demonstrates the working of the FETCH clause in PostgreSQL using some examples.

 **How to Use the FETCH in PostgreSQL?**

The below snippet will illustrate the basic syntax of the Postgres FETCH clause:
    
    
    OFFSET start { ROW | ROWS }
    FETCH { FIRST | NEXT } [ row_count ] { ROW | ROWS } ONLY

Let’s analyze the above syntax stepwise:

\- OFFSET is a clause in Postgres that is used to skip some rows.

\- Strat represents an integer value that must be >= 0.

\- ROW and ROWS are synonymous with each other similarly, FIRST and NEXT are synonymous with each other.

\- row_count represents the number of rows to be fetched, and it must be >=1. By default, its value is 1.

Let’s directly jump into the practical implementation of the FETCH clause.

 **Example #1: How to Use the FETCH Clause in PostgreSQL?**

We already have a table in our database whose details are listed below:
    
    
    SELECT * FROM article_details;

The output shows that the article_details table has ten rows. Let’s run the following query to fetch the first three rows of the article details table (sorted by article_id in ascending order):
    
    
    SELECT * FROM article_details
    ORDER BY article_id ASC
    FETCH FIRST 3 ROW ONLY;

The output shows that the FETCH clause successfully fetched the first three rows of the selected table.

 **Example #2: How to Skip First Three Rows and Fetch Next Three Rows in PostgreSQL?**

Use the Postgres OFFSET clause to skip the first three rows of the table and then use the FETCH CLAUSE to fetch the next three rows:
    
    
    SELECT * FROM article_details
    ORDER BY article_id ASC
    OFFSET 3 ROWS
    FETCH FIRST 3 ROW ONLY;

The output shows that the FETCH clause succeeded in fetching the next three rows after the first three rows (sorted by article_id).

 **Example #3: How to Fetch the Last Three Rows of a Table in Postgres?**

Sort the article_id in descending order, and utilize the FETCH method to fetch the last three rows:
    
    
    SELECT * FROM article_details
    ORDER BY article_id DESC
    FETCH FIRST 3 ROW ONLY;

The output shows that the FETCH clause succeeded in fetching the last three rows of the selected table.

 **Conclusion**

In PostgreSQL, the FETCH clause is used to fetch/retrieve a specific portion/part of rows returned by any query. An optional clause named OFFSET can be used with the FETCH clause to skip some rows of a table. The FETCH clause performs the same functionality as the LIMIT clause. The LIMIT clause is not a standard SQL command, while the FETCH clause is a standard SQL command. Therefore, the FETCH clause provides more flexibility/compatibility. This write-up described the working of the FETCH clause with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-fetch-clause-in-postgresql/)

---

# How to Use the Truncate Table Command in PostgreSQL

> PostgreSQL provides several methods for truncating a specific table. The TRUNCATE TABLE command is one of them. It can be executed from the psql and pgAdmin.

PostgreSQL offers a couple of ways to truncate a particular table. The **TRUNCATE TABLE** command is one of the most frequently used ways of truncating a table. The **TRUNCATE TABLE** command can be executed from the SQL SHELL as well as from pg Admin.

This write-up will illustrate the usage of the **TRUNCATE TABLE** command with the help of different examples. So, let’s start!

 **How to Truncate a Table in PostgreSQL?**

The basic syntax of the **TRUNCATE TABLE** command will be as follows:
    
    
    TRUNCATE TABLE tab_name;

Here, **tab_name** is a table to be truncated.

 **Parameters of the TRUNCATE TABLE Command**

The **“TRUNCATE TABLE”** command can accept one of the following parameters:

● **CONTINUE IDENTITY** : It is a default option in the **TRUNCATE TABLE** command that doesn’t modify or restart the value of orders.

● **RESTART IDENTITY:** Resets the identity column.

● **CASCADE:** It truncates all the tables, including those tables that have foreign-key references to other tables.

● **RESTRICT:** It is a default option in the **TRUNCATE TABLE** that is used to decline truncation if any other tables have a foreign-key reference of tables.

 **How to Use the TRUNCATE TABLE Statment From the psql?**

Open the SQL SHELL and perform the following steps to truncate a table from the selected database.

 **Step 1: Establish a Connection With the Database**

Select a database and establish a connection with the selected table using the **“\c”** command:

 **Step 2: Select a Table**

Run the **“\dt”** command to see the list of tables:

Choose a table that you want to truncate. Let’s say we need to truncate the staff_details table.

 **Step 3: Truncate the Table Using TRUNCATE TABLE Command**

Run the **“TRUNCATE TABLE”** command as shown in the following snippet to truncate the selected table:
    
    
    TRUNCATE TABLE staff_details;

The above snippet proves that the **TRUNCATE TABLE** command gets executed successfully.

 **How to Truncate a Table Using GUI?**

Follow the below steps properly to **TRUNCATE** a table using **pgAdmin** :

 **Step 1: Select a Database**

Firstly, open the **pgAdmin** and select the desired database from the object tree:

We selected the **“example”** database.

 **Step 2: Select a Table**

Within the selected database, locate the **public** section under the **schemas** sections, and select a table that you want to truncate:

Suppose we want to truncate the **“author_details”** table.

 **Step 3: Truncate the Desired Table**

Right-click on the selected table and select the **“Truncate”** option to truncate/delete the desired table:

 **Step 4: Confirm the Table Truncation**

Clicking on the **Truncate** option will open a confirmation window. Click on the **“Yes”** button to truncate the selected table:

Clicking on the **“Yes”** button will show a confirmation message at the bottom-right side of your computer screen:

The above snippet verifies that the selected table has been truncated successfully.

 **How to Execute TRUNCATE TABLE Command From pgAdmin?**

Right-click on the tables section and select the “Query Tool” option:

Clicking on the Query Tool option will open the following window:

Type the below-given command to truncate the author_details table:
    
    
    TRUNCATE TABLE author_details;

The output clarifies that the selected table has been truncated successfully.

 **How to Truncate a Table That Has Foreign Key References?**

Let’s execute the following command to truncate the article_details table:
    
    
    TRUNCATE TABLE article_details;

The output shows that an error occurred when we tried to truncate the “article_details” table. The error says you can’t truncate a foreign key-referenced table. To deal with such errors, the CASCADE parameter is used along with the TRUNCATE TABLE command.

Let’s execute the following query to truncate the article_details table:

The output verified that the article_details table had been truncated successfully.

 **Conclusion**

PostgreSQL provides several methods for truncating a specific table. The **TRUNCATE TABLE** command is one of them. PostgreSQL offers multiple parameters that can be used with the **TRUNCATE TABLE** command to achieve different functions. For example, the CASCADE parameter is used to truncate a table along with its dependent objects completely. This write-up demonstrated the working of the TRUNCATE TABLE using relevant examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-truncate-table-command-in-postgresql/)

---

# How to Use IN Operator in PostgreSQL

> In PostgreSQL, the IN operator is used with the collaboration of the WHERE clause to check the existence of a particular value in a list of values.

In PostgreSQL, the **IN** operator is used with the collaboration of the WHERE clause to check the existence of a particular value in a list of values. If a match is found between a particular value and a list of given values, then the **IN** operator returns a Boolean value **“true”**.

This post will consider some examples to explain the working of the IN operator in PostgreSQL. So, let’s start!

 **How to Use IN Operator in PostgreSQL?**

In PostgreSQL, if the targeted_val matches with the values of the given list, then the IN operator will return a true value. The OR operator, along with the equal to “=” operator, produces the same results as IN operator.

The basic syntax of the IN operator will look like this:
    
    
    targeted_val IN (val_1,val_2,.., val_N)

Here in the above syntax, targeted_val is a value to be searched. While val_1, val_2, …, val_N represents the list of values to which the targeted_val will be compared.

The list values can be anything such as numbers, literals, result-set of the SELECT statement, or strings.

Let’s jump into the practical implementation of the Postgres IN operator:

 **Example 1: How to Use IN Operator in PostgreSQL?**

Suppose we have a table named bike_details whose details are as follows:
    
    
    SELECT * FROM bike_details;

Suppose we want to know the price of bikes whose ids are 5, 6, and 7. Then we will execute the following query:
    
    
    SELECT * FROM bike_details
    WHERE bike_id IN (5, 6, 7)
    ORDER BY bike_id ASC;

The output verifies that the IN operator finds the perfect match and hence returns the record of selected bikes.

 **Example 2: How to Use NOT IN Operator in PostgreSQL?**

The NOT IN operator is used to get contradictory results as compared to the IN operator. The NOT IN operator will produce the same result as the combination of not equal “<>” and “AND” operators does. The NOT IN operator will return all the records available in the list except the searched records:
    
    
    SELECT * FROM bike_details
    WHERE bike_id NOT IN (5, 6, 7)
    ORDER BY bike_id ASC;

The output proved that the NOT IN operator fetched all the records except the targeted records (i.e. bike_id = 5, 6, and 7).

 **What is a Subquery in Postgres?**

If there is a query within the parenthesis of IN operator, then it will be referred to as a subquery. The basic syntax of the IN operator with respect to the subquery will be as follows:
    
    
    targeted_val IN (SELECT col_name FROM tab_name);

The snippet shows that a query is nested within another query, which is known as a subquery.

 **Example: How to Use an IN Operator With a Subquery in Postgres?**

In this example, we will use the IN operator with a subquery to fetch all those bikes whose bike_color starts with “B”:
    
    
    SELECT * FROM bike_details
    WHERE bike_color IN (
    SELECT bike_color FROM bike_details
    WHERE (bike_color LIKE 'B%'));

The above query will execute in the following sequence:

\- Firstly, the subquery will execute. It will fetch all those bikes whose bike_color starts with B.

\- The result set will be passed to the outer query.

\- Finally, the outer query will get executed.

\- Consequently, the IN operator will produce the following output:

The output authenticates the working of IN operator with a subquery.

 **Conclusion**

In PostgreSQL, the **IN** operator is used with the collaboration of the WHERE clause to check the existence of a particular value in a given list. The list values can be anything such as numbers, literals, result-set of the SELECT statement, or strings. The **IN** operator returns true if the targeted value is found in the given list of values. Specifying a NOT operator prior to the IN operator will produce contradictory results as compared to the IN operator. This write-up explained the working of IN operator with the help of some suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-in-operator-in-postgresql/)

---

# How to Use HAVING Clause in PostgreSQL

> In Postgres, the HAVING clause is mostly used with the GROUP BY clause to filter the group/aggregate based on some specific condition.

PostgreSQL offers a **HAVING** clause that is used to specify a specific condition for a group/aggregate. Generally, the **HAVING** clause is used in conjunction with the GROUP BY clause for filtering the groups based on some particular criteria.

In PostgreSQL, a WHERE clause specifies a condition for table columns; however, the **HAVING** clause specifies a condition for groups/aggregates.

This write-up will explain how to use the Postgres **HAVING** clause with the help of some examples. So, let’s begin.

 **How to Use the HAVING Clause in PostgreSQL?**

The first step towards working with Postgres' HAVING clause is to understand its basic syntax:
    
    
    SELECT
      col1, col2
    FROM
      tbl_name
    GROUP BY
      col1, col2
    HAVING
      condition;

Let’s illustrate the above syntax stepwise:

\- Here, col_1, and col_2 are two columns returned by the GROUP BY clause.

\- The returned groups will be filtered based on the condition specified within the HAVING clause.

Postgres allows us to use some other clauses of the SELECT query with the HAVING clause, such as ORDER BY, LIMIT, etc.

While specifying multiple clauses, you have to follow the below-given hierarchy:

\- FROM, WHERE, and GROUP BY clauses must come before the HAVING clause while the ORDER BY clause and LIMIT clause must come after the HAVING clause.

 **Example 1: Basic Understanding of GROUP BY Clause:**

Let’s execute the SELECT statement to get all the records of the bike_details table:

The output shows that there are ten records in the bike_details table.

Let’s run the following query to get a basic understanding of the GROUP BY clause:
    
    
    SELECT
      bike_model,
      SUM (bike_price)
    FROM
      bike_detials
    GROUP BY
      bike_model;

The output shows that the GROUP BY clause eliminated the duplicated records.

 **Example 2: HAVING Clause with SUM() Function:**

In the below-given example, the HAVING clause will fetch only those groups that have bike_price more than 275,000:
    
    
    SELECT
      bike_model,
      SUM (bike_price)
    FROM
      bike_details
    GROUP BY
      bike_model
    HAVING SUM (bike_price) > 275000;

The output verified that the HAVING clause returned only those groups that satisfied the criteria, i.e., bike_price > 275,000.

 **Example 3: HAVING Clause with COUNT() Function:**

Suppose we have to count the number of groups whose price is greater than 275,000. To do so, we can use the COUNT() function with the collaboration of the HAVING clause and SELECT statement:
    
    
    SELECT
      bike_model,
      COUNT (bike_price)
    FROM
      bike_details
    GROUP BY
      bike_model
    HAVING SUM (bike_price) > 275000;

The output shows that there are two bikes whose bike_model is 2022.

 **Conclusion**

PostgreSQL provides a HAVING clause that is used to specify a specific condition for a group/aggregate. Generally, the HAVING clause is used in conjunction with the GROUP BY clause for filtering the groups based on some particular criteria. Different functions like SUM(), COUNT(), etc., are used with the HAVING clause to specify a particular search condition. In this write-up, we considered multiple examples to understand the working of the Postgres HAVING clause in a better way.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-having-clause-in-postgresql/)

---

# How to Use DISTINCT Keyword in PostgreSQL

> In PostgreSQL, the DISTINCT keyword/clause is used within the SELECT statement to fetch the unique records from the result-set.

In PostgreSQL, the **DISTINCT** keyword/clause is used within the SELECT statement to fetch the unique records from the result-set. The **DISTINCT** keyword removes all the redundant/duplicate records and returns only the unique ones.

In PostgreSQL, the **SELECT DISTINCT** clause can be used to fetch unique records for a single or multiple columns of a result set returned by the SELECT statement. In the case of multiple columns, the SELECT DISTINCT clause skips only those records that have duplicates in all the specified columns.

In this write-up, we will explain the different use cases of the SELECT DISTINCT clause using some examples. So, let’s get started.

 **How to Use DISTINCT Keyword/Clause in PostgreSQL?**

The below-given snippet illustrates the syntax of the **DISTINCT** keyword:
    
    
    SELECT DISTINCT col_1, col_2,.....col_N
    FROM tab_name

\- col_1, col_2,.....col_N are the n number of columns to be fetched by the SELECT statement.

\- The SELECT **DISTINCT** represents that only unique records will be fetched/returned, and the duplicate records will be neglected.

 **Example 1: Fetch Table Records Without DISTINCT Keyword**

Firstly, we will run the SELECT statement to get all the records of the bike_details table:
    
    
    SELECT * FROM bike_details;

Let’s execute the below-given query to fetch the bike_model column:
    
    
    SELECT bike_model FROM bike_details;

The output shows that the bike_model column has some unique as well as some duplicate records.

 **Example 2: Fetch Table Records With DISTINCT Keyword**

Let’s run the SELECT statement with the collaboration of the DISTINCT keyword to get only unique records from the bike_model column:
    
    
    SELECT DISTINCT bike_model FROM bike_details;

The output proved that the DISTINCT keyword fetched only the unique records and skipped duplicated ones.

 **Example 3: Fetch Sorted and Unique Records**

Let’s execute the following query to get the sorted and unique records from the bike_model column:
    
    
    SELECT DISTINCT bike_model 
    FROM bike_details 
    ORDER BY bike_model DESC;

The output clarified that the SELECT DISTINCT clause returned the unique and sorted(descending order) records of the bike_details table.

 **Example 4: Fetch Multiple Columns Using DISTINCT Keyword**

You have to follow the comma-separated syntax to fetch more than one column using the DISTINCT keyword:
    
    
    SELECT DISTINCT bike_model, bike_color 
    FROM bike_details 
    ORDER BY bike_model DESC;

\- From the above snippet, we can observe that the bike_model 2022 occurs twice. But the SELECT DISTINCT didn’t eliminate it because bike_color for both these records is different.

\- This proved that the DISTINCT keyword evaluated the duplicated values based on both bike_model and bike_color columns.

\- The SELECT DISTINCT clause skipped only those records that were duplicated in both bike_model and bike_color columns.

 **Conclusion**

In PostgreSQL, the **DISTINCT** keyword/clause is used with the collaboration of the SELECT statement to fetch the unique records from a result-set. The **DISTINCT** keyword removes all the redundant/duplicate records and returns only the unique ones. In PostgreSQL, the **DISTINCT** keyword or the **SELECT DISTINCT** clause can be used to fetch single or multiple columns of a result set returned by the SELECT statement. This write-up considered several examples to explain the working of the SELECT DISTINCT clause in PostgreSQL.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-distinct-keyword-in-postgresql/)

---

# How to Use DELETE Query in PostgreSQL

> In PostgreSQL, the DELETE query can be used with or without the WHERE clause to delete a single, multiple, or all the rows of a specific table.

In PostgreSQL, the **DELETE** query is used to remove/delete a single, multiple, or all the rows of a table. Within the **DELETE** query, the **WHERE** clause is used to specify a condition or a group of conditions. In such a case, the **DELETE** query will delete the table’s record based on the specified condition. Omitting the **WHERE** clause will delete all the data/records from the targeted table.

This write-up will explain all the basics of the Postgres **DELETE** query with the help of some examples. So, let’s begin!

 **How to Use DELETE Query in PostgreSQL?**

You have to follow the below-mentioned syntax to use the **DELETE** query in the PostgreSQL:
    
    
    DELETE FROM tab_name
    WHERE [condition];

Here, in the above syntax:

\- tab_name represents a table whose record will be deleted.

\- condition represents a criterion based on which the table’s record will be deleted.

\- A single or a group of conditions can be used in the WHERE clause using the Boolean Operators i.e. AND and OR.

Now, let’s jump into the practical implementation of the DELETE Query.

 **How to Delete a Single Row in PostgreSQL using the DELETE Query?**

We will understand the working of the DELETE query step-by-step:

 **Step 1: Retrieve the Table Details Using SELECT Query**

We have already created a table **“student_details”**. Let’s run the **SELECT** query to see all the details of the **“student_details”** table:
    
    
    SELECT * FROM student_details;

The above figure signifies that the **“student_details”** table has ten rows. Suppose we need to delete the student record whose id is 8.

 **Step 2: Delete a Record Using DELETE QUERY**

Utilize the **WHERE** clause with the **DELETE** Query to delete a single record from the selected table. Within the WHERE clause, specify a condition based on which the selected record will be deleted:
    
    
    DELETE FROM student_details
    WHERE student_id = 8;

The output shows that one record has been deleted successfully from the selected table.

 **Step 3: Verify the Deleted Record Using SELECT QUERY**

Run the SELECT query to retrieve the table details:
    
    
    SELECT * FROM student_details;

The output authenticates that the student having id 8 has been deleted from the student_details table.

 **How to Delete Several Rows in Postgres using the DELETE Query?**

In PostgreSQL, **IN** operator can be used in the WHERE clause of the DELETE query to delete multiple rows.

 **Step 1: Delete the Multiple Rows Using DELETE Query**

Let’s run the **DELETE** command with the aid of the WHERE clause and **IN** operator to delete multiple rows of the table:
    
    
    DELETE FROM student_details
    WHERE student_id IN (2, 4);

The above snippet shows that two rows have been deleted from the studend_details table.

 **Step 2: Verify the Rows Deletion Using Select Query**

Execute the **SELECT** query to see all the rows of the **student_detail** table:
    
    
    SELECT * FROM student_details;

The output clarifies that two students having id 2 and 4 have been deleted from the studend_details table.

 **How to Delete All Rows in PostgreSQL using the DELETE Query?**

Omitting the WHERE clause allows us to delete all rows of the selected table. Follow the below-given steps to delete all the rows of the selected table:

 **Step 1: Execute the DELETE Query to Delete All Rows of the Table**

Run the below-given query to delete all the rows of the student_details table:
    
    
    DELETE FROM student_details;

The output confirms that all six rows of the student_details table have been deleted successfully.

 **Step 2: Verify the Rows Deletion Using SELECT Query**
    
    
    SELECT * FROM student_details;

The above snippet verifies that all the rows of the student_details table have been deleted.

 **RETURNING Clause in Postgres DELETE Query**

In **PostgreSQL** , the **DELETE** query can accept a **RETURNING** clause that returns the deleted rows. The syntax of the **DELETE** query with the **RETURNING** clause will look like this:
    
    
    DELETE FROM tab_name
    WHERE [condition]
    RETURNING *;

The **RETURNING** clause will come after the WHERE clause. Let’s run the following query to get a profound understanding of the **RETURNING** clause:
    
    
    DELETE FROM student_details
    WHERE student_id = 6
    RETURNING *;

The above snippet verifies that the RETURNING clause returns the deleted row.

From the examples discussed in this write-up, we can conclude that the **DELETE** query can be used with or without the **WHERE** clause to delete a single, multiple, or all the rows of a specific table.

 **Conclusion**

In PostgreSQL, the **DELETE** query is used to delete a single, multiple, or all the rows of a specific table. In the **DELETE** query, the WHERE clause is used to specify a single or a group of conditions to delete a specific record of a table. Skipping the WHERE clause will delete all the rows of the targeted table. This write-up considered multiple scenarios to explain the working of the Postgres DELETE query in a better way.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-delete-query-in-postgresql/)

---

# How to Use Update Query in PostgreSQL

> In PostgreSQL, the UPDATE query is used with the assistance of the SET clause to update or modify the table’s record/data.

In PostgreSQL, the **UPDATE** query is used with the assistance of the **SET** clause to update/modify the table’s record. In PostgreSQL, different clauses like WHERE, RETURNING, etc., can be used with the **UPDATE** query to achieve different functionalities. The [WHERE](<https://commandprompt.com/education/how-to-use-where-clause-in-postgresql/>) clause is used with the **UPDATE** command to modify the record of a specific row. In the WHERE clause, you can specify several conditions with the aid of [AND and OR](<https://commandprompt.com/education/how-to-use-and-or-operators-in-postgresql/>) operators. In PostgreSQL, omitting the WHERE clause will update the whole table.

This post is going to explain the working of the Postgres **UPDATE** query using some examples. So, let’s begin!

 **How to Use UPDATE Query in PostgreSQL?**

Let’s consider the following syntax to get a basic understanding of the UPDATE query in PostgreSQL.
    
    
    UPDATE tab_name  
    SET col_1 = val_1,  
    col_2 = val_2,
    ...  
    col_N = val_N
    WHERE  
    condition;

Consider the below-listed points to analyze the working of the **UPDATE** query:

● Write the **UPDATE** keyword followed by the table name to update the table’s record. In the above snippet, tab_name represents a table to be updated.

● The **SET** clause takes comma-separated column-value pairs. Specify the column names and their updated values.

● In the above-snippet, col_1, col_2, …, col_N are the columns to be updated, while val_1, val_2, …, val_N, are their respective values.

● **WHERE** clause takes a condition on the basis of which the selected table will be updated.

 **Example: How to Update a single row in PostgreSQL?**

We have an existing table named “team_members”. We will utilize the UPDATE query to update a specific row of the “team_members” table.

 **Step 1: Get the Table’s Details Using SELECT Query**

Let’s run the **SELECT** query to see all the data of the selected table:
    
    
    SELECT * FROM team_members;

 **Step 2: Update the Selected Row Using UPDATE Query**

Suppose we want to update the player name from “Paul” to “Marsh”. To do this, execute the below-given command:
    
    
    UPDATE team_members  
    SET player_name = 'Marsh'
    WHERE  
    player_id = 5;

Let’s analyze the working of the above-given query step-by-step:

\- team_members is the table to be updated.

\- Marsh is the value to be updated in the player_name column.

\- The updated value will be assigned to the player whose player_id = 5.

The error-free output verifies that the UPDATE query gets executed successfully.

 **Step 3: Verify the Updated Row Using the Select Command**

Let’s run the below-given command to verify whether the selected row has been updated or not:
    
    
    SELECT * FROM team_members;

The above snippet verified that the targeted row had been updated successfully.

 **RETURNING Clause in Postgres UPDATE Query**

In **PostgreSQL** , the **UPDATE** query can accept an optional clause named **RETURNING** that is used to return the updated rows. The syntax of the **UPDATE** query with the **RETURNING** clause will go like this:
    
    
    UPDATE tab_name
    SET col_1 = val_1,
      col_2 = val_2,
      ...
    WHERE condition
    RETURNING *;

 **RETURNING *** clause will return the updated rows.

 **Example: How to Use the RETURNING Clause With UPDATE Query in PostgreSQL?**

Suppose we want to update and return the player_name whose id is 8. To do this, let’s execute the **UPDATE** query along with **RETURNING** clause:
    
    
    UPDATE team_members  
    SET player_name = 'Joe'
    WHERE player_id = 8
    RETURNING *;

The output clarifies that the **RETURNING** clause succeeded in returning the updated row.

 **Conclusion**

 **PostgreSQL** allows us to update the record of any existing table using the **UPDATE** query. In PostgreSQL, different clauses like WHERE, RETURNING, etc., can be used with the **UPDATE** query to serve different purposes. **WHERE** clause takes a condition based on which the selected table will be updated. While the **RETURNING** clause returns the updated record. This post explained several use cases of the **UPDATE** query with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-update-query-in-postgresql/)

---

# How to Use Select Query in PostgreSQL

> The SELECT statement is used to fetch one or more columns of a table. It returns a resultant table which is known as the result set or result table.

**PostgreSQL** offers a very useful query named **SELECT** that retrieves the record of an individual or multiple tables. The **SELECT** statement fetches the record from a targeted table of a database and returns the resultant table. On successful execution, the **SELECT** statement returns a resultant table entitled as **result table or** **result set**.

A wide range of clauses can be used with the Postgres **SELECT** statement. For example, WHERE, ORDER BY, HAVING, INNER JOIN, CROSS JOIN, UNION, and so on. All these clauses serve different functionalities and provide more ease/flexibility.

In this write-up, we will discuss the basics of **SELECT** query; however, we will explain the working of each clause in the later tutorials. So, let’s get started!

 **How Does the SELECT Statement Work in PostgreSQL?**

In **PostgreSQL** , you can fetch the record of an individual, multiple, or all column using the **SELECT** statement.

 **How to Select the Data From a Single Column in PostgreSQL?**

The syntax given below shows how to fetch the record of a single column in **PostgreSQL** :
    
    
    SELECT
      col_name
    FROM
      tab_name;

Here is the step-by-step description of the above-given syntax:

\- **SELECT** is a statement used to select/target an individual or a list of columns.

\- **col_name** is the column to be fetched/selected.

\- **FROM** is a clause that determines which table to select.

\- **tab_name** is the targeted table.

 **Example: How to Select a column’s record in PostgreSQL?**

Follow the below-given step-wise instructions to select a single column in **PostgreSQL** :

 **Step 1: Select a Database**

Open **pgAdmin,** and select the desired database from the available databases:

We selected the “example” database.

 **Step 2: Select a Table**

Explore the tables available within the **“example”** database and select the desired table under the **“Schemas”** section:

The above snippet shows that there are seven tables available within the example database. We selected the **“team_info”** table.

 **Step 3: Check the Available Columns**

Click on the selected table and select the **“Columns”** section to see all the columns of that table:

The above snippet shows that the **“team_info”** table has three columns i.e. **“team_id”** , **“team_name”** , and **“team_ranking”**.

 **Step 4: Fetch the Column’s Data**

Suppose we need to fetch the data of the **“team_name”** column. To do this, right-click on the **“Columns”** section and select the **“Query Tool”** :

Now, execute the **SELECT** query to fetch the data of the **“team_name”** column:

The output shows that the **“SELECT”** query succeeded in fetching the data of the **“team_name”** column.

 **How to Select the Data From Multiple Columns in PostgreSQL?**

Let’s have a look at the below-given syntax to understand how to select more than one column in **PostgreSQL** :
    
    
    SELECT
      col_1, col_2, col_3, ..., col_N
    FROM
      tab_name;

Here, **col_1, col_2, col_3, ..., col_N** are the columns to be fetched.

 **Example: How to Fetch More Than One Column in PostgreSQL?**

Suppose we have to fetch the record of the **“team_name”** and **“team_ranking”** columns. To do this, we will run the **“SELECT”** command using the comma-separated syntax:
    
    
    SELECT team_name, team_ranking
    FROM
    team_info;

The output verified that the **SELECT** query successfully fetched the record of the **“team_name”** and **“team_ranking”** columns.

 **How to Select the Data From ALL Columns in PostgreSQL?**

Follow the below syntax to fetch the record of all columns in **PostgreSQL** :
    
    
    SELECT * FROM tab_name;

Specifying an asterisk ***** with the **SELECT** statement will provide the data of all columns.

 **Example: How to Fetch All Columns Data in PostgreSQL?**

Run the below-given query to fetch all the columns of a table:
    
    
    SELECT * FROM team_info;

The output shows that this time **SELECT** query returned all the columns of the selected table.

 **Conclusion**

The **SELECT** statement is used to fetch a single or more than one column of a table. On successful execution, the **SELECT** statement returns a resultant table entitled as **result table or** **result set**. In **PostgreSQL** , asterisk * is used with the **SELECT** statement to fetch the data of all the columns. This write-up explains the working of the **SELECT** query in **PostgreSQL** using some relevant examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-select-query-in-postgresql/)

---

# How to Use AND & OR Operators in PostgreSQL

> In PostgreSQL, the AND and OR operators are used to combine more than one condition and are referred to as conjunctive, logical, or boolean operators.

**PostgreSQL** offers three logical operators, i.e., **AND** , **NOT,** and **OR**. Among them, the most frequently used operators are **AND** and **OR** operators. Both these operators are used to combine different conditions hence also referred to as conjunctive operators.

These operators are also known as Boolean operators. The **AND** and **OR** operators test the specified condition and return a TRUE, FALSE, or NULL value. In this post, you will learn the working of each operator with the help of suitable examples. So, let’s get started!

 **How to Use AND Operator in PostgreSQL?**

In **PostgreSQL** , the [WHERE](<https://commandprompt.com/education/how-to-use-where-clause-in-postgresql/>) clause is used to specify a condition in a statement. The **AND** operator allows us to specify/combine multiple conditions.

Let’s consider the below snippet for a profound understanding of the Postgres **AND** operator:
    
    
    SELECT col_1, col_2, ..., col_N
    FROM tab_name
    WHERE [condition_1] AND [condition_2]... AND [condition_N];

Let’s analyze the working of the above snippet:

● **SELECT** is a statement used to fetch the data of single or multiple tables.

● col_1, col_2, …, col_N are the columns whose data will be fetched using the SELECT statement.

● tab_name is the targeted table, and col_1, col_2, …, col_N belong to the tab_name table.

● **WHERE** is a clause that takes a condition or group of conditions based on which the retrieved data will be filtered.

● **AND** is a logical operator that combines multiple conditions.

 **How Does AND Operator Work in PostgreSQL?**

The below-listed points will let you understand the working of the **AND** operator in **PostgreSQL** :

● **AND** operator returns true only if all conditions are true.

● If any of the conditions didn't match the criteria, then the **AND** operator will return false.

● It returns a NULL value if all the conditions return NULL.

 **Example: How to Combine Multiple Conditions in PostgreSQL using AND Operator?**

We have already created a table named **“student_details”**. Let’s execute the **SELECT** statement to see the table’s record:
    
    
    SELECT * FROM student_details;

The output shows that there are ten students; six males and four females. Some students are under twenty years while others are above twenty years.

Suppose we need to fetch only those male students whose age is above 20. To do so, we will utilize the **AND** operator with the **SELECT** command:
    
    
    SELECT * FROM student_details
    WHERE student_age => 20 AND student_gender = 'M';

Let’s analyze how the above query works:

● The **SELECT** statement will fetch all the records from the student_details table.

● The **WHERE** clause will filter records based on the specified conditions.

● The **AND** operator will return the filtered data if both conditions are true. This means the student must be male and at least 20 years old.

The output clarifies that the result-set shows only those students who satisfied both conditions.

 **How to Use OR Operator in PostgreSQL?**

The **OR** operator is used in the **WHERE** clause to combine multiple conditions. For the **OR** operator, if one or more conditions are true, the whole condition will be considered true.

The below-given syntax will explain the working of the Postgres **OR** operator in a better way:
    
    
    SELECT col_1, col_2, ..., col_N
    FROM tab_name
    WHERE [condition_1] OR [condition_2]... OR [condition_N];

Let’s analyze the working of the above snippet:

● **SELECT** statement fetches the data of single or multiple tables.

● col_1, col_2, …, col_N are the columns whose data will be fetched using the SELECT statement.

● tab_name represents a table whose record will be fetched using the SELECT statement.

● **WHERE** is a clause that takes a condition or group of conditions based on which the retrieved data will be filtered.

● **OR** is a logical operator that combines multiple conditions.

 **How Does OR Operator Work in PostgreSQL?**

Consider the following points to understand the working of the **OR** operator in **PostgreSQL** :

● **OR** operator returns true if one or more conditions are true.

● It returns false if all conditions don’t match the specified criteria.

 **Example: How to Combine Multiple Conditions in PostgreSQL using OR Operator?**

Let’s consider the below-given query to understand how the **OR** operator works in **PostgreSQL** :
    
    
    SELECT * FROM student_details
    WHERE student_age < 20 OR student_gender = 'F';

● The **SELECT** statement will fetch all the records from the student_details table.

● The **WHERE** clause will filter records based on the specified conditions.

● The **OR** operator will return the filtered data if at least one condition satisfies the criteria.

The output shows that the **OR** operator includes all those records that fulfill at least one condition. This is how the **OR** operator works in **PostgreSQL**.

 **Conclusion**

In **PostgreSQL** , the **AND** and **OR** operators combine more than one condition in the **WHERE** clause. The **AND** operator returns true if all the conditions satisfy the given criteria, while the **OR** operator returns true if at least one condition satisfies the specified criteria. This write-up explained the working of Postgres **AND** and **OR** operators with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-and-or-operators-in-postgresql/)

---

# How to Use WHERE Clause in PostgreSQL

> In PostgreSQL, the WHERE clause is used to filter the results of different statements such as SELECT, DELETE, UPDATE, etc.

In **PostgreSQL** , the **WHERE** clause is used to filter the results of different statements such as SELECT, DELETE, UPDATE, etc. In PostgreSQL, the **WHERE** clause specifies a condition for retrieving the table's record. Within the specified condition, different operators can be used, such as AND, OR, etc. These operators determine the filtration criteria of the **WHERE** clause.

In this post, you will learn different use cases of the **WHERE** clause within the SELECT statement.

 **How to Use WHERE clause in PostgreSQL?**

In **Postgres** , the **WHERE** clause takes a condition and checks it. If the specified condition is true, then the **WHERE** clause will return a specific value or set of values from the targeted table.

Following will be the basic syntax of the **WHERE** clause:
    
    
    SELECT col_1, col_2, ..... col_N  
    FROM tab_name
    WHERE [condition]

Let’s understand the syntax of the WHERE clause step-by-step:

● **SELECT** command will select a single column or a list of columns.

● **FROM** clause specifies a table or list of tables to be targeted.

● **tab_name** is a table to be selected.

● **WHERE** clause takes a condition and checks if it's true or not. It comes after the FROM clause of any statement.

● **condition** represents a single Boolean expression or a combination of several expressions.

 **Example # 1: Select the Players Whose Age is Greater Than 25**

Follow the below-given steps to understand the working of the **WHERE** clause in **PostgreSQL** :

 **Step 1: Describe the Targeted Table Using Select Command**

Let’s execute the SELECT command followed by an asterisk to retrieve all the columns of the “team_member” table:
    
    
    SELECT * FROM team_members;

The above snippet shows that the team_members table has eight players. Some players are above 25, and others are under 25 years.

 **Step 2: Filter Players Above 25 Using WHERE Clause**

Execute the **SELECT** query with the collaboration of the **WHERE** clause to fetch the name of only those players whose age is above 25:
    
    
    SELECT
      player_name, player_age
    FROM
      team_members
    WHERE
      player_age > 25;

Here, we utilized the greater than sign in the **WHERE** clause to fetch the record of only those team_members whose age is greater than 25:

The output verifies that the **WHERE** clause returns the filtered data.

 **Example # 2: Select the Players Whose Age is Equal to 22 or Whose Name is John**

We will use the **OR** operator in the **WHERE** clause to fetch the player's name whose age is equal to 22 or whose name is John:
    
    
    SELECT * FROM team_members
    WHERE player_age = 22 OR player_name = 'John';

The output clarifies that the **WHERE** clause retrieves the filtered data.

 **Example # 3: Select the Players Whose Name is “John” and Whose Age is Greater than 25**

In **PostgreSQL** , the **AND** operator returns true if both the conditions satisfy the specified criteria. In this example, we will use the **AND** operator, which will return the data of only those players who satisfy both conditions:
    
    
    SELECT * FROM team_members
    WHERE player_name = 'John' AND player_age > 25;

This is how you can use the **AND** operator in the **WHERE** clause.

 **Example # 4: Select the Players Whose Name Starts With ‘J’**

In **PostgreSQL** , the **LIKE** operator is used for pattern matching. In this example, we will use the **LIKE** operator with the **WHERE** clause to filter the players whose name starts with the “ **J** ”:
    
    
    SELECT * FROM team_members
    WHERE player_name LIKE 'J%';

As shown in the output, the **WHERE** clause with the aid of the **LIKE** operator fetched only those players whose name starts with the **“J”**.

 **Example # 5: Select the Players Whose Name is Not Equal to John**

In PostgreSQL, **“ <>”** and **“!=”** symbols are used to check the non-equal values:
    
    
    SELECT * FROM team_members
    WHERE player_name != 'John';

This output confirms that the **WHERE** clause fetched all players except “John”.

From the examples, we can conclude that the **WHERE** clause filters the rows returned by the SELECT statement. That’s all you need to know about the Postgres **WHERE** clause.

 **Conclusion**

In PostgreSQL, the **WHERE** clause can be used within different queries/statements such as SELECT, DELETE, UPDATE, etc. The **WHERE** clause filters the results on the basis of different conditions. The condition represents a single Boolean expression or set of multiple Boolean expressions. In PostgreSQL, different operators can be used within the specified condition, such as AND, OR, !=, >, etc. This write-up considered some examples to summarize the basics of the Postgres **WHERE** clause with the SELECT query.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-where-clause-in-postgresql/)

---

# How to Rename the columns of a table in PostgreSQL

> PostgreSQL provides a RENAME COLUMN clause that is used with the collaboration of ALTER TABLE command to rename a column.

**PostgreSQL** provides a **RENAME COLUMN** clause that is used with the collaboration of **ALTER TABLE** command to rename a column. The **RENAME COLUMN** command allows us to rename a single or multiple columns. **PostgreSQL** doesn’t provide the **“IF EXISTS”** option for the **“RENAME COLUMN”** command.

This write-up will explain the below-listed use-cases of the **RENAME COLUMN** command in **PostgreSQL**.

● How to Use RENAME COLUMN Command to Rename Columns in PostgreSQL?

● How to Rename a Column That Has Some Dependent Objects?

● How to Use RENAME COLUMN Command to Rename Several Columns in PostgreSQL?

So, let’s get started.

 **How to Use RENAME COLUMN Command to Rename Columns in PostgreSQL?**

The **“RENAME COLUMN”** command can also be used as **“RENAME”**. The **RENAME COLUMN** command gets executed with the assistance of **ALTER TABLE** command, as shown in the following syntax:
    
    
    ALTER TABLE tab_name
    RENAME COLUMN old_col_name TO new_col_name;

Let’s understand how the above snippet works:

\- **ALTER TABLE** is a clause used to alter or modify a table.

\- **tab_name** is a table to be altered/modified.

\- **RENAME COLUMN** is a command that renames a column.

\- **old_col_name** represents a column to be renamed.

\- **new_col_name** represents new/modified column name.

 **Example # 1: How to Rename a Table’s Column in Postgres?**

Follow the below-given steps to learn how **RENAME COLUMN** command works in **PostgreSQL** :

 **Step 1: Choose a Database**

Open the **SQL SHELL** and establish a connection with a database using the **“\c”** command:
    
    
    \c example;

The output shows that we are successfully connected to the **“example”** database.

 **Step 2: Select a Table**

Run the **“\dt”** command to check the available tables within the connected database:
    
    
    \dt;

Select a table of your choice from the available tables.

 **Step 3: Describe a Table**

Let’s run the **“\d”** command followed by the table name to see all the columns present in the selected table:
    
    
    \d staff_details;

 **Step 4: Rename the Column**

Suppose we have to rename the **“staff_location”** column to **“staff_address”**. Execute the **“RENAME COLUMN”** command to rename the selected column:
    
    
    ALTER TABLE staff_details
    
    
    RENAME COLUMN staff_location TO staff_address;

 **Step 5: Verify the Column Name**

Let’s execute the “\d” command followed by the table name to verify whether the column name has been altered or not:
    
    
    \d staff_details;

The output verified that the **“staff_location”** column had been renamed to **“staff_address”**.

 **How to Rename a Column That Has Some Dependent Objects?**

Renaming a column that has dependent objects such as foreign keys, views, stored procedures, etc., will implement the modifications to its dependent objects as well.

 **Example: How to Rename a Foreign Key in PostgreSQL?**

Consider the below-given steps to rename a column on which some other objects are dependent:

 **Step 1: Fetch the tables**

Firstly, we will fetch the **“article_details”** and **“author_details”** tables using the **“\d”** command:

The above snippet shows that the **“article_id”** is a foreign key in the **“author_details”** table. So, renaming the **“article_id”** column in the **“article_details”** table will automatically rename the **“article_id”** column in the **“author_details”** table.

 **Step 2: Rename the Column**

Let’s run the below-given command to rename the **“article_id”** column to **“id”** :
    
    
    ALTER TABLE article_details
    RENAME COLUMN article_id TO id;

 **Step 3: Verify the Column Name**

Type **“\d”** command followed by the table name (i.e., **“article_detials”** ) to see the changes made in the selected table:
    
    
    \d article_detials;

The above snippet clarified that the **“article_id”** had been renamed to **“id”** in the selected table as well as in the dependent objects/tables.

 **How to Use RENAME COLUMN Command to Rename Several Columns?**

Follow the semi-colon separated syntax to rename several columns in **PostgreSQL** :
    
    
    ALTER TABLE tab1_name 
    RENAME COLUMN old_col_name TO new_col_name;
    
    
    
    ALTER TABLE tab2_name
    RENAME COLUMN old_col_name TO new_col_name;

 **Example: How to Rename Several Columns in Postgres?**

In this example, firstly, we will rename the **“id”** column of the **“article_details”** table to **“article_id”**. Next, we will modify the name of the **“author_id”** column to **“a_id”** :
    
    
    ALTER TABLE article_details 
    RENAME COLUMN id TO article_id;
    
    
    
    ALTER TABLE author_details
    RENAME COLUMN author_id TO a_id;

Let’s execute this query from the pgAdmin’s query tool:

The output verified that the selected tables had been altered successfully.

 **Conclusion**

 **PostgreSQL** provides a **RENAME COLUMN** clause that is used with the collaboration of **ALTER TABLE** command to rename a column. **PostgreSQL** doesn’t provide the **“IF EXISTS”** option for the **“RENAME COLUMN”** command. So, Postgres will throw an error if the targeted column doesn’t exist in the selected table. This write-up considered multiple examples to explain the working of the **“RENAME COLUMN”** clause.

---
[View this page online](https://www.commandprompt.com/education/how-to-rename-the-columns-of-a-table-in-postgresql/)

---

# How to Change/Modify Column Type in PostgreSQL

> In PostgreSQL, the “ALTER TABLE” and “ALTER COLUMN” commands, along with the TYPE Keyword, are used to change/modify the data type of any specific column.

In **PostgreSQL** , the **“ALTER TABLE”** and **“ALTER COLUMN”** commands, along with the **TYPE** Keyword, are used to change/modify the data type of a column. For example, integer to character, text to varchar, and so on. In **PostgreSQL** , we can change the data type of one or more than one column using the **“ALTER TABLE”** and **“ALTER COLUMN”** commands.

This blog will present a step-by-step guide on changing the column’s data type. So, without any further delay, let’s start.

 **How to Change/Update the Column’s Data Type in Postgres?**

The below-given syntax will assist you in changing the data type of any particular column:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_name TYPE new_data_type;

Let’s analyze the above-given syntax step-by-step:

\- **tab_name** represents a table whose column will be altered.

\- **col_name** represents the column to be altered.

\- **TYPE** is a keyword.

\- **new_data_type** represents the altered/modified data type of the selected column.

 **Example: How to Change/Modify the Column’s Type From int to text?**

You have to follow the below-listed procedure to change the column’s data type:

 **Step 1: Access a Database**

Firstly, open SQL SHELL and type the “\c” command followed by the database name to make a connection with the selected database:
    
    
    \c example;

 **Step 2: Available Tables**

Once you are connected to the targeted database, type the **“\dt”** command to see the list of available tables in that database:
    
    
    \dt;

 **Step 3: Describe the Table**

Select a table and run the following command to see the structure of the selected table:
    
    
    \d team_info;

 **Step 4: Change Column Type**

Execute the below-given command to change the data type of the **“team_rating”** column from **“integer”** to **“character”** :
    
    
    ALTER TABLE team_info
    ALTER COLUMN team_rating TYPE VARCHAR(30);

 **Step 5: Verify the Column Type**

Let’s run the **“\d”** command followed by table name to see the changes made to the selected table:
    
    
    \d team_info;

The output authenticates that the data type of the **“team_rating”** column has been updated to the character type.

 **How to Change/Modify the Type of Several Columns With a Single Command?**

Follow the comma-separated syntax to change the data type of more than one column using a single query:
    
    
    ALTER TABLE tab_name
    ALTER COLUMN col_1 TYPE new_data_type,
    ALTER COLUMN col_2 TYPE new_data_type;

 **Example: How to update data types of several columns using a single command in PostgreSQL?**

From the snippet shown in step 4 of the previous example, we can observe that the **“team_rating”** and **“team_lead”** columns have a “character” data type. Suppose we have to change both columns' data types from character to text. To do so, we have to follow the below-given process:

 **Step 1: Change the Column Type**

We can change the type of selected columns by executing the following query/command:
    
    
    ALTER TABLE team_info
    ALTER COLUMN team_rating TYPE TEXT,
    ALTER COLUMN team_lead TYPE TEXT;

 **Step 2: Verify the Column Type**

Let’s execute the below-given command to check and verify the data type of the selected columns:
    
    
    \d team_info;

The snippet given above proved that the data type of the **“team_rating”** and **“team_lead”** columns have been successfully updated to the “text” data type.

 **Conclusion**

In **PostgreSQL** , the **“ALTER TABLE”** and **“ALTER COLUMN”** commands are used along with the **TYPE** Keyword to change/modify the data type of a column. These commands allow us to change/modify the type of an individual or multiple columns simultaneously. This post explained how to change the column type in **PostgreSQL** with the help of suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-changemodify-columns-of-a-table-in-postgresql/)

---

# How to Drop Columns From a Table in PostgreSQL

> In PostgreSQL, the DROP COLUMN command is used with the collaboration of the ALTER TABLE command to drop single or multiple columns.

In **PostgreSQL** , the **DROP COLUMN** command is used to drop an individual column or multiple columns. The **DROP COLUMN** statement in **PostgreSQL** is used with the collaboration of the **ALTER TABLE** command. In **PostgreSQL,** some options like **“CASCADE”** and **“IF NOT EXISTS”** can be used with the **DROP COLUMN** command to achieve different functionalities.

 **How to Drop/Delete a Single Column from a Table in PostgreSQL?**

The syntax given below is used to drop a single column from a table in **PostgreSQL** :
    
    
    ALTER TABLE tbl_name  
    DROP COLUMN col_name;

Here, **ALTER TABLE** is a command, and **tbl_name** represents a table to be modified. The **DROP COLUMN** is a command, and **col_name** represents a column to be dropped **.**

 **Example# 1: How to Drop/delete a Single Column in Postgres?**

Let’s follow the below-given guidelines to get a profound understanding of the **DROP COLUMN** command.

 **Step1: Select a Table**

Open the **pgAdmin** , and select a table:

From the available tables, we select the **“student_details”** table.

 **Step 2: Drop the Column**

Select a column that you want to drop from the targeted table:

Let’s say you have to drop the **“student_age”** column. To do so, execute the following command:
    
    
    ALTER TABLE student_details  
    DROP COLUMN student_age;

 **Step 3: Verify the Table Alteration**

Let’s refresh the targeted table and then click on the “Columns” section to see the available columns in the selected table:

The above snippet shows that the **“student_age”** column has been dropped successfully.

 **Example# 2: Drop a Column That Does Not Exist**

In **PostgreSQL** , if someone tries to drop a column that does not exist, then an error will occur:
    
    
    ALTER TABLE student_details  
    DROP COLUMN student_age;

The above snippet proved that an error occurred when we tried to drop a column that didn’t exist.

 **Example# 3: How to Avoid the “Relation Doesn’t Exist” Error?**

Use the **“IF EXISTS”** parameter along with the **“DROP COLUMN”** command to avoid such an error:
    
    
    ALTER TABLE student_details  
    DROP COLUMN IF EXISTS student_age;

This time, the query returned successfully, and the **“DROP COLUMN”** command shows a notice instead of throwing an error.

 **How to Drop/Delete Multiple Columns From a Table in PostgreSQL?**

In **Postgres** , the **DROP COLUMN** command can be used with the comma-separated syntax to drop more than one column:
    
    
    ALTER TABLE tbl_name  
    DROP COLUMN col1,
    
    
    DROP COLUMN col2,
    DROP COLUMN col3;

In this way, you can drop as many columns as you want simultaneously.

 **Example: How to Delete/Drop Multiple Columns in Postgres?**

Follow the below-given procedure to delete the multiple columns simultaneously:

 **Step 1: Drop the Unwanted Columns**

Let’s execute the following query to drop the **“student_roll”** and **“student_name”** columns from the **“student_details”** table:
    
    
    ALTER TABLE student_details  
    DROP COLUMN student_roll,
    DROP COLUMN student_name;

 **Step 2: Verify the Table Alteration**

Let’s execute the following command from the **SQL SHELL** to verify the modifications made in the **“student_details”** table:
    
    
    \d student_details;

The above snippet proved that the selected columns had been dropped successfully.

 **What is CASCADE and How to Use it in PostgreSQL?**

In **PostgreSQL** , attempting to delete a column on which other columns/objects depend will cause an error. We can use the **“CASCADE”** option along with the **“DROP COLUMN”** command to drop/delete the targeted column with all the associated objects. Following will be the basic syntax of the **“CASCADE”** option:
    
    
    ALTER TABLE tbl_name
    DROP COLUMN col_name CASCADE;

 **How to Get the Structure of a Table in PostgreSQL?**

Let’s execute the **“\d”** command from the SQL SHELL(psql) to get the details of the **“author_details”** table:
    
    
    \d author_details;

The above snippet shows that the **“author_id”** is used as a foreign key in the **“article_details”** table. This means the **“article_details”** table depends on the **“author_id”** column of the **“author_details”** table.

 **Example# 1: “Can’t drop a column” Error in Postgres**

Run the following query to drop the **“author_id”** column of the **“author_details”** table:
    
    
    ALTER TABLE author_details  
    DROP COLUMN author_id;

The output shows that we encountered an error **“cannot drop column author_id”**. This is because some other objects depend on the **“author_id”** column.

 **Example# 2: How to Drop/Delete the Dependent Columns?**

Let’s execute the following query to drop the **“author_id”** column and the objects associated with that column:
    
    
    ALTER TABLE author_details
    DROP COLUMN author_id CASCADE;

The output clarified that the **“author_details”** table has been altered successfully.

 **Conclusion**

In **PostgreSQL** , the **DROP COLUMN** statement is used with the collaboration of **ALTER TABLE** clause to drop/delete the columns. The **DROP COLUMN** command can accept some options such as **“CASCADE”** and **“IF NOT EXISTS”**. These options facilitate us with different functionalities. This write-up explained the working of the **DROP COLUMN** command with the help of examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-columns-from-a-table-in-postgresql/)

---

# How to Add Columns to a Table in PostgreSQL

> In PostgreSQL, the ADD COLUMN command/statement along with the ALTER TABLE clause is used to add single or multiple columns to a table.

In **PostgreSQL** , the **ADD COLUMN** command along with the **ALTER TABLE** clause is used to add/insert one or more than one column to an existing table. The **ADD COLUMN** statement enables us to add constraints to a column in **PostgreSQL,** such as **NOT NULL** , **UNIQUE** , etc. So, let’s learn how the **ADD COLUMN** statement works in **PostgreSQL** with the help of some examples.

 **How to Add/Insert a New Column to a Table in Postgres?**

You have to follow a specific syntax to add a new column to any particular table that already exists:
    
    
    ALTER TABLE tbl_name  
    ADD COLUMN col_name data_type;

Let’s discuss the above-given syntax stepwise:

\- **ALTER TABLE** is a command/clause used to modify/alter a table.

\- **tbl-name** is a user-defined table name.

\- **ADD COLUMN** inserts one or more than one column to a table.

\- **col_name** represents the column to be altered.

\- **data_type** represents the type of targeted column such as integer, character, etc.

 **Example: How to add a single column to an already existing table?**

Let’s execute the **ADD COLUMN** command from the **pgAdmin** to learn how it works in **PostgreSQL** :

 **Step 1: Select the Desired Table**

Firstly, open the **pgAdmin** , select the database, find the available **“Tables”** under the **“Schemas”** section, and select the desired one:

Let’s assume we want to alter the **“team_info”** table.

 **Step 2: Open the Query Tool**

From the menu bar, select the **Query Tool** under the **Tools** tab as shown in the below snippet:

 **Step 3: Add a New Column**

Currently, we have three columns in the **“team_info”** table. Let’s execute the **ADD COLUMN** command to add a new column named **“team_lead”** in the **“team_info”** table:
    
    
    ALTER TABLE team_info  
    ADD COLUMN team_lead VARCHAR;

Now press **F5** or click on the **“Execute/Refresh”** button to run the **ADD COLUMN** command:

The output shows that the **“team_info”** table has been altered successfully.

 **Step 4: Verify the Working of ADD COLUMN Command**

Right-click on the desired table and select the **“Refresh”** option to see the modifications in the selected table:

Once you click on the **“Refresh”** option, consequently, the selected table will be updated:

The above-snippet clarified that the **“team_lead”** column had been added to the **“team_info”** table successfully.

 **How to Add More Than One Column to a Table in Postgres?**

As we have discussed earlier, the **ADD COLUMN** command can be used to add multiple columns to any specific table. Now, we will learn it practically.

 **Syntax**

The below-given syntax will be used to add multiple columns to a table in **PostgreSQL** :
    
    
    ALTER TABLE tbl_name
    ADD COLUMN first_col data_type constraint,
    ADD COLUMN second_col data_type constraint, 
    ...
    ADD COLUMN nth-col data_type constraint;

The above snippet shows that we can add multiple columns to a table using comma-separated syntax.

 **Example: How to Add Multiple Columns to a Particular Table in Postgres?**

Follow the below-listed instructions to add multiple columns to a table:

 **Step 1: Select the Table**

Choose a table you want to alter; let’s say we want to modify the **“staff_details”** table:

The above snippet shows that the **“staff_details”** table has two columns.

 **Step 2: Add Multiple Columns**

Let’s execute the **“ADD COLUMNS”** statement to add a couple of more columns in the **“staff_details”** table:
    
    
    ALTER TABLE staff_details
    ADD COLUMN staff_email VARCHAR,
    ADD COLUMN staff_location VARCHAR;

In the above-given query, the **ALTER TABLE** command is used to alter/modify the **“staff_details”** table. While the **ADD COLUMN** command is used to add the **“staff_email”** and **“staff_location”** columns in the **“staff_details”** table:

 **Step 3: Verify the Working of ADD COLUMN Command**

Refresh the targeted table and click on the Columns section to see the available columns in the selected table:

The above-snippet verified that the **“staff_email”** and **“staff_location”** columns had been added to the **“staff_details”** table successfully.  


 **How to Add Columns With Constraints in Postgres?**

In **Postgres** , we can add a column with constraints such as **NOT NULL, DEFAULT, UNIQUE,** etc. Here is the basic syntax of adding a column with constraints in **Postgres** :
    
    
    ALTER TABLE tbl_name
    ADD COLUMN col_name data_type constraints;

Consider the below-listed points for a detailed understanding of the above-given syntax:

\- **The ALTER TABLE** command modifies a table.

\- **tbl-name** is the table to be altered.

\- **ADD COLUMN** adds/inserts one or more than one column to the targeted table.

\- **data_type** represents the type of targeted column such as integer, character, etc.

\- **Constraints** represent a rule to be implemented on a column.

\- **col_name** represents a column to be added to a table with constraints.

 **Example: How to Add a Column with constraints in Postgres**

Follow the below-listed steps to understand how to insert a new column with a constraint in **PostgreSQL** :

 **Step 1: Add DEFAULT Constraints**

Let’s suppose we want to add an **“is_illegable”** column with a default value **“false”**. To do so, we will utilize the **“DEFAULT”** constraint as shown in the below-given snippet:
    
    
    ALTER TABLE team_info
    ADD COLUMN is_illegible BOOLEAN default false;

The above-given query will add an **“is_illegible”** column in the **“team_info”** table. The **“is_illegible”** column has a Boolean data type with the default value **“false”** :

 **Step 2: Describe the Altered Table**

Run the **“\d”** command from the SQL SHELL ( **psql)** to verify the working of the **ADD COLUMN** command:
    
    
    \d team_info;

The output verified that the **“is_illegible”** column having a data type boolean with a default value false had been added to the **“team_info”** table.

 **Conclusion**

In **PostgreSQL** , the **ADD COLUMN** command/statement along with the **ALTER TABLE** clause is used to add single or multiple columns to a table. The **ADD COLUMN** command allows us to add new columns with constraints such as **DEFAULT** , **NOT NULL** , **UNIQUE** , etc. This write-up considered some examples to explain the working of the **ADD COLUMN** command in a better way.

---
[View this page online](https://www.commandprompt.com/education/how-to-add-columns-to-a-table-in-postgresql/)

---

# How to use the ALTER TABLE command in PostgreSQL

> In PostgreSQL, the ALTER TABLE command serves multiple functionalities on a table like adding a column, dropping a column, renaming a table/columns, etc.

In **PostgreSQL** , the **ALTER TABLE** command performs different functionalities on a table. For example, the **ALTER TABLE** statement can add, drop, or update the table columns. Moreover, it allows us to add or remove constraints to a table. So, all in all, we can say that the **ALTER TABLE** command is used to change/modify the table structure.

This write-up will explain the multiple use-cases of the **ALTER TABLE** command in **PostgreSQL.** So, let’s get started.

 **How to Add/Insert a Column in PostgreSQL?**

In **PostgreSQL** , the **ALTER TABLE** command/clause can be used to add columns to any specific table. To do so, follow the below-given syntax:
    
    
    ALTER TABLE tbl_name ADD col_name data_type;

\- Here, the **ALTER TABLE** command/statement is used to add a column in a table.

\- The **tbl-name** is the name of the targeted table.

\- **ADD** is a reserved keyword used to add/insert a column in a table.

\- **col_name** is a column name to be added to the targeted table, while **data_type** represents the column’s type.

 **Example: How to add a column with the ALTER TABLE command/statement?**

Follow the below-listed guidelines to learn how to add a new column in a table using **ALTER TABLE** :

 **Step 1: Connect to the Table**

Open the psql, and run the **“\c”** command to connect/access the desired table as shown below:
    
    
    \c example;

 **Step 2: Describe the Table**

Once you are connected to the targeted database, run the **“\d”** command to get all the necessary details about that table:
    
    
    \d team_details;

Here, **“\d”** is the command while “team_details” is the table to be described:

 **Step 3: Add a New Column**

Let’s assume you have to add a new column in the **“team_details”** table. To do so, you can run the **“ALTER TABLE”** command as follows:
    
    
    ALTER TABLE team_details ADD team_ranking int;

Here in the above snippet,

\- **ALTER TABLE** is a command.

\- **team_details** is the table name.

\- **ADD** is the reserved Keyword.

\- **team_ranking** is the column name, while **int** is the data type of that column.

So, on successful execution of the **“ALTER TABLE”** command, a new column named **“team_ranking”** of **“integer”** data type will be added to the table named **“team_details”**.

 **Step 4: Describe the Altered/Modified Table**

Let’s execute the **“\d”** command to verify that the targeted table has been altered successfully:
    
    
    \d team_details;

The above snippet verifies the working of the **“ALTER TABLE”** command.

 **How to Drop a Column in PostgreSQL?**

You have to follow the below-given syntax to drop a column using the **ALTER TABLE** command in **PostgreSQL** :
    
    
    ALTER TABLE tbl_name DROP col_name;

\- Here, the **ALTER TABLE** command/statement is used to drop a column from a table.

\- The **tbl-name** is the name of the targeted table.

\- **DROP** is a reserved keyword to drop/delete a specific column from the table.

\- **col_name** represents the column to be dropped.

 **Example: How to Use the ALTER TABLE Command to Drop a Column?**

Run the following command to drop/delete a column from any specific table:
    
    
    ALTER TABLE team_details DROP team_targets;

On successful execution of the **“ALTER TABLE”** command, a column named **“team_targets”** will be dropped from the **“team_details”** table:

Let’s verify the working of the **“ALTER TABLE”** command by executing the following command:
    
    
    \d team_details;

The output verified that the **“team_targets”** column had been dropped from the **“team_details”** table using the **“ALTER TABLE”** command.

 **How to Rename a Table in PostgreSQL?**

The **“ALTER TABLE”** command can be used along with the **“RENAME TO”** clause to rename a specific table:
    
    
    ALTER TABLE tbl_name RENAME TO modified_tbl_name;

In the above snippet,

\- **ALTER TABLE** is a command.

\- **RENAME** and **TO** are predefined clauses in **PostgreSQL** that can be used to rename a table.

\- **tbl-name** represents the table's name, while **modified_tbl_name** represents the altered/modified table name.

 **Example: How to Rename a Table using the ALTER TABLE Clause?**

Let’s execute the **“ALTER TABLE”** command to rename the **“team_details”** table to **“team_info”** :
    
    
    ALTER TABLE team_details RENAME TO team_info;

\- Here, we utilized the **“RENAME TO”** along with the **“ALTER TABLE”** command to rename a table.

\- **“team_details”** is a table name to be altered/renamed.

\- **“team_info”** represents the modified table name.

Let’s run the **“\dt”** command to get the list of relations/tables:
    
    
    \dt;

The output verified that the **“team_details”** table had been renamed to the **“team_info”**.

 **How to Rename a Column in Postgres?**

A table column in **PostgreSQL** can be renamed/modified using the **" ALTER TABLE"** command:
    
    
    ALTER TABLE tbl_name  
    RENAME old_col_name TO new_col_name;

\- Here, **ALTER TABLE** is a command used to alter a table in **PostgreSQL**.

\- **RENAME** and **TO** are predefined clauses used to rename a column.

\- **tbl_name** represents the table name.

\- **old_col_name** is a column to be altered.

\- **new_col_name** represents the altered/modified column name.

 **Example: How to Rename a Column Using ALTER TABLE Command?**

Type the below-given command to rename a column from **“team_ranking”** to **“team_rating”** :
    
    
    ALTER TABLE team_info
    RENAME team_ranking TO team_rating;

Let’s verify the column alteration using the **“\d”** command:
    
    
    \d team_info;

The output clarified that the column name **“team_ranking”** has been modified to the **“team_rating”**.

 **How to Change/Modify the Data Type of a Column in PostgreSQL?**

In **PostgreSQL** , the **“ALTER TABLE”** command can be used along with the **“ALTER COLUMN”** and **“TYPE”** clauses to modify the data type of a column **:**
    
    
    ALTER TABLE tbl_name ALTER COLUMN col_name TYPE data_type;

In the above syntax, **tbl_name** represents the table name, **col_name** is the column to be altered, and **data_type** represents the type of the column like int, varchar, etc.

 **Example: How to Use the ALTER TABLE Command to Modify/Update the Column’s Data Type?**

Let’s run the following statement to modify/alter the type of the **“team_rating”** column from **“int”** to **“char”** :
    
    
    ALTER TABLE team_info ALTER COLUMN team_rating TYPE CHAR(50);

Now compile the **“\d”** command to verify the modifications made in the **“team_info”** table:

The output verified that the column type of the **“team_rating”** has been changed from **“integer”** type to **“character”**.

 **How to ADD a PRIMARY KEY Constraint Using the ALTER TABLE Command?**

 **PostgreSQL** allows us to add or drop a constraint using the **ALTER TABLE** command, such as adding or dropping a unique constraint, primary key constraint, not null constraint, etc.

 **Example: How to Add Primary Key Constraint to a Column in PostgreSQL?**

The below snippet will let you understand how to add the **“PRIMARY KEY”** constraint in **“PostgreSQL”** using the **“ALTER TABLE”** command:
    
    
    ALTER TABLE team_info 
    ADD PRIMARY KEY (team_rating);

The output verified that multiple primary keys in the table **“team_info”** are not allowed. This is how you can add or drop any constraint in **PostgreSQL** using the **ALTER TABLE** command.

 **Conclusion**  
In **PostgreSQL** , the **ALTER TABLE** command serves multiple functionalities on a table like adding a column, dropping a column, renaming a table/columns, etc. The **ALTER TABLE** command enables us to add or drop constraints like **PRIMARY KEY** , **UNIQUE** CONSTRAINT, **NOT NULL** CONSTRAINT, etc. This write-up explained the working of the **ALTER TABLE** command with the help of suitable examples.

---
[View this page online](https://www.commandprompt.com/education/how-to-use-the-alter-table-command-in-postgresql/)

---

# How to drop a table in PostgreSQL

> To drop/delete a table from the PostgreSQL database, open the SQL SHELL and type the DROP TABLE command followed by the table name.

There are a couple of ways to drop/remove a table in **PostgreSQL,** such as using **psql** and **pgAdmin**. In **PostgreSQL** , the **DROP TABLE** command is used to delete/drop the targeted table permanently. Therefore, once a table is dropped using the **DROP TABLE** command, it cannot be retrieved.

 **How to Drop/Delete a table using SQL SHELL (psql) in PostgreSQL?**

The **DROP TABLE** command is used to delete/drop a table and everything that resides within that table permanently. The basic syntax of the DROP TABLE command will be as follows:
    
    
    DROP TABLE tblname;

Here, the **DROP TABLE** is a command that drops a table while tblname is the table to be dropped.

 **How to Drop/Delete Multiple tables in PostgreSQL using psql?**

You can drop multiple tables using the **DROP TABLE** command simultaneously. To do so, you have to follow the comma-separated syntax as shown in the below-given snippet:
    
    
    DROP TABLE table1, table2, ...;

Here, table1, table2, etc., are the tables to be dropped/deleted.

Let’s follow the below-given steps to understand how to drop a table in **PostgreSQL** :

 **Step 1: Check available databases**

Type **“\l”** to check the list of available databases:
    
    
    \l

 **Step 2: Access/Select the database**

Firstly, select/access the database where the table to be deleted is located. To do so, type **“\c”** followed by database name:
    
    
    \c example

Here, **“\c”** represents a command while “example” is the database to be accessed:

 **Step 3: Check available tables**

To get all available tables within the targeted database, run the "/d" command:
    
    
    \d

The above snippet shows that there are two tables (company_details and team_details) within the selected database.

 **Step 4: Drop the tables**

Let’s drop both these tables using the **DROP TABLE** command:
    
    
    DROP TABLE company_details, team_details;

 **Step 5: Verify the Table deletion**

Let’s execute the **“\d”** command to verify whether the selected tables have been dropped or not:
    
    
    \d

This is how you can drop a table using the **DROP TABLE** command from the psql.

 **How to Drop/Delete a table using pgAdmin in PostgreSQL?**

Follow the below-given step-wise instructions to drop a table using the **pgAdmin:**

 **Step 1: Select the database**

Firstly, open the **pgAdmin** and select the database in which the targeted table is located:

 **Step 2: Open the Schemas**

Let’s click on the **schemas** and select the **public** section/option:

 **Step 3: Find the tables section**

Scroll down to locate the **Tables** section. To check the list of available tables, click on the **tables** section:

The above-given snippet shows that there are two tables available in the selected database.

 **Step 4: Drop the selected table**

Select the table to be dropped under the **“Tables”** section. Right-click on the targeted table and select the Delete/Drop option to drop the unwanted table:

 **Step 5: Confirm the table deletion**

Clicking on the Drop/Delete option will show a “drop table” window. Clicking on the “Yes” button will drop/delete the targeted table permanently from the database:

 **Step 6: Verify the table deletion**

You can verify the table deletion under the **“Tables”** section:

The above-given snippet shows that the **“company_details”** table is no longer available under the **“Tables”** section.

This is how you can drop a table in **PostgreSQL** by using the **SQL SHELL (psql)** and **pgAdmin**.

 **Conclusion**

In **PostgreSQL** , we can drop a table using **SQL SHELL** and **pgAdmin**. Utilize the **DROP TABLE** command followed by the table name to drop the targeted table from **SQL SHELL**. While in the case of **pgAdmin** , select the database > open the public section under schemas > find the targeted table > right-click on the selected table > select the Drop/Delete option to delete the selected table from the database. This write-up explained a couple of table deletion methods with the help of appropriate screenshots.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-table-in-postgresql/)

---

# How to drop a database in PostgreSQL

> Execute the DROP DATABASE command from psql while dropdb command from the command prompt to remove/drop any specific PostgreSQL database.

When a **PostgreSQL** database is no longer needed, we can delete/drop it using **SQL SHELL, command prompt,** and **pgAdmin**. To do that, **PostgreSQL** provides a couple of commands/statements such as **DROP DATABASE** and **dropdb**. So, let’s learn how to drop/delete a specific database in PostgreSQL.

 **How to drop/delete a PostgreSQL database using SQL SHELL?**

The **DROP DATABASE** command can be executed from the **SQL SHELL** to drop/delete a **PostgreSQL** database. The **DROP DATABASE** statement deletes the catalogs and directory associated with that database. Here is the basic syntax of the **DROP DATABASE** statement:
    
    
    DROP DATABASE [IF EXISTS] dbname;

Let’s understand the above-given command step-by-step:

\- **DROP DATABASE** is a command to delete a specific **PostgreSQL** database.

\- If the specified database does not exist, the **IF EXISTS** parameter will issue a notice rather than throwing an error.

\- **dbname** is the database to be deleted.

Let’s execute the **“\l”** command to check the list of all the available databases:

Let’s assume we need to drop a database named **“example”** using psql. To do so, we will execute the following command:
    
    
    DROP DATABASE IF EXISTS example;

The above command will serve the following functionalities:

\- **testdb** is a database name.

\- **IF EXISTS** will check the existence of the example.

\- **DROP DATABASE** will delete the given database, i.e. example.

The above snippet verified that the database named “example” has been deleted successfully.

Let’s execute the **DROP DATABASE** command one more time to remove the same database i.e. example:
    
    
    DROP DATABASE IF EXISTS example;

This time the **DROP DATABASE** command issued a notice that the “example” database doesn’t exist.

 **How to drop/delete a PostgreSQL database using Command Prompt?**

In Postgres, the **dropdb** command can be executed from the command prompt(cmd) to delete any specific database. The **dropdb** command will have the following syntax:

dropdb [parameter/option] dbname

Here is the detailed explanation of the above snippet:

\- **dropdb** is a command that drops/deletes a database.

\- **parameters/options** are the command-line arguments that the **dropdb** command can accept.

\- **dbname** is the database name to be deleted.

Below is a list of parameters that **dropdb** command can accept:

 **–help**

It is used to get help regarding the dropdb command.

 **-if exists**

It issues a notice rather than throwing an error if the given database doesn’t exist.

 **-e**

It is used to display the commands to be sent to the server

 **-i**

It shows a verification prompt before deletion.

 **-V**

It shows the dropdb’s version.

 **-h**

It is used to specify the host name for the server’s machine.

 **-U**

It is used to specify the user name to connect with.

 **-p**

It is used to specify the port on which the server listens for the connections.

 **maintenance db-=dbname**

It takes the name of the connected database to remove that specific database.

 **-w**

Use -w option if you don’t want to prompt a password for the **dropdb**.

 **-W**

It is used to prompt a password for the dropdb command.

Let’s follow the below steps to delete a database named **“exampledb”** using the **dropdb** command:

 **Step 1: Access Postgres**

Firstly, access the **bin** directory of the **PostgreSQL** by using the cd command followed by the complete path:
    
    
    C:\Program Files\PostgreSQL\14\bin

 **Step 2: Execute dropdb command**

Let’s execute the **dropdb** command from the command prompt to remove a database named “exampledb”:
    
    
    dropdb -U postgres exampledb

When you execute the above mentioned command, it will ask you to enter a password. Once you provide the appropriate password then the **dropdb** command will delete the database named “exampledb” connected to the user named postgres.

 **How to drop/delete a PostgreSQL database using pgAdmin?**

You can drop a PostgreSQL database using a GUI i.e. pgAdmin. Follow the below-given steps to learn how to drop a Postgres database using pgAdmin:

 **Step 1: select database**

Open the **pgAdmin** and pick the database you want to drop:

 **Step 2: drop database**

Right click on the desired database and select the “Delete/Drop” option to drop the particular database:

 **Step 3: Confirmation**

A confirmation notification will appear once you click on the “Delete/Drop” option:

Clicking on the “Yes” button will drop the selected database.

 **Conclusion**

In **PostgreSQL** , **DROP DATABASE** and **dropdb** commands are used to delete a specific database. You can execute the **DROP DATABASE** command from psql while **dropdb** command from the command prompt to remove/drop a database. Moreover, a PostgreSQL database can be deleted using **pgAdmin**. This write-up explained the different ways to drop a PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-drop-a-database-in-postgresql/)

---

# How to select/access a database in PostgreSQL

> There are multiple ways to select or access a PostgreSQL database, such as Command Prompt (cmd), SQL SHELL (psql), and pgAdmin 4.

Once you have created a PostgreSQL database, the next step is to select or access that database. A PostgreSQL database can be selected or accessed using multiple methods such as **command prompt, pgAdmin,** or **SQL SHELL(psql)**. So, let’s learn how to access a Postgres database.

 **How to access/select a PostgreSQL database using SQL SHELL?**

We have already created some databases, and now we will select one of them using the **SQL SHELL(psql)**. If you have not yet created a PostgreSQL database, we recommend you to read our tutorial on [database creation](<https://docs.google.com/document/d/1FlxBv_r5W-3wopbAQrNmWLYxJRh6rG3L/edit>).

 **Step 1: Open psql**

Firstly, type **“psql”** in the Windows search bar and open it:

 **Step 2: List of databases**

Type **“\l”** to check all the available databases:

 **Step 3: Select database**

Choose a desired database from the available databases, and type the following command to access it:
    
    
    \c exampledb;

Here, the **“\c”** is a command used to select/access a database while **“exampledb”** is a database to be accessed:

This is how you can access any database using **“psql”**.

 **How to access/select a PostgreSQL database using Command prompt?**

Follow the below-listed steps to select the desired PostgresQL database using the Windows command prompt(cmd):

 **Step1: Open cmd**

Type **“cmd”** in the Windows search bar and click on the command prompt app to open it:

 **Step 2: Access Postgres**

To access the Postgres bin directory, provide the complete path of the directory where Postgres is installed:

Now, you are successfully entered into the PostgreSQL bin’s directory.

 **Step 3: Select database**

Type the below-given command to access the desired database:
    
    
    psql -h localhost -p 5432 -U postgres exampledb

\- Here, in the above snippet, we utilized the **“-h”** option/argument to specify the host, **“-p”** argument to specify the port number, and **“-U”** to specify the user name. While **“exampledb”** is the database to be accessed.

\- Type the command, press the enter button, and provide the superuser password.

\- Consequently, the above-mentioned command will select the database named **“exampledb”** , owned by the user **“Postgres”,** available on the **“localhost”,** and has a default port number **“5432”** :

The above snippet clarified that we have successfully accessed the “exampledb” database using the command prompt.

 **How to access/select a PostgreSQL database using pgAdmin?**

The below-listed steps will guide you to select a Postgres database using pgAdmin:

 **Step 1: Open pgAdmin**

Search **“pgAdmin”** in the windows search bar and open it:

 **Step 2: Select Database**

Select the desired database from the available databases:

 **Step 3: Select Query Tool**

Click on the **“Tools”** tab, and select the **“Query tool”** from the drop-down menu:

Clicking on the **“Query Tool”** will open a new window with an established connection to the desired database:

The above window shows that the desired database, i.e. **“exampledb”** , has been selected successfully.

 **Conclusion**

There are multiple ways to select or access a PostgreSQL database, such as Command Prompt (cmd), SQL SHELL (psql), and pgAdmin 4. Type **“\c”** followed by a database name to select a database using psql. Type **“psql hostname port number username databasename”** to select a database using cmd. Open pgAdmin > select desired database> and open the “Query Tool” to select a database using pgAdmin. This write-up considered multiple methods along with screenshots to select/access a PostgreSQL database.

---
[View this page online](https://www.commandprompt.com/education/how-to-selectaccess-a-database-in-postgresql/)

---

# How to download and install PostgreSQL

> Download PostgreSQL “exe” file &gt; open downloaded file &gt; specify installation directory &gt; select components &gt; select directory &gt; set password &gt; and install.

**PostgreSQL** or **Postgres** is the most commonly used open-source relational database. It offers features like robustness, reliability, cost-free, etc. **PostgreSQL** serves as a data warehouse for multiple applications like web apps, mobile apps, etc. It enables us to store enormous and sophisticated data securely. However, to achieve any of its functionalities or features, firstly, we have to download and install **PostgreSQL**.

This write-up will present a detailed guide on downloading and installing **PostgreSQL** on Windows 10. So, let’s get started!

 **How to download PostgreSQL for Windows 10?**

You have to follow the below-given steps appropriately to download the **PostgreSQL** :

 **Step1: Visit postgresql.org**

Firstly, open the browser of your choice and enter **“www.postgresql.org/download”** in the address bar of your browser or click on the following link:

[Download postgreSQL](<https://www.postgresql.org/download/>)

Clicking on the link will open the following window:

 **Step2: Select your OS**

Select the operating system on which you want to download the **PostgreSQL**. In our case, its Windows operating system:

 **Step3: Download the installer**

Clicking on the **“Windows”** option will direct to the below-given page:

Click on the **“Download the installer”** option to download the interactive installer by EDB.

 **Step4: Choose the relevant PostgreSQL Version**

Clicking on the above-given link will show you **PostgreSQL** versions for the different operating systems. Choose the latest **PostgreSQL** version for your respective operating system and click on the download button:

Clicking on the download button will start the downloading process:

 **PostgreSQL** will be downloaded to your windows operating system within a few minutes.

 **How to install PostgreSQL?**

Follow the below-listed steps to install **PostgreSQL** on your Windows operating system:

 **Step 1: Open the downloaded file**

Once the downloading is completed, open the respective **“.exe”** file:

Initially, a **" welcome"** window will appear; click **" Next"** to proceed.

 **Step 2: Choose Installation directory**

Specify or browse the directory where you want to install the **PostgreSQL** :

After specifying, click on the **“Next”** button to proceed further.

 **Step 3: Select Components**

You can select the components of your choice to install on your computer. We will proceed with the default settings, so just click on the **“Next”** button:

 **Step 4: Select Data Directory**

Select a data directory to store your data and click on the **“Next”** button:

 **Step 5: Set Password**

Set a password (must remember it for later use) for the Postgres superuser and click on the **“Next”** button:

 **Step 6: Set Port Number**

Whether set the port number or go with the default port number **“5432”** to connect to a database:

 **Step 7: Advanced Options**

The next window will give you choice to select locale; leave them as it is, and click on the **“Next”** button:

 **Step 8: Verify Pre-installation Summary**

The pre-installation summary will tell you which settings will be used for the installation:

 **Step 9: Begin PostgreSQL Installation**

The setup is ready to install **Postgres** on your windows operating system:

Just click on the **“Next”** button to begin the installation:

The whole process will take a few minutes to complete:

Once the **PostgreSQL** setup wizard is completed, click on the “ **Finish** ” button to close the installation windows.

 **How to launch PostgreSQL on Windows 10?**

The below-given steps are required to launch **PostgreSQL** on Windows Operating System:

 **Step 1: Open pgAdmin**

Click the windows button and find the **“postgreSQL 14”**. Once you find it click on it and select the **“pgAdmin 4”** :

Or you can directly search for the **“pgAdmin 4”** in the windows search bar.

 **Step 2: Enter Password**

Clicking on the **“pgAdmin 4”** will ask you to enter the password:

Provide the master password that you have recently set during the installation and click the “Ok” button to proceed.

 **Step 3: Select PostgreSQL 14**

In the left pane, click on the **“Servers”** and then **“PostgreSQL 14”**. Consequently, the following dashboard will appear:

That was all the necessary information about downloading, installing, and launching **PostgreSQL** on Windows 10 operating system.

 **Conclusion**

To download **PostgreSQL,** visit “[www.postgresql.org/download](<http://www.postgresql.org/download>)” > Select your **OS** > Download the **installer** > Choose the relevant **PostgreSQL Version** , consequently, a “.exe” file will be downloaded. To install **PostgreSQL** on **Windows** 10, open the downloaded file > specify installation directory > select components > select data directory > set password > read pre installation summary and finally click on the next button to begin the installation process.

---
[View this page online](https://www.commandprompt.com/education/how-to-download-and-install-postgresql/)

---

# How to Create a Table in PostgreSQL & Perform CRUD Operations

> Tables in PostgreSQL can be created following the syntax discussed in the article. You can insert, update, read, and delete data from the table with the help o…

Let's learn to create tables in PostgreSQL and how to perform basic operations, such as insert or create, read, update, and delete, on tables. In databases, a table is like a container that stores the data in the forms of columns and rows, much like excel or google sheets.

##  **How to Create a Table in PostgreSQL?**

To create a table in PostgreSQL, you have to use a specific syntax consisting of specific keywords responsible for table creation. Let's jump directly into it and create a table so that you can understand:
    
    
    CREATE TABLE workers(
    id SERIAL PRIMARY KEY,
    first_name VARCHAR(40),
    email VARCHAR(255),
    age INT
    );

Now, let’s discuss the table creation syntax step by step:

  *  **CREATE TABLE workers:** CREATE TABLE is the keyword which creates the table and workers is the table name. Table name could be of your choice.  
**Note:** In SQL, every uppercase is a syntax keyword, lowercase is not the keyword and its name can be the choice of programmer.
  *  **id SERIAL PRIMARY KEY:** id is the column name, SERIAL is a special type which increments integer value with +1 each time a new data entry takes place, PRIMARY KEY makes id column a unique identifier which is used to reference to specific rows.
  *  **first_name VARCHAR(40):** first_name is the column name in the table and VARCHAR is the data type which simply is text and 40 is the character limit. First name is not going to be very big so it’s a good idea to optimize with the character limit.
  * \- **email VARCHAR(255):** email is the column name, VARCHAR is the datatype which is text and emails could be long so 255 is the character limit.
  * \- **age INT:** age is column name and INT is simply the integer.
  * \- **()** are used to enclose the column names and datatypes.
  * \- **;** is used to end the statement in SQL, which means the query ends here.



As other programming languages have their conventions, SQL also has its own conventions. The convention is to write all the keywords in uppercase and everything relating to table such as column name in lowercase. However, SQL doesn’t care about uppercase or lowercase. For example, the keywords **CREATE TABLE** can also be written as **create table** and it would still work but we write code for people and other programmers are used to these conventions which make the code readable.

Let’s run the query in psql shell and create a table:

To verify if the table has been created, write in psql shell:  

    
    
    \dt

##  **CRUD Operations (CREATE, READ, UPDATE, and DELETE)**

Let’s practically perform CRUD operations on the table we just created.

 **1- CREATE OR INSERT OPERATION**

In order to insert data into the table we are going to write following query:
    
    
      INSERT INTO workers (first_name, email, age) VALUES ('Robert', 'bob@commandprompt.com', 26);

See the result:

In the first parenthesis, followed by the table name, we entered column names, and after the keyword VALUES, we entered the values we wanted to insert into the table.

 **Note** : Single colons **‘’** and double colons **“”** do not mean the same thing in SQL.

 **2-** **READ Operation**

Let’s see the data that we inserted previously in the table. To read, simply write the following query:
    
    
    SELECT * FROM workers;
    

In the above query, * refers to column. You can use column names to fetch data against a single column or even a combination of multiple columns:
    
    
    SELECT email FROM workers;

In the above query, * refers to column. You can use column names to fetch data against a single column or even a combination of multiple columns:
    
    
    SELECT email FROM workers;

You can also refer to row after adding a WHERE keyword. You can pick up a single or multiple rows using WHERE and a condition. Let’s see how you can do that:
    
    
    SELECT * FROM workers WHERE age = 26;

It would simply pick up the row/s having age 26.

 **3-** **Update Operation**

Let’s say we want to update a specific name in our table. In that case we would write:
    
    
    UPDATE workers SET first_name = 'BOB' WHERE id = 1;

Here we can see that first_name column has been updated successfully.

 **4-** **DELETE OPERATION**

I have added an extra record in the table and now the table looks like this:

To delete the column, I’d write the following query:
    
    
    DELETE FROM workers WHERE id = 2;

Here, you can see the 2nd record or row has been deleted successfully.

##  **How to Drop a Table in PostgreSQL?**

We learned how to create a table and perform CRUD operations in the table. Now, let’s learn about removing a table from database.
    
    
    DROP TABLE workers;

By running the above query, table is now dropped. Afterwards, running **\dt** would ensure this as you can see above.

##  **Conclusion**

To create tables in PostgreSQL, you have to use a specific syntax with specific keywords along with the column names and datatypes. You can perform CRUD operations on the table by writing similar queries discussed in the article. In PostgreSQL, similar to other programming languages, you must follow conventions while writing queries, so it's easy for other programmers to understand your work. If you want to get rid of any table in your database, you can use the **DROP TABLE** keyword.

---
[View this page online](https://www.commandprompt.com/education/how-to-create-a-table-in-postgresql-perform-crud-operations/)