diff --git a/.github/workflows/issue-auto-assign.yml b/.github/workflows/issue-auto-assign.yml
new file mode 100644
index 0000000..40dadc3
--- /dev/null
+++ b/.github/workflows/issue-auto-assign.yml
@@ -0,0 +1,74 @@
+name: Auto Assign Issue on Command
+
+on:
+ issue_comment:
+ types: [created]
+
+jobs:
+ assign_on_command:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ contents: read
+ steps:
+ - name: Assign to user on /assign command
+ uses: actions/github-script@v6
+ with:
+ github-token: ${{secrets.IVORY_TOKEN}}
+ script: |
+ const commentBody = context.payload.comment.body.trim().toLowerCase();
+ const commenter = context.payload.comment.user.login;
+ const issueNumber = context.issue.number;
+ const repoOwner = context.repo.owner;
+ const repoName = context.repo.repo;
+
+ if (commentBody === '/assign') {
+ console.log(`User @${commenter} commented "/assign" on issue #${issueNumber}. Attempting to assign.`);
+
+ if (commenter.endsWith('[bot]') || commenter === 'github-actions[bot]') {
+ console.log(`Skipping assignment for bot user: ${commenter}`);
+ return;
+ }
+
+ const { data: issue } = await github.rest.issues.get({
+ owner: repoOwner,
+ repo: repoName,
+ issue_number: issueNumber
+ });
+
+ if (issue.assignees && issue.assignees.some(a => a.login === commenter)) {
+ console.log(`Issue #${issueNumber} is already assigned to @${commenter}. No action needed.`);
+ return;
+ }
+
+ if (issue.state === 'closed') {
+ console.log(`Issue #${issueNumber} is closed. No assignment will be made.`);
+ await github.rest.issues.createComment({
+ owner: repoOwner,
+ repo: repoName,
+ issue_number: issueNumber,
+ body: `Hi @${commenter}, issue #${issueNumber} is closed and cannot be assigned.`
+ });
+ return;
+ }
+
+ try {
+ await github.rest.issues.addAssignees({
+ owner: repoOwner,
+ repo: repoName,
+ issue_number: issueNumber,
+ assignees: [commenter]
+ });
+ console.log(`Successfully assigned issue #${issueNumber} to @${commenter}.`);
+ } catch (error) {
+ console.error(`Error assigning issue #${issueNumber} to @${commenter}:`, error);
+ await github.rest.issues.createComment({
+ owner: repoOwner,
+ repo: repoName,
+ issue_number: issueNumber,
+ body: `Hi @${commenter}, I encountered an error trying to assign you to issue #${issueNumber}. Please check permissions or assign manually. \nError: ${error.message}`
+ });
+ }
+ } else {
+ console.log(`Comment by @${commenter} on issue #${issueNumber} was not an "/assign" command. Body: "${context.payload.comment.body.trim()}"`);
+ }
diff --git a/.github/workflows/merge-build-push.yml b/.github/workflows/merge-build-push.yml
new file mode 100644
index 0000000..607fe56
--- /dev/null
+++ b/.github/workflows/merge-build-push.yml
@@ -0,0 +1,269 @@
+name: Build , Push to web, Deploy Antora Docs
+
+on:
+ pull_request_target:
+ types:
+ - closed
+
+jobs:
+ build-and-deploy:
+ runs-on: ubuntu-latest
+ if: github.event.pull_request.merged == true
+ permissions:
+ contents: write
+ pull-requests: write
+
+ steps:
+ - name: PR was merged
+ run: |
+ echo "PR #${{ github.event.pull_request.number }} was merged into ${{ github.event.pull_request.base.ref }}."
+ echo "Head commit was: ${{ github.event.pull_request.head.sha }}"
+
+ - name: Checkout Documentation Repository (ivorysql_doc)
+ uses: actions/checkout@v4
+ with:
+ path: ivorysql_doc
+
+ - name: Checkout Doc Builder Repository (doc_builder)
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ github.repository_owner }}/ivory-doc-builder
+ path: ivory-doc-builder
+
+ - name: Determine Latest Version from ivorysql_docs branches
+ id: latest_version_step
+ shell: bash
+ run: |
+ echo "Detecting latest version from remote branches of IvorySQL/ivorysql_docs..."
+ LATEST_VERSION_NUMBER=$( \
+ git ls-remote --heads --refs "https://github.com/IvorySQL/ivorysql_docs.git" 'refs/heads/v*.*' | \
+ sed 's_^[^\t]*\trefs/heads/v__g' | \
+ grep -E '^[0-9]+\.[0-9]+(\.[0-9]+)?$' | \
+ sort -V | \
+ tail -n1 \
+ )
+
+ if [[ -z "$LATEST_VERSION_NUMBER" ]]; then
+ echo "::error::Could not determine latest version from branches. Please check git ls-remote command and repo accessibility."
+ exit 1
+ fi
+
+ echo "Detected latest version number: $LATEST_VERSION_NUMBER"
+ echo "version=$LATEST_VERSION_NUMBER" >> "$GITHUB_OUTPUT"
+
+ - name: Install yq
+ run: |
+ sudo apt-get update -y
+ sudo apt-get install -y jq
+ sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq
+ sudo chmod +x /usr/bin/yq
+ yq --version
+
+ - name: Modify Antora Playbooks
+ working-directory: ./ivory-doc-builder
+ env:
+ DETECTED_VERSION: '${{ steps.latest_version_step.outputs.version }}'
+ START_PAGE_COMPONENT_NAME: "ivorysql-doc"
+ START_PAGE_FILE_PATH: "welcome.adoc"
+ run: |
+ PLAYBOOK_FILES=("antora-playbook-CN.yml" "antora-playbook-EN.yml")
+
+ for PLAYBOOK_FILE in "${PLAYBOOK_FILES[@]}"; do
+ if [ -f "$PLAYBOOK_FILE" ]; then
+ echo "--- Modifying Playbook: $PLAYBOOK_FILE ---"
+ echo "Original content of $PLAYBOOK_FILE:"
+ cat "$PLAYBOOK_FILE"
+ echo # Newline for better readability
+
+ if [[ -n "$DETECTED_VERSION" ]]; then
+ NEW_START_PAGE="${START_PAGE_COMPONENT_NAME}::v${DETECTED_VERSION}/${START_PAGE_FILE_PATH}"
+ yq -i ".site.start_page = \"$NEW_START_PAGE\"" "$PLAYBOOK_FILE"
+ echo "Updated .site.start_page in $PLAYBOOK_FILE to: $NEW_START_PAGE"
+ else
+ echo "WARNING: DETECTED_VERSION is empty. Skipping start_page update for $PLAYBOOK_FILE."
+ fi
+ echo "Modified content of $PLAYBOOK_FILE:"
+ cat "$PLAYBOOK_FILE"
+ echo "--- Finished modification for $PLAYBOOK_FILE ---"
+ echo # Newline
+ else
+ echo "WARNING: Playbook file $PLAYBOOK_FILE not found in $(pwd)."
+ fi
+ done
+
+ - name: Checkout Web Repository (web)
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ github.repository_owner }}/ivorysql_web
+ path: www_publish_target
+ token: ${{ secrets.WEB_TOKEN }}
+
+ - name: Setup Ruby and Bundler
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: '3.0'
+
+ - name: Install Asciidoctor PDF and related Gems
+ run: |
+ echo "Installing Asciidoctor PDF gems..."
+ gem install asciidoctor-pdf --version "~>2.3.19"
+ gem install rouge
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.15'
+
+ - name: Install Antora CLI
+ run: |
+ echo "Installing Antora packages local..."
+ npm install --global antora@3.1.7 @antora/lunr-extension @antora/pdf-extension @node-rs/jieba
+
+ - name: Build English Documentation
+ working-directory: ./ivory-doc-builder
+ run: |
+ echo "Current directory: $(pwd)"
+ echo "Building English site..."
+ ls ../www_publish_target/
+ npx antora generate --stacktrace --to-dir ../www_publish_target/docs/en antora-playbook-EN.yml
+
+ - name: Build Chinese Documentation
+ working-directory: ./ivory-doc-builder
+ run: |
+ echo "Building Chinese site..."
+ npx antora generate --stacktrace --to-dir ../www_publish_target/docs/cn antora-playbook-CN.yml
+
+ - name: Move and Rename PDF Files
+ id: process_pdfs
+ working-directory: ./www_publish_target
+ run: |
+ echo "--- Searching for PDF files to move and rename ---"
+
+ PDF_FILES_FOUND=$(find . -type f -path '*/_exports/index.pdf')
+
+ if [ -z "${PDF_FILES_FOUND}" ]; then
+ echo "No PDF files found to move. Skipping."
+ else
+ echo "Found PDF files to process:"
+ echo "${PDF_FILES_FOUND}"
+
+ echo "${PDF_FILES_FOUND}" | while read PDF_FILE; do
+ # ./docs/cn/ivorysql-doc/master/_exports/index.pdf -> ./docs/cn/ivorysql-doc/master
+ BASE_DIR="${PDF_FILE%/_exports/index.pdf}"
+
+ NEW_PDF_PATH="${BASE_DIR}/ivorysql.pdf"
+
+ echo "Moving '${PDF_FILE}' to '${NEW_PDF_PATH}'"
+ mv "${PDF_FILE}" "${NEW_PDF_PATH}"
+ done
+
+ echo "--- Cleaning up empty _exports directories ---"
+ find . -type d -name '_exports' -empty -delete
+ fi
+
+ echo "--- PDF processing complete ---"
+
+ - name: Commit and Push to web Repository new branch , pull request
+ id: commit_push_new_branch
+ working-directory: ./www_publish_target
+ env:
+ OPEN_PUSH_PR: true
+ run: |
+ echo "push_pr=${OPEN_PUSH_PR}" >> $GITHUB_OUTPUT
+ echo "--- Preparing to commit and push changes ---"
+ echo "--- Git status ---"
+ GIT_STATUS_OUTPUT=$(git status --porcelain)
+ echo "${GIT_STATUS_OUTPUT}"
+ echo "--- End of git status --porcelain output ---"
+
+ git config user.name "IvorySQL Actions Bot"
+ git config user.email "actions-bot@users.noreply.github.com"
+
+ if [ -z "${GIT_STATUS_OUTPUT}" ]; then
+ echo "No changes to commit."
+ echo "changes_detected=false" >> $GITHUB_OUTPUT
+ else
+ echo "Changes detected. Proceeding with add, commit, and push."
+ if [[ "${OPEN_PUSH_PR}" == "true" ]]; then
+ NEW_BRANCH_NAME="docs-update-${{ github.run_attempt }}-$(date +'%Y-%m-%d-%H%M%S')"
+ echo "Generated new branch name: ${NEW_BRANCH_NAME}"
+ echo "new_branch_name=${NEW_BRANCH_NAME}" >> $GITHUB_OUTPUT
+ echo "changes_detected=true" >> $GITHUB_OUTPUT
+ git checkout -b "${NEW_BRANCH_NAME}"
+ git add .
+ COMMIT_MESSAGE="docs: Regenerate Antora site from IvorySQL/ivorysql_docs commit ${{ github.event.head_commit.id || github.sha }}"
+ git commit -m "${COMMIT_MESSAGE}"
+ git push origin "${NEW_BRANCH_NAME}"
+ else
+ echo "Pushing changes to master branch."
+ git add .
+ COMMIT_MESSAGE="docs: Regenerate Antora site from IvorySQL/ivorysql_docs commit ${{ github.event.head_commit.id || github.sha }}"
+ git commit -m "${COMMIT_MESSAGE}"
+ git push origin master
+ fi
+ fi
+
+ - name: Create or Update Pull Request with GitHub CLI
+ id: cpr
+ if: steps.commit_push_new_branch.outputs.push_pr == 'true' && steps.commit_push_new_branch.outputs.changes_detected == 'true' && steps.commit_push_new_branch.outputs.new_branch_name != ''
+ working-directory: ./www_publish_target
+ env:
+ GH_TOKEN: ${{ secrets.WEB_TOKEN }}
+ PARAM_BASE_BRANCH: master
+ PARAM_HEAD_BRANCH: ${{ steps.commit_push_new_branch.outputs.new_branch_name }}
+ PARAM_TITLE: "Docs: Automated update from IvorySQL/ivorysql_docs commit ${{ github.event.head_commit.id || github.sha }}"
+ PARAM_BODY: |
+ Automated Antora site regeneration based on changes in the IvorySQL/ivorysql_docs repository.
+
+ Source commit: `${{ github.server_url }}/${{ github.repository_owner }}/ivorysql_docs/commit/${{ github.event.head_commit.id || github.sha }}`
+
+ - Auto-generated by gh pr create
+ PARAM_DRAFT: "false"
+ run: |
+ echo "Attempting to create or update Pull Request for branch '${PARAM_HEAD_BRANCH}' into '${PARAM_BASE_BRANCH}'"
+
+ DRAFT_FLAG_STRING=""
+ if [[ "${PARAM_DRAFT}" == "true" ]]; then
+ DRAFT_FLAG_STRING="--draft"
+ fi
+
+ echo "Executing: gh pr create --base \"${PARAM_BASE_BRANCH}\" --head \"${PARAM_HEAD_BRANCH}\" --title
--body-file <(echo body) ${DRAFT_FLAG_STRING}"
+
+ if gh pr create \
+ --base "${PARAM_BASE_BRANCH}" \
+ --head "${PARAM_HEAD_BRANCH}" \
+ --title "${PARAM_TITLE}" \
+ --body-file <(echo "${PARAM_BODY}") \
+ ${DRAFT_FLAG_STRING}; then
+ echo "Pull Request created or already exists and metadata might have been updated."
+ else
+ echo "'gh pr create' command indicated an issue or no action was taken."
+
+ EXISTING_PR_URL=$(gh pr view "${PARAM_HEAD_BRANCH}" --json url -q ".url" 2>/dev/null || echo "")
+ if [[ -n "$EXISTING_PR_URL" ]]; then
+ echo "An existing PR was found for branch '${PARAM_HEAD_BRANCH}': ${EXISTING_PR_URL}"
+ echo "Proceeding to enable auto-merge for this existing PR."
+ else
+ echo "::error::Failed to create PR and no existing PR found for branch '${PARAM_HEAD_BRANCH}'. Cannot enable auto-merge."
+ exit 1
+ fi
+ fi
+
+ - name: Enable Auto-Merge for PR
+ if: steps.cpr.outcome == 'success' && steps.commit_push_new_branch.outputs.push_pr == 'true' && steps.commit_push_new_branch.outputs.changes_detected == 'true' && steps.commit_push_new_branch.outputs.new_branch_name != ''
+ working-directory: ./www_publish_target
+ env:
+ GH_TOKEN: ${{ secrets.WEB_TOKEN }}
+ PR_HEAD_BRANCH: ${{ steps.commit_push_new_branch.outputs.new_branch_name }}
+ PR_BASE_BRANCH: master
+ MERGE_STRATEGY: MERGE
+ run: |
+ echo "Attempting to enable auto-merge for PR from branch '$PR_HEAD_BRANCH' to '$PR_BASE_BRANCH'"
+ if gh pr merge "$PR_HEAD_BRANCH" \
+ --${MERGE_STRATEGY,,} \
+ --delete-branch; then
+ echo "Auto-merge enabled successfully for PR from branch '$PR_HEAD_BRANCH'."
+ else
+ echo "::warning::Failed to enable auto-merge for PR from branch '$PR_HEAD_BRANCH'."
+ echo "This might be because the PR is not mergeable (e.g., has conflicts, is a draft PR), requires reviews, auto-merge is already enabled, or the PR could not be uniquely identified by branch name."
+ fi
diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml
new file mode 100644
index 0000000..d121485
--- /dev/null
+++ b/.github/workflows/pr-preview.yml
@@ -0,0 +1,187 @@
+name: Pr preview
+
+on:
+ pull_request_target:
+
+jobs:
+ build-and-deploy:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+ deployments: write
+ statuses: write
+
+ steps:
+ - name: Checkout Documentation Repository (ivorysql_doc)
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ repository: ${{ github.event.pull_request.head.repo.full_name }}
+ path: ivorysql_doc
+
+ - name: Fetch All Relevant Branches into Local Docs Repo
+ working-directory: ./ivorysql_doc
+ run: |
+ echo "Fetching all branches from origin to update local remote-tracking branches..."
+ git fetch origin --prune --no-tags
+
+ echo "--- Fetched Remote-Tracking Branches ---"
+ git branch -r
+
+ - name: Checkout Doc Builder Repository (doc_builder)
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ github.repository_owner }}/ivory-doc-builder
+ path: ivory-doc-builder
+
+ - name: Determine Latest Version from ivorysql_docs branches
+ id: latest_version_step
+ shell: bash
+ run: |
+ echo "Detecting latest version from remote branches of ${{ github.repository_owner }}/ivorysql_docs..."
+ LATEST_VERSION_NUMBER=$( \
+ git ls-remote --heads --refs "https://github.com/${{ github.repository_owner }}/ivorysql_docs.git" 'refs/heads/v*.*' | \
+ sed 's_^[^\t]*\trefs/heads/v__g' | \
+ grep -E '^[0-9]+\.[0-9]+(\.[0-9]+)?$' | \
+ sort -V | \
+ tail -n1 \
+ )
+
+ if [[ -z "$LATEST_VERSION_NUMBER" ]]; then
+ echo "::error::Could not determine latest version from branches. Please check git ls-remote command and repo accessibility."
+ exit 1
+ fi
+
+ echo "Detected latest version number: $LATEST_VERSION_NUMBER"
+ echo "version=$LATEST_VERSION_NUMBER" >> "$GITHUB_OUTPUT"
+
+ - name: Install yq
+ run: |
+ sudo apt-get update -y
+ sudo apt-get install -y jq
+ sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq
+ sudo chmod +x /usr/bin/yq
+ yq --version
+
+ - name: Modify Antora Playbooks for Local PR Build
+ working-directory: ./ivory-doc-builder
+ env:
+ DETECTED_VERSION: '${{ steps.latest_version_step.outputs.version }}'
+ START_PAGE_COMPONENT_NAME: "ivorysql-doc"
+ START_PAGE_FILE_PATH: "welcome.adoc"
+ run: |
+ PLAYBOOK_FILES=("antora-playbook-CN.yml" "antora-playbook-EN.yml")
+ NEW_LOCAL_URL="../ivorysql_doc"
+
+ for PLAYBOOK_FILE in "${PLAYBOOK_FILES[@]}"; do
+ if [ -f "$PLAYBOOK_FILE" ]; then
+ echo "--- Modifying Playbook: $PLAYBOOK_FILE ---"
+ echo "Original content of $PLAYBOOK_FILE:"
+ cat "$PLAYBOOK_FILE"
+ echo # Newline for better readability
+
+ yq -i ".content.sources[0].url = \"$NEW_LOCAL_URL\"" "$PLAYBOOK_FILE"
+
+ yq -i ".content.sources[0].branches = [\"HEAD\"]" "$PLAYBOOK_FILE"
+
+ yq -i ".content.sources[0].edit_url = false" "$PLAYBOOK_FILE"
+ if [[ -n "$DETECTED_VERSION" ]]; then
+ NEW_START_PAGE="${START_PAGE_COMPONENT_NAME}::v${DETECTED_VERSION}/${START_PAGE_FILE_PATH}"
+ yq -i ".site.start_page = \"$NEW_START_PAGE\"" "$PLAYBOOK_FILE"
+ echo "Updated .site.start_page in $PLAYBOOK_FILE to: $NEW_START_PAGE"
+ else
+ echo "WARNING: DETECTED_VERSION is empty. Skipping start_page update for $PLAYBOOK_FILE."
+ fi
+ yq -i ".site.title = .site.title + \" (PR Preview)\"" "$PLAYBOOK_FILE"
+ echo "Modified content of $PLAYBOOK_FILE:"
+ cat "$PLAYBOOK_FILE"
+ echo "--- Finished modification for $PLAYBOOK_FILE ---"
+ echo # Newline
+ else
+ echo "WARNING: Playbook file $PLAYBOOK_FILE not found in $(pwd)."
+ fi
+ done
+
+ - name: Checkout WWW Repository (www)
+ uses: actions/checkout@v4
+ with:
+ repository: ${{ github.repository_owner }}/ivorysql_web
+ path: www_publish_target
+
+ - name: Setup Ruby and Bundler
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: '3.0'
+
+ - name: Install Asciidoctor PDF and related Gems
+ run: |
+ echo "Installing Asciidoctor PDF gems..."
+ gem install asciidoctor-pdf --version "~>2.3.19"
+ gem install rouge
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.15'
+
+ - name: Install Antora CLI
+ run: |
+ echo "Installing Antora packages local..."
+ npm install --global antora@3.1.7 @antora/lunr-extension @antora/pdf-extension @node-rs/jieba
+
+ - name: Build English Documentation
+ working-directory: ./ivory-doc-builder
+ run: |
+ echo "Current directory: $(pwd)"
+ echo "Building English site..."
+ #mkdir -p ../www_publish_target/docs/en
+ npx antora generate --stacktrace --to-dir ../www_publish_target/docs/en antora-playbook-EN.yml
+
+ - name: Build Chinese Documentation
+ working-directory: ./ivory-doc-builder
+ run: |
+ echo "Building Chinese site..."
+ #mkdir -p ../www_publish_target/docs/cn
+ npx antora generate --stacktrace --to-dir ../www_publish_target/docs/cn antora-playbook-CN.yml
+
+ - name: Deploy to Netlify
+ id: netlify_deploy
+ uses: nwtgck/actions-netlify@v3.0
+ with:
+ publish-dir: './www_publish_target/docs'
+ production-branch: test
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ deploy-message: "Deploy preview for PR #${{ github.event.number }}"
+ enable-pull-request-comment: false
+ enable-commit-comment: false
+ enable-commit-status: true
+ alias: pr-${{ github.event.number }}-doc
+ env:
+ NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
+ NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
+ timeout-minutes: 5
+
+ - name: Post Custom Preview Links Comment
+ if: steps.netlify_deploy.outputs.deploy-url
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const baseUrl = '${{ steps.netlify_deploy.outputs.deploy-url }}';
+
+ const enUrl = `${baseUrl}/en`;
+
+ const body = `
+ 🚀 **IvorySQL-Docs Preview Ready**
+
+ - **Chinese Preview:** [${baseUrl}](${baseUrl})
+ - **English Preview:** [${enUrl}](${enUrl})
+ `;
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: body
+ });
\ No newline at end of file
diff --git a/CN/antora.yml b/CN/antora.yml
index 1d17feb..6612cec 100644
--- a/CN/antora.yml
+++ b/CN/antora.yml
@@ -1,7 +1,7 @@
name: ivorysql-doc
title: IvorySQL
-version: v3.0
-start_page: v3.0/welcome.adoc
+version: v1.23
+start_page: v1.22/welcome.adoc
asciidoc:
attributes:
source-language: asciidoc@
diff --git a/CN/modules/ROOT/images/p20.jpg b/CN/modules/ROOT/images/p20.jpg
new file mode 100644
index 0000000..b200c5a
Binary files /dev/null and b/CN/modules/ROOT/images/p20.jpg differ
diff --git a/CN/modules/ROOT/images/p21.jpg b/CN/modules/ROOT/images/p21.jpg
new file mode 100644
index 0000000..a0c62a6
Binary files /dev/null and b/CN/modules/ROOT/images/p21.jpg differ
diff --git a/CN/modules/ROOT/images/p22.jpg b/CN/modules/ROOT/images/p22.jpg
new file mode 100644
index 0000000..1736f47
Binary files /dev/null and b/CN/modules/ROOT/images/p22.jpg differ
diff --git a/CN/modules/ROOT/images/p31.png b/CN/modules/ROOT/images/p31.png
new file mode 100644
index 0000000..51e0e02
Binary files /dev/null and b/CN/modules/ROOT/images/p31.png differ
diff --git a/CN/modules/ROOT/images/p32.png b/CN/modules/ROOT/images/p32.png
new file mode 100644
index 0000000..d8cc211
Binary files /dev/null and b/CN/modules/ROOT/images/p32.png differ
diff --git a/CN/modules/ROOT/nav.adoc b/CN/modules/ROOT/nav.adoc
index 889241c..d987428 100644
--- a/CN/modules/ROOT/nav.adoc
+++ b/CN/modules/ROOT/nav.adoc
@@ -1,24 +1,38 @@
-* xref:v3.0/welcome.adoc[欢迎]
-* xref:v3.0/1.adoc[发行说明]
-* xref:v3.0/2.adoc[关于IvorySQL]
+* xref:v1.22/welcome.adoc[欢迎]
+* xref:v1.22/1.adoc[发行说明]
+* xref:v1.22/2.adoc[关于IvorySQL]
* IvorySQL入门
-** xref:v3.0/3.adoc[用户使用手册]
-** xref:v3.0/4.adoc[管理员指南]
-** xref:v3.0/5.adoc[运维人员指南]
-* xref:v3.0/6.adoc[安装部署]
-* xref:v3.0/7.adoc[开发者指南]
-* xref:v3.0/8.adoc[运维管理指南]
-* xref:v3.0/9.adoc[迁移指南]
-* xref:v3.0/10.adoc[社区贡献指南]
-* xref:v3.0/11.adoc[工具参考]
-* xref:v3.0/12.adoc[FAQ]
-* 功能列表
-** xref:v3.0/14.adoc[1、Ivorysql框架设计]
-** xref:v3.0/15.adoc[2、GUC框架]
-** xref:v3.0/16.adoc[3、大小写转换]
-** xref:v3.0/17.adoc[4、双模式设计]
-** xref:v3.0/18.adoc[5、兼容Oracle like]
-** xref:v3.0/19.adoc[6、兼容Oracle匿名块]
-** xref:v3.0/20.adoc[7、兼容Oracle函数与存储过程]
-** xref:v3.0/21.adoc[8、内置数据类型与内置函数]
-** xref:v3.0/22.adoc[9、新增Oracle兼容模式的端口与Ip]
+** xref:v1.22/3.adoc[快速开始]
+** xref:v1.22/4.adoc[日常监控]
+** xref:v1.22/5.adoc[日常维护]
+* IvorySQL高级
+** xref:v1.22/6.adoc[安装指南]
+** xref:v1.22/7.adoc[开发者指南]
+** xref:v1.22/8.adoc[运维管理指南]
+* IvorySQL生态
+** xref:v1.22/33.adoc[概述]
+** xref:v1.22/9.adoc[PostGIS]
+** xref:v1.22/10.adoc[pgvector]
+** xref:v1.22/34.adoc[PGroonga]
+** xref:v1.22/35.adoc[pgddl (DDL Extractor)]
+** xref:v1.22/36.adoc[pgRouting]
+** xref:v1.22/37.adoc[pg_cron]
+** xref:v1.22/38.adoc[pgsql-http]
+** xref:v1.22/40.adoc[pgvectorscale]
+* Oracle兼容功能列表
+** xref:v1.22/11.adoc[1、Ivorysql框架设计]
+** xref:v1.22/12.adoc[2、GUC框架]
+** xref:v1.22/13.adoc[3、大小写转换]
+** xref:v1.22/14.adoc[4、双模式设计]
+** xref:v1.22/15.adoc[5、兼容Oracle like]
+** xref:v1.22/16.adoc[6、兼容Oracle匿名块]
+** xref:v1.22/17.adoc[7、兼容Oracle函数与存储过程]
+** xref:v1.22/18.adoc[8、内置数据类型与内置函数]
+** xref:v1.22/19.adoc[9、新增Oracle兼容模式的端口与IP]
+* IvorySQL试验田
+** xref:v1.22/41.adoc[1、全局唯一索引]
+** xref:v1.22/42.adoc[2、新增无主键表默认支持逻辑复制]
+** xref:v1.22/43.adoc[3、修改列类型时自动重建依赖视图]
+* xref:v1.22/20.adoc[社区贡献指南]
+* xref:v1.22/21.adoc[工具参考]
+* xref:v1.22/22.adoc[FAQ]
diff --git a/CN/modules/ROOT/pages/v1.22/1.adoc b/CN/modules/ROOT/pages/v1.22/1.adoc
new file mode 100644
index 0000000..1b65edd
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/1.adoc
@@ -0,0 +1,67 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+## 版本介绍
+
+[**发行日期:2026年4月21日**]
+
+IvorySQL 1.22 基于 PostgreSQL 14.22,包含多种错误修复。
+
+## 增强功能
+
+- PostgreSQL 14.18-14.22 增强
+1. 避免在检查声明为 GB18030 编码的无效编码字符串时发生一字节缓冲区越界读取。
+2. 正确处理分区表上的自引用外键。
+3. 加强规划器估算函数中的安全检查。
+4. 防止 pg_dump 脚本被用于攻击执行恢复操作的用户。
+5. 在 `CREATE STATISTICS` 中检查对 schema 的 `CREATE` 权限。
+6. 避免 libpq 中分配大小计算时的整数溢出。
+7. 防范 `oidvector`/`int2vector` 的意外维度。
+8. 加固选择性估算器,防止其被附加到接受意外数据类型的操作符上。
+9. 修复在重放由旧版本生成的多事务截断 WAL 记录后的失败问题。
+10. 避免 `substring()` 应用于"toast"数据时产生无效编码的错误报告。
+更多详情,请访问 link:https://www.postgresql.org/docs/release/14.22/[PostgreSQL 发布说明]。
+
+## 主要特性
+
+- 升级至 PG 14.22 内核:link:https://github.com/IvorySQL/IvorySQL/pull/1223[Feature #1223] +
+ PostgreSQL 内核升级至 14.22 版本。
+
+- 全平台打包 +
+ 提供 X86、ARM、MIPS、LoongArch 架构的多平台介质包。
+
+- PostgreSQL 扩展 +
+ 新增支持 7 个 PostgreSQL 扩展:PostGIS、pgRouting、PGroonga、ddlx、pgsql-http、pgvector、pgvectorscale。
+
+- 全局唯一索引:link:https://github.com/IvorySQL/IvorySQL/pull/1230[Feature #1230] +
+ 提供使用非分区键确保跨分区唯一性的分区表唯一索引,在 Postgres 和 Oracle 兼容模式下均可用,并支持创建、附加、分离、插入和更新操作。
+
+- 基表列类型变更时自动重建视图:link:https://github.com/IvorySQL/IvorySQL/pull/1224[Feature #1224] +
+ 当执行列类型变更时,数据库自动保存所有依赖视图的定义,并在完成类型变更后按照正确的依赖顺序重建这些视图。
+
+- 无主键表的逻辑复制回退至 FULL IDENTITY:link:https://github.com/IvorySQL/IvorySQL/pull/1227[Feature #1227] +
+ 引入新的 GUC 参数 logical_replication_fallback_to_full_identity,允许逻辑复制对配置为 DEFAULT IDENTITY 但缺少主键的表自动回退至 REPLICA IDENTITY FULL。
+
+## 源代码
+
+IvorySQL 的研发工作主要通过以下两个核心代码库进行维护:
+- IvorySQL 数据库源代码:https://github.com/IvorySQL/IvorySQL
+- IvorySQL 官方网站:https://github.com/IvorySQL/Ivory-www
+
+## 贡献人员
+以下个人(按字母顺序排列)作为补丁作者、提交者、审阅者、测试者或问题报告者为本版本做出了贡献。
+
+* Chao Li
+* David Zhang
+* Grant Zhou
+* Oreo Yang
+* Shuntian Jiao
+* Steven Niu
+* Xiaohui Liu
+* Xinjie LYU
+* Xueyu Gao
+* Zheng Tao
+* Zhenhao Pan
+
+link:https://github.com/IvorySQL/IvorySQL/compare/IvorySQL_1.17...IvorySQL_1.22[完整变更日志]
diff --git a/CN/modules/ROOT/pages/v1.22/10.adoc b/CN/modules/ROOT/pages/v1.22/10.adoc
new file mode 100644
index 0000000..c95df54
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/10.adoc
@@ -0,0 +1,120 @@
+:sectnums:
+:sectnumlevels: 5
+
+= pgvector
+
+== 概述
+向量数据库是生成式人工智能(GenAI)的关键组成部分。pgvector作为PostgreSQL的重要扩展,不仅能够支持高达16000维度的向量计算,还提供了强大的向量操作和索引功能,使得PostgreSQL能够直接转化为高效的向量数据库。由于IvorySQL基于PostgreSQL研发,这使得它具备了与pgvector扩展无缝集成的能力,从而为用户提供了更广泛的数据处理和分析选项。在Oracle兼容模式下,pgvector扩展同样可用,这为Oracle用户使用向量数据库提供了极大的便利,使其能够轻松地迁移和管理数据,实现更高效的业务操作。
+
+
+== 原理介绍
+
+IVFFLAT和HNSW是PGVector的两个索引算法
+
+=== IVFFLAT
+
+IVFFLAT的工作原理是将相似的向量聚类为区域,并建立一个倒排索引,将每个区域映射到其向量。这使得查询可以集中在数据的一个子集上,从而实现快速搜索。通过调整列表和探针参数,ivfflat 可以平衡数据集的速度和准确性,使 PostgreSQL 有能力对复杂数据进行快速的语义相似性搜索。通过简单的查询,应用程序可以在数百万个高维向量中找到与查询向量最近的邻居。对于自然语言处理、信息检索等,ivfflat 是一个比较好的解决方案
+在建立 ivfflat 索引时,你需要决定索引中包含多少个 list。每个 list 代表一个 "中心";这些中心通过 k-means 算法计算而来。一旦确定了所有中心,ivfflat 就会确定每个向量最靠近哪个中心,并将其添加到索引中。当需要查询向量数据时,你可以决定要检查多少个中心,这由 ivfflat.probes 参数决定。这就是 ANN 性能/召回率的结果:访问的中心越多,结果就越精确,但这是以牺牲性能为代价的。
+
+=== HNSW
+
+HNSW (Hierarchical Navigating Small World) 是一种基于图的索引算法,它由多层的邻近图组成,因此称为分层的 NSW 方法。它会为一张图按规则建成多层导航图,并让越上层的图越稀疏,结点间的距离越远;越下层的图越稠密,结点间的距离越近。HNSW 算法是一种经典的空间换时间的算法,它的搜索质量和搜索速度都比较高,但是它的内存开销也比较大,因为不仅需要将所有的向量都存储在内存中。还需要维护一个图的结构,也同样需要存储。
+
+== 安装
+
+=== 源码安装
+
+** 设置PG_CONFIG环境变量
+```
+export PG_CONFIG=/usr/local/ivorysql//bin/pg_config
+```
+
+** 拉取pg_vector源码
+```
+git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git
+```
+
+** 安装 pgvector
+```
+cd pgvector
+
+sudo --preserve-env=PG_CONFIG make
+sudo --preserve-env=PG_CONFIG make install
+```
+
+** 创建pgvector扩展
+```
+[ivorysql@localhost ]$ psql
+psql
+Type "help" for help.
+
+ivorysql=# create extension vector;
+CREATE EXTENSION
+```
+至此,pgvector扩展安装已完成。
+更多用例,请参考 https://github.com/pgvector/pgvector?tab=readme-ov-file#getting-started[pgvector文档]
+
+== Oracle兼容性
+
+在IvorySQL Oracle兼容模式下,pgvector扩展同样可以正确运行
+[TIP]
+建议用户使用1521端口进行测试, psql -p 1521
+
+=== 数据类型
+
+```
+ivorysql=# CREATE TABLE items5 (id bigserial PRIMARY KEY, name varchar2(20), num number(20), embedding bit(3));
+CREATE TABLE
+ivorysql=# INSERT INTO items5 (name, num, embedding) VALUES ('1st oracle data',0, '000'), ('2nd oracle data', 111, '111');
+INSERT 0 2
+ivorysql=# SELECT * FROM items5 ORDER BY bit_count(embedding # '101') LIMIT 5;
+ id | name | num | embedding
+----+-----------------+-----+-----------
+ 2 | 2nd oracle data | 111 | 111
+ 1 | 1st oracle data | 0 | 000
+```
+
+=== 匿名块
+
+```
+ivorysql=# declare
+i vector(3) := '[1,2,3]';
+begin
+raise notice '%', i;
+end;
+ivorysql-# /
+NOTICE: [1,2,3]
+DO
+```
+
+=== 存储过程(PROCEDURE)
+```
+ivorysql=# CREATE OR REPLACE PROCEDURE ora_procedure()
+AS
+p vector(3) := '[4,5,6]';
+begin
+raise notice '%', p;
+end;
+/
+CREATE PROCEDURE
+ivorysql=# call ora_procedure();
+NOTICE: [4,5,6]
+CALL
+```
+
+==== 函数(FUNCTION)
+```
+ivorysql=# CREATE OR REPLACE FUNCTION AddVector(a vector(3), b vector(3))
+RETURN vector(3)
+IS
+BEGIN
+RETURN a + b;
+END;
+/
+CREATE FUNCTION
+ivorysql=# SELECT AddVector('[1,2,3]','[4,5,6]') FROM DUAL;
+ addvector
+----------------
+ [5,7,9]
+(1 row)
+```
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v3.0/14.adoc b/CN/modules/ROOT/pages/v1.22/11.adoc
similarity index 100%
rename from CN/modules/ROOT/pages/v3.0/14.adoc
rename to CN/modules/ROOT/pages/v1.22/11.adoc
diff --git a/CN/modules/ROOT/pages/v3.0/15.adoc b/CN/modules/ROOT/pages/v1.22/12.adoc
similarity index 97%
rename from CN/modules/ROOT/pages/v3.0/15.adoc
rename to CN/modules/ROOT/pages/v1.22/12.adoc
index 3585295..5615018 100644
--- a/CN/modules/ROOT/pages/v3.0/15.adoc
+++ b/CN/modules/ROOT/pages/v1.22/12.adoc
@@ -24,7 +24,6 @@
| ivorysql.database_mode | 表示当前数据库的模式(pg/oracle),可以通过show命令查看,set/reset/reset all命令不影响该变量
| ivorysql.datetime_ignore_nls_mask | 表示日期格式是否会受NLS参数影响,默认为0,可以通过set命令设置,reset 命令重置,reset all命令会重置该变量
| ivorysql.enable_emptystring_to_NULL | 取值为(on/off),该变量为on时,会将插入的空字符串转成NULL值存储
-| ivorysql.identifier_case_switch | 设置字符大小写转换模式
| ivorysql.listen_address | 表示兼容模式监听的地址,在初始化数据库时,从ivorysql.conf文件中读取该配置,在配置文件中修改该值,需要重启数据库生效,可以通过show命令查看
| ivorysql.port | 表示兼容模式下连接的端口号,在初始化数据库时,从ivorysql.conf文件中读取该配置,在配置文件中修改该值,需要重启数据库生效,可以通过show命令查看
| nls_date_format | 表示默认的日期格式,可以通过show命令查看,默认为‘YYYY-MM-DD’,可以通过set命令设置,可以通过reset命令重置回默认值,reset all 命令会重置该变量
diff --git a/CN/modules/ROOT/pages/v1.22/13.adoc b/CN/modules/ROOT/pages/v1.22/13.adoc
new file mode 100644
index 0000000..e46f642
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/13.adoc
@@ -0,0 +1,285 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+= 引用标识符的大小写转换设计
+
+== 目的
+
+- 为了满足PG和Oracle的引用标识符大小写兼容,ivorysql设计了三种引用标识符的大小写转换模式。通过guc参数“identifier_case_switch”选择转换模式;
+
+== 功能
+
+=== 大小写转换的三种模式(默认为interchange)
+
+- 如果 guc参数“identifier_case_switch”值为“normal”
+
+ 1). 保持双引号所引用的标识符中的字母大小写不变。
+
+- 如果 guc参数“identifier_case_switch”值为“interchange”:
+
+ 1). 如果双引号所引用的标识符中的字母全部为大写,则将大写转换为小写。
+
+ 2). 如果双引号所引用的标识符中的字母全部为小写,则将小写转换为大写。
+
+ 3). 如果用双引号引起来的标识符中的字母是大小写混合的,则保持标识符不变。
+
+- 如果 guc参数“identifier_case_switch”值为“lowercase”
+
+ 1). 如果双引号所引用的标识符中的字母全部为大写,则将大写转换为小写。
+
+ 2). 如果用双引号引起来的标识符中的字母是大小写混合的,则保持标识符不变。
+
+=== 初始化数据库集簇时
+
+- 在initdb程序中加入 -C选项设置大小写转换模式,-C对应的值为:
+
+ "normal" ------ "0"同义
+
+ "interchange" ------ "1"同义
+
+ "lowercase" ------ "2"同义
+
+ 在初始化数据库集簇的过程中,将大小写转换模式保存到data目录的global/pg_control文件中。
+
+=== 经典用例
+
+**normal**
+```
+ivorysql=# SET ivorysql.compatible_mode to oracle;
+SET
+
+ivorysql=# SET ivorysql.enable_case_switch = true;
+SET
+
+ivorysql=# SET ivorysql.identifier_case_switch = normal;
+SET
+
+ivorysql=# CREATE TABLE "NORMAL_1"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# CREATE TABLE "Normal_2"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# CREATE TABLE "normal_3"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# select * from "NORMAL_1";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "Normal_1";
+ERROR: relation "Normal_1" does not exist
+LINE 1: select * from "Normal_1";
+
+ivorysql=# select * from "normal_1";
+ERROR: relation "normal" does not exist
+LINE 1: select * from "normal";
+
+ivorysql=# select * from NORMAL_1;
+ERROR: relation "normal_1" does not exist
+LINE 1: select * from NORMAL_1;
+
+ivorysql=# select * from "Normal_2";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "NORMAL_2";
+ERROR: relation "NORMAL_2" does not exist
+LINE 1: select * from "NORMAL_2";
+
+ivorysql=# select * from "normal_2";
+ERROR: relation "normal_2" does not exist
+LINE 1: select * from "normal_2";
+
+ivorysql=# select * from Normal_2;
+ERROR: relation "normal_2" does not exist
+LINE 1: select * from Normal_2;
+
+ivorysql=# select * from "normal_3";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "NORMAL_3";
+ERROR: relation "NORMAL_3" does not exist
+LINE 1: select * from "NORMAL_3";
+
+ivorysql=# select * from "Normal_3";
+ERROR: relation "Normal_3" does not exist
+LINE 1: select * from "Normal_3";
+
+ivorysql=# drop table "NORMAL_1";
+DROP TABLE
+ivorysql=# drop table "Normal_2";
+DROP TABLE
+ivorysql=# drop table "normal_3";
+DROP TABLE
+```
+
+**interchange**
+```
+ivorysql=# SET ivorysql.compatible_mode to oracle;
+SET
+
+ivorysql=# SET ivorysql.enable_case_switch = true;
+SET
+
+ivorysql=# SET ivorysql.identifier_case_switch = interchange;
+SET
+
+ivorysql=# CREATE TABLE "INTER_CHANGE_1"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# CREATE TABLE "Inter_Change_2"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# CREATE TABLE "inter_change_3"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# select * from "INTER_CHANGE_1";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "Inter_Change_1";
+ERROR: relation "Inter_Change_1" does not exist
+LINE 1: select * from "Inter_Change_1";
+
+ivorysql=# select * from "inter_change_1";
+ERROR: relation "INTER_CHANGE_1" does not exist
+LINE 1: select * from "inter_change_1";
+
+ivorysql=# select * from INTER_CHANGE_1;
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "Inter_Change_2";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "INTER_CHANGE_2";
+ERROR: relation "inter_change_2" does not exist
+LINE 1: select * from "INTER_CHANGE_2";
+
+ivorysql=# select * from "inter_change_2";
+ERROR: relation "INTER_CHANGE_2" does not exist
+LINE 1: select * from "inter_change_2";
+
+ivorysql=# select * from Inter_Change_2;
+ERROR: relation "inter_change_2" does not exist
+LINE 1: select * from Inter_Change_2;
+
+ivorysql=# select * from "inter_change_3";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "INTER_CHANGE_3";
+ERROR: relation "inter_change_3" does not exist
+LINE 1: select * from "INTER_CHANGE_3";
+
+ivorysql=# select * from "Inter_Change_3";
+ERROR: relation "Inter_Change_3" does not exist
+LINE 1: select * from "Inter_Change_3";
+
+ivorysql=# select * from inter_change_3;
+ERROR: relation "inter_change_3" does not exist
+LINE 1: select * from "INTER_CHANGE_3";
+
+ivorysql=# drop table "INTER_CHANGE_1";
+DROP TABLE
+ivorysql=# drop table "Inter_Change_2";
+DROP TABLE
+ivorysql=# drop table "inter_change_3";
+DROP TABLE
+```
+
+**lowercase**
+```
+ivorysql=# SET ivorysql.compatible_mode to oracle;
+SET
+
+ivorysql=# SET ivorysql.enable_case_switch = true;
+SET
+
+ivorysql=# SET ivorysql.identifier_case_switch = lowercase;
+SET
+
+ivorysql=# CREATE TABLE "LOWER_CASE_1"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# CREATE TABLE "Lower_Case_2"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# CREATE TABLE "lower_case_3"(c1 int, c2 int);
+CREATE TABLE
+
+ivorysql=# select * from "LOWER_CASE_1";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "Lower_Case_1";
+ERROR: relation "Lower_Case_1" does not exist
+LINE 1: select * from "Lower_Case_1";
+
+ivorysql=# select * from "lower_case_1";
+ c1 | c2
+----+----
+(0 行记录)
+
+
+ivorysql=# select * from LOWER_CASE_1;
+ c1 | c2
+----+----
+(0 行记录)
+
+
+ivorysql=# select * from "Lower_Case_2";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "LOWER_CASE_2";
+ERROR: relation "lower_case_2" does not exist
+LINE 1: select * from "LOWER_CASE_2";
+
+ivorysql=# select * from "lower_case_2";
+ERROR: relation "lower_case_2" does not exist
+LINE 1: select * from "lower_case_2";
+
+ivorysql=# select * from Lower_Case_2;
+ERROR: relation "lower_case_2" does not exist
+LINE 1: select * from Lower_Case_2;
+
+ivorysql=# select * from "lower_case_3";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "LOWER_CASE_3";
+ c1 | c2
+----+----
+(0 rows)
+
+ivorysql=# select * from "Lower_Case_3";
+ERROR: relation "Lower_Case_3" does not exist
+LINE 1: select * from "Lower_Case_3";
+
+ivorysql=# select * from LOWER_CASE_3;
+ c1 | c2
+----+----
+(0 行记录)
+
+ivorysql=# drop table "NORMAL_1";
+DROP TABLE
+ivorysql=# drop table "Normal_2";
+DROP TABLE
+ivorysql=# drop table "normal_3";
+DROP TABLE
+```
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v3.0/17.adoc b/CN/modules/ROOT/pages/v1.22/14.adoc
similarity index 95%
rename from CN/modules/ROOT/pages/v3.0/17.adoc
rename to CN/modules/ROOT/pages/v1.22/14.adoc
index d8efbf6..9f72a34 100644
--- a/CN/modules/ROOT/pages/v3.0/17.adoc
+++ b/CN/modules/ROOT/pages/v1.22/14.adoc
@@ -1,33 +1,33 @@
-:sectnums:
-:sectnumlevels: 5
-
-:imagesdir: ./_images
-
-= 双模式设计
-
-== 目的
-
-- 为了满足PG模式和兼容Oracle模式,Ivorysql设计了pg和oracle两种模式。并且可以在initdb时指定模式;
-
-== 功能
-
-- Initdb -m 初始化,需要判断不同的模式,其中Oracle模式下,需要执行postgres_oracle.bki的SQL语句;
-- 启动时会根据初始化模式,判断是否为oracle兼容模式。
-
-```
-database_mode:用于表示初始化模式;
-database_mode=DB_PG,PG模式,且不可切换;
-database_mode=DB_ORACLE,Oracle兼容模式;
-```
-
-== 测试用例
-
-```
-初始化PG模式:
-./initdb -D ../data -m pg
-
-初始化oracle兼容模式:
-./initdb -D ../data -m oracle
-或
-./initdb -D ../data
-```
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 双模式设计
+
+== 目的
+
+- 为了满足PG模式和兼容Oracle模式,Ivorysql设计了pg和oracle两种模式。并且可以在initdb时指定模式;
+
+== 功能
+
+- Initdb -m 初始化,需要判断不同的模式,其中Oracle模式下,需要执行postgres_oracle.bki的SQL语句;
+- 启动时会根据初始化模式,判断是否为oracle兼容模式。
+
+```
+database_mode:用于表示初始化模式;
+database_mode=DB_PG,PG模式,且不可切换;
+database_mode=DB_ORACLE,Oracle兼容模式;
+```
+
+== 测试用例
+
+```
+初始化PG模式:
+./initdb -D ../data -m pg
+
+初始化oracle兼容模式:
+./initdb -D ../data -m oracle
+或
+./initdb -D ../data
+```
diff --git a/CN/modules/ROOT/pages/v3.0/18.adoc b/CN/modules/ROOT/pages/v1.22/15.adoc
similarity index 98%
rename from CN/modules/ROOT/pages/v3.0/18.adoc
rename to CN/modules/ROOT/pages/v1.22/15.adoc
index 0cf48a5..890b3f1 100644
--- a/CN/modules/ROOT/pages/v3.0/18.adoc
+++ b/CN/modules/ROOT/pages/v1.22/15.adoc
@@ -1,69 +1,69 @@
-:sectnums:
-:sectnumlevels: 5
-
-:imagesdir: ./_images
-
-= 兼容Oracle like
-
-== 目的
-
-- 本文档意在为使用 like 模糊查询的人员提供一个深入了解兼容Oracle 的模糊查询like实现的过程,是like兼容的实现文档。
-
-== 功能说明
-|====
-|数据库名称|like模糊查询
-|oracle|oracle的字符串类型是varchar2,支持对数字、日期、字符串字段类型的列用Like关键字配合通配符来实现模糊查询
-|IvorySQL|IvorySQL的字符串基本类型是text,所以like是以text为基础上,其他IvorySQL的类型能隐式转换成text,这样不用创建opeartor就能自动转换
-|====
-
-== 测试用例
-
-```
-
-create table t_ora_like (id int ,str1 varchar(8), date1 timestamp with time zone, date2 time with time zone, num int, str2 varchar(8));
-insert into t_ora_like (id ,str1 ,date1 ,date2) values (123456,'test1','2022-09-26 16:39:20','2022-09-26 16:39:20');
-insert into t_ora_like (id ,str1 ,date1 ,date2) values (123457,'test2','2022-09-26 16:40:20','2022-09-26 16:40:20');
-insert into t_ora_like (id ,str1 ,date1 ,date2) values (223456,'test3','2022-09-26 16:41:20','2022-09-26 16:41:20');
-insert into t_ora_like (id ,str1 ,date1 ,date2) values (123458,'test4','2022-09-26 16:42:20','2022-09-26 16:42:20');
-
-select * from t_ora_like where str1 like 'test%';
- id | str1 | date1 | date2 | num | str2
---------+-------+-----------------------------------+-------------+-----+------
- 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
- 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
- 223456 | test3 | 2022-09-26 16:41:20.000000 +08:00 | 16:41:20+08 | |
- 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
-(4 rows)
-
-select * from t_ora_like where date1 like '2022%';
- id | str1 | date1 | date2 | num | str2
---------+-------+-----------------------------------+-------------+-----+------
- 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
- 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
- 223456 | test3 | 2022-09-26 16:41:20.000000 +08:00 | 16:41:20+08 | |
- 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
-(4 rows)
-
-select * from t_ora_like where date2 like '16%';
- id | str1 | date1 | date2 | num | str2
---------+-------+-----------------------------------+-------------+-----+------
- 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
- 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
- 223456 | test3 | 2022-09-26 16:41:20.000000 +08:00 | 16:41:20+08 | |
- 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
-(4 rows)
-
-select * from t_ora_like where id like '123%';
- id | str1 | date1 | date2 | num | str2
---------+-------+-----------------------------------+-------------+-----+------
- 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
- 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
- 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
-(3 rows)
-
-select * from t_ora_like where id like null;
- id | str1 | date1 | date2 | num | str2
-----+------+-------+-------+-----+------
-(0 rows)
-
-```
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 兼容Oracle like
+
+== 目的
+
+- 本文档意在为使用 like 模糊查询的人员提供一个深入了解兼容Oracle 的模糊查询like实现的过程,是like兼容的实现文档。
+
+== 功能说明
+|====
+|数据库名称|like模糊查询
+|oracle|oracle的字符串类型是varchar2,支持对数字、日期、字符串字段类型的列用Like关键字配合通配符来实现模糊查询
+|IvorySQL|IvorySQL的字符串基本类型是text,所以like是以text为基础上,其他IvorySQL的类型能隐式转换成text,这样不用创建opeartor就能自动转换
+|====
+
+== 测试用例
+
+```
+
+create table t_ora_like (id int ,str1 varchar(8), date1 timestamp with time zone, date2 time with time zone, num int, str2 varchar(8));
+insert into t_ora_like (id ,str1 ,date1 ,date2) values (123456,'test1','2022-09-26 16:39:20','2022-09-26 16:39:20');
+insert into t_ora_like (id ,str1 ,date1 ,date2) values (123457,'test2','2022-09-26 16:40:20','2022-09-26 16:40:20');
+insert into t_ora_like (id ,str1 ,date1 ,date2) values (223456,'test3','2022-09-26 16:41:20','2022-09-26 16:41:20');
+insert into t_ora_like (id ,str1 ,date1 ,date2) values (123458,'test4','2022-09-26 16:42:20','2022-09-26 16:42:20');
+
+select * from t_ora_like where str1 like 'test%';
+ id | str1 | date1 | date2 | num | str2
+--------+-------+-----------------------------------+-------------+-----+------
+ 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
+ 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
+ 223456 | test3 | 2022-09-26 16:41:20.000000 +08:00 | 16:41:20+08 | |
+ 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
+(4 rows)
+
+select * from t_ora_like where date1 like '2022%';
+ id | str1 | date1 | date2 | num | str2
+--------+-------+-----------------------------------+-------------+-----+------
+ 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
+ 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
+ 223456 | test3 | 2022-09-26 16:41:20.000000 +08:00 | 16:41:20+08 | |
+ 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
+(4 rows)
+
+select * from t_ora_like where date2 like '16%';
+ id | str1 | date1 | date2 | num | str2
+--------+-------+-----------------------------------+-------------+-----+------
+ 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
+ 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
+ 223456 | test3 | 2022-09-26 16:41:20.000000 +08:00 | 16:41:20+08 | |
+ 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
+(4 rows)
+
+select * from t_ora_like where id like '123%';
+ id | str1 | date1 | date2 | num | str2
+--------+-------+-----------------------------------+-------------+-----+------
+ 123456 | test1 | 2022-09-26 16:39:20.000000 +08:00 | 16:39:20+08 | |
+ 123457 | test2 | 2022-09-26 16:40:20.000000 +08:00 | 16:40:20+08 | |
+ 123458 | test4 | 2022-09-26 16:42:20.000000 +08:00 | 16:42:20+08 | |
+(3 rows)
+
+select * from t_ora_like where id like null;
+ id | str1 | date1 | date2 | num | str2
+----+------+-------+-------+-----+------
+(0 rows)
+
+```
diff --git a/CN/modules/ROOT/pages/v3.0/19.adoc b/CN/modules/ROOT/pages/v1.22/16.adoc
similarity index 91%
rename from CN/modules/ROOT/pages/v3.0/19.adoc
rename to CN/modules/ROOT/pages/v1.22/16.adoc
index ef13fd8..e552dc6 100644
--- a/CN/modules/ROOT/pages/v3.0/19.adoc
+++ b/CN/modules/ROOT/pages/v1.22/16.adoc
@@ -1,49 +1,47 @@
-:sectnums:
-:sectnumlevels: 5
-
-:imagesdir: ./_images
-
-= 兼容Oracle匿名块
-
-== 目的
-
-- 本文档是PLSQL匿名块(anonymous block)兼容Oracle语法功能的设计文档,目的是可以在IvorySQL中兼容Oracle的匿名块语句。
-
-== 功能说明
-
-- 匿名块是能够动态地创建和执行过程代码的PLSQL结构,而不需要以持久化的方式将代码作为数据库对象储存在系统目录中。本次实现中IvorySQL主要兼容的是PLSQL匿名块的语法格式,我们主要处理的部分包括客户端工具psql、主服务器和PSQL端支持。
-
-== 测试用例
-
-```
-
-declare
-i integer := 10;
-begin
- raise notice '%', i;
- raise notice '%', main.i;
-end;
-/
-NOTICE: 10
-NOTICE: 10
-
-```
-
-```
-
-DECLARE
- grade CHAR(1);
-BEGIN
- grade := 'B';
- CASE grade
- WHEN 'A' THEN raise notice 'Excellent';
- WHEN 'B' THEN raise notice 'Very Good';
- END CASE;
-EXCEPTION
- WHEN CASE_NOT_FOUND THEN
- raise notice 'No such grade';
-END;
-/
-NOTICE: Very Good
-
-```
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 兼容Oracle匿名块
+
+== 目的
+
+- 本文档是PLSQL匿名块(anonymous block)兼容Oracle语法功能的设计文档,目的是可以在IvorySQL中兼容Oracle的匿名块语句。
+
+== 功能说明
+
+- 匿名块是能够动态地创建和执行过程代码的PLSQL结构,而不需要以持久化的方式将代码作为数据库对象储存在系统目录中。本次实现中IvorySQL主要兼容的是PLSQL匿名块的语法格式,我们主要处理的部分包括客户端工具psql、主服务器和PSQL端支持。
+
+== 测试用例
+
+```
+
+declare
+i integer := 10;
+begin
+ raise notice '%', i;
+end;
+/
+NOTICE: 10
+
+```
+
+```
+
+DECLARE
+ grade CHAR(1);
+BEGIN
+ grade := 'B';
+ CASE grade
+ WHEN 'A' THEN raise notice 'Excellent';
+ WHEN 'B' THEN raise notice 'Very Good';
+ END CASE;
+EXCEPTION
+ WHEN CASE_NOT_FOUND THEN
+ raise notice 'No such grade';
+END;
+/
+NOTICE: Very Good
+
+```
diff --git a/CN/modules/ROOT/pages/v3.0/20.adoc b/CN/modules/ROOT/pages/v1.22/17.adoc
similarity index 95%
rename from CN/modules/ROOT/pages/v3.0/20.adoc
rename to CN/modules/ROOT/pages/v1.22/17.adoc
index 33b7ea2..8801dc4 100644
--- a/CN/modules/ROOT/pages/v3.0/20.adoc
+++ b/CN/modules/ROOT/pages/v1.22/17.adoc
@@ -1,101 +1,97 @@
-:sectnums:
-:sectnumlevels: 5
-
-:imagesdir: ./_images
-
-= 兼容Oracle函数与存储过程
-
-== 目的
-
-- 本文档意在兼容Oracle PLSQL函数和存储过程的语法,在IvorySQL中我们称其为PLISQL语言。
-
-== 功能说明
-
-.函数(FUNCTION)
-|====
-|CREATE FUNCTION语法支持EDITIONABLE/NONEDITIONABLE
-|CREATE FUNCTION语法支持RETURN, IS关键字,不指定language
-|CREATE FUNCTION语法函数没有参数,函数名后面不带()
-|CREATE FUNCTION参数个数最多是32767
-|CREATE FUNCTION语法中END; 在psql中以/结束
-|CREATE FUNCTION语法变量声明前面没有DECLARE关键字
-|CREATE FUNCTION语法支持OUT 参数NOCOPY功能
-|CREATE FUNCTION语法支持sharing_clause
-|CREATE FUNCTION语法支持invoker_rights_clause,默认权限改成DR(DEFINER)
-|CREATE FUNCTION语法支持ACCESSIBLE BY
-|CREATE FUNCTION语法支持DEFAULT COLLATION
-|CREATE FUNCTION语法支持result_cache_clause
-|CREATE FUNCTION语法支持aggregate_clause
-|CREATE FUNCTION语法支持pipelined_clause
-|CREATE FUNCTION语法支持sql_macro_clause
-|ALTER FUNCTION语法
-|函数和存储过程相关的视图
-|====
-
-
-.存储过程(PROCEDURE)
-|====
-|CREATE PROCEDURE语法支持EDITIONABLE/NONEDITIONABLE
-|CREATE PROCEDURE语法函数没有参数,函数名后面不带()
-|CREATE PROCEDURE参数个数最多是32767
-|CREATE PROCEDURE语法中END; 在psql中以/结束
-|CREATE PROCEDURE语法支持sharing_clause
-|CREATE PROCEDURE语法支持DEFAULT COLLATION
-|CREATE PROCEDURE语法支持invoker_rights_clause
-|CREATE PROCEDURE语法支持ACCESSIBLE BY
-|ALTER PROCEDURE语法
-|存储过程没有参数,调用支持不带()
-|存储过程调用支持EXEC
-|在PL/SQL 中调用存储过程,可以省略CALL,直接使用存储过程名字
-|支持--和/**/两种注释方法
-|====
-
-
-== 测试用例
-
-```
-
-CREATE or replace FUNCTION ora_func RETURN integer AS
-BEGIN
- RETURN 1;
-END;
-/
-
-CREATE OR REPLACE FUNCTION test_nocopy(a IN int, b OUT NOCOPY int, c IN OUT NOCOPY int)
-RETURN record
-IS
-BEGIN
- b := a;
- c := a;
-END;
-/
-
-```
-```
-
-CREATE OR REPLACE PROCEDURE ora_procedure()
-AS
- p integer := 20;
-begin
- raise notice '%', p;
-end;
-/
-call ora_procedure();
-
-CREATE OR REPLACE PROCEDURE ora_procedure
-SHARING = METADATA
-DEFAULT COLLATION USING_NLS_COMP
-AUTHID CURRENT_USER
-ACCESSIBLE BY ( FUNCTION A.B )
-IS
- p integer := 20;
-begin
- raise notice '%', p;
-end;
-/
-
-```
-
-
-
-
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 兼容Oracle函数与存储过程
+
+== 目的
+
+- 本文档意在兼容Oracle PLSQL函数和存储过程的语法,在IvorySQL中我们称其为PLISQL语言。
+
+== 功能说明
+
+.函数(FUNCTION)
+|====
+|CREATE FUNCTION语法支持EDITIONABLE/NONEDITIONABLE
+|CREATE FUNCTION语法支持RETURN, IS关键字,不指定language
+|CREATE FUNCTION语法函数没有参数,函数名后面不带()
+|CREATE FUNCTION参数个数最多是32767
+|CREATE FUNCTION语法中END; 在psql中以/结束
+|CREATE FUNCTION语法变量声明前面没有DECLARE关键字
+|CREATE FUNCTION语法支持OUT 参数NOCOPY功能
+|CREATE FUNCTION语法支持sharing_clause
+|CREATE FUNCTION语法支持invoker_rights_clause,默认权限改成DR(DEFINER)
+|CREATE FUNCTION语法支持ACCESSIBLE BY
+|CREATE FUNCTION语法支持DEFAULT COLLATION
+|CREATE FUNCTION语法支持result_cache_clause
+|CREATE FUNCTION语法支持aggregate_clause
+|CREATE FUNCTION语法支持pipelined_clause
+|CREATE FUNCTION语法支持sql_macro_clause
+|ALTER FUNCTION语法
+|函数和存储过程相关的视图
+|====
+
+
+.存储过程(PROCEDURE)
+|====
+|CREATE PROCEDURE语法支持EDITIONABLE/NONEDITIONABLE
+|CREATE PROCEDURE语法函数没有参数,函数名后面不带()
+|CREATE PROCEDURE参数个数最多是32767
+|CREATE PROCEDURE语法中END; 在psql中以/结束
+|CREATE PROCEDURE语法支持sharing_clause
+|CREATE PROCEDURE语法支持DEFAULT COLLATION
+|CREATE PROCEDURE语法支持invoker_rights_clause
+|CREATE PROCEDURE语法支持ACCESSIBLE BY
+|ALTER PROCEDURE语法
+|存储过程没有参数,调用支持不带()
+|存储过程调用支持EXEC
+|在PL/SQL 中调用存储过程,可以省略CALL,直接使用存储过程名字
+|支持--和/**/两种注释方法
+|====
+
+
+== 测试用例
+
+```
+
+CREATE or replace FUNCTION ora_func RETURN integer AS
+BEGIN
+ RETURN 1;
+END;
+/
+
+CREATE OR REPLACE FUNCTION test_nocopy(a IN int, b OUT NOCOPY int, c IN OUT NOCOPY int)
+RETURN record
+IS
+BEGIN
+ b := a;
+ c := a;
+END;
+/
+
+```
+```
+
+CREATE OR REPLACE PROCEDURE ora_procedure()
+AS
+ p integer := 20;
+begin
+ raise notice '%', p;
+end;
+/
+call ora_procedure();
+
+CREATE OR REPLACE PROCEDURE ora_procedure
+SHARING = METADATA
+DEFAULT COLLATION USING_NLS_COMP
+AUTHID CURRENT_USER
+ACCESSIBLE BY ( FUNCTION A.B )
+IS
+ p integer := 20;
+begin
+ raise notice '%', p;
+end;
+/
+
+```
diff --git a/CN/modules/ROOT/pages/v3.0/21.adoc b/CN/modules/ROOT/pages/v1.22/18.adoc
similarity index 93%
rename from CN/modules/ROOT/pages/v3.0/21.adoc
rename to CN/modules/ROOT/pages/v1.22/18.adoc
index 91d1171..1a511db 100644
--- a/CN/modules/ROOT/pages/v3.0/21.adoc
+++ b/CN/modules/ROOT/pages/v1.22/18.adoc
@@ -1,965 +1,1033 @@
-:sectnums:
-:sectnumlevels: 5
-
-:imagesdir: ./_images
-
-= 内置数据类型与内置函数
-
-== 内置数据类型
-
-|====
-|char
-|varchar
-|varchar2
-|number
-|binary_float
-|binary_double
-|date
-|timestamp
-|timestamp with time zone
-|timestamp with local time zone
-|interval year to month
-|interval day to second
-|raw
-|long
-|====
-
-== 内置函数类型
-
-|====
-|sysdate
-|systimestamp
-|add_months
-|last_day
-|next_day
-|months_between
-|current_date
-|current_timestamp
-|new_time
-|tz_offset
-|trunc
-|instrb
-|substr
-|substrb
-|trim
-|ltrim
-|rtrim
-|length
-|lengthb
-|rawtohex
-|replace
-|regexp_replace
-|regexp_substr
-|regexp_instr
-|regexp_like
-|to_number
-|to_char
-|to_date
-|to_timestamp
-|to_timestamp_tz
-|to_yminterval
-|to_dsinterval
-|numtodsinterval
-|numtoyminterval
-|localtimestamp
-|from_tz
-|sys_extract_utc
-|sessiontimezone
-|hextoraw
-|uid
-|USERENV
-|====
-
-== 内置函数说明
-
-1、兼容sysdate函数,功能:查看对应的日期与时间,测试用例如下:
-查询当前系统的日期:
-
-```
-select sysdate() from dual;
- sysdate
-------------
- 2023-07-06
-(1 row)
-```
-
-查询往前推1天的日期:
-
-```
-select sysdate()-1 from dual;
- ?column?
-------------
- 2023-07-05
-(1 row)
-```
-
-2、兼容systimestamp函数,功能:返回本机数据库上当前系统日期和时间(包括微秒和时区),测试用例如下:
-查询当前日期的日期和时间:
-
-```
-select systimestamp() from dual;
- systimestamp
------------------------------------
- 2023-07-06 10:18:31.674322 +08:00
-(1 row)
-```
-
-3、兼容add_months函数,功能:函数将一个月数(n)添加一个日期,并返回相隔n月的同一天,支持参数:date, number;测试用例如下:
-查询当前日期(七月六日)的下个月的同一天:
-
-```
-select add_months(sysdate(),1) from dual;
- add_months
-------------
- 2023-08-06
-(1 row)
-```
-
-查询当前日期的上个月的同一天:
-
-```
-select add_months(sysdate(),-1) from dual;
- add_months
-------------
- 2023-06-06
-(1 row)
-```
-
-4、兼容last_day函数,功能:返回指定日期所在月份的最后一天,支持参数:date,测试用例如下:
-查询当天所在月份的最后一天:
-
-```
-select last_day(sysdate())from dual;
- last_day
-------------
- 2023-07-31
-(1 row)
-```
-
-查询某一天所在月份的最后一天:
-
-```
-select last_day(to_date('2019-09-01'))from dual;
- last_day
-------------
- 2019-09-30
-(1 row)
-```
-
-5、兼容next_day函数,功能:返回指定日期的下一个日期。支持参数:date, integer /date ,text, 说明:当函数中第二个参数传的星期数比现有星期数小时,会返回下一个星期的日期;当函数中第二个参数所传的日期比现有星期数大,会返回本周相应星期日期。测试用例如下:
-查询当前日期的下一天:
-
-```
-select next_day(sysdate(),1) from dual;
- next_day
-------------
- 2023-07-07
-(1 row)
-```
-
-查询当前日期的下个星期五:
-
-```
-select next_day(sysdate(),'FRIDAY') from dual;
- next_day
-------------
- 2023-07-07
-(1 row)
-```
-
-6、兼容months_between函数,功能:返回日期类型的date1和date2之间相差的月份,支持参数:date,date,说明:如果date1晚于date2,返回正数;如果date1早于date2返回负数;如果date1和date2是某月里的同一天,返回结果为整数;如果不是同一天,会在每月31天的基础上返回带有小数部分的结果。测试用例如下:
-查询不同月份同一天之间相差的月份:
-
-```
-select months_between(to_date('2023-07-06'),to_date('2023-08-06')) from dual;
- months_between
-----------------
- -1
-(1 row)
-```
-
-查询不同月份不同日期之间相差的月份:
-
-```
-select months_between(to_date('2023-07-06'),to_date('2023-08-05')) from dual;
- months_between
---------------------
- -0.967741935483871
-(1 row)
-```
-
-7、兼容current_date函数,功能:返回当前时区的当前日期,测试用例如下:
-查询当前时区的当前日期:
-
-```
-select current_date from dual;
- current_date
---------------
- 2023-07-06
-(1 row)
-```
-
-8、兼容current_timestamp函数,功能:返回当前时区的当前日期与当前时间,包含当前时区信息。支持参数:integer, 说明:返回的时间可调整精度。测试用例如下:
-查询当前时区的当前日期与时间:
-
-```
-select current_timestamp from dual;
- current_timestamp
------------------------------------
- 2023-07-06 10:27:01.440600 +08:00
-(1 row)
-```
-
-查询当前时区的当前日期与时间(精度调整为前三位小数):
-
-```
-select current_timestamp(3) from dual;
- current_timestamp
------------------------------------
- 2023-07-06 10:27:14.182000 +08:00
-(1 row)
-```
-
-9、兼容new_time函数,功能:返回某个时间在某时区所对应的在另一个时区的日期,支持参数:date, text, text ,测试用例如下:
-返回当前日期在另一个时区对应的日期:
-
-```
-select sysdate() bj_time,new_time(sysdate(),'PDT','GMT')los_angles from dual;
- bj_time | los_angles
-------------+------------
- 2023-07-06 | 2023-07-06
-(1 row)
-```
-
-10、兼容tz_offset函数,功能:返回给定时区与标准时区的偏移量,支持参数:text,测试用例如下:
-返回给定时区与标准时区偏移量:
-
-```
-select tz_offset('US/Eastern') from dual;
- tz_offset
------------
- -04:00
-(1 row)
-```
-
-11、兼容trunc函数,功能:可以截取日期,得到想要的数值,如年,月,日,时,分,支持参数:date/date,text,测试用例如下:
-截取当前日期:
-
-```
-select trunc(sysdate()) from dual;
- trunc
-------------
- 2023-07-06
-(1 row)
-```
-
-截取年,返回值只有年是正确的,月和日不是准确值:
-
-```
-select trunc(sysdate(),'yyyy') from dual;
- trunc
-------------
- 2023-01-01
-(1 row)
-```
-
-截取月,返回值只有月是正确的,年和日不是准确值:
-
-```
-select trunc(sysdate(),'mm') from dual;
- trunc
-------------
- 2023-07-01
-(1 row)
-```
-
-12、兼容instrb函数,功能:字符串查找函数,返回字符串的位置,支持参数: varchar2, text, number DEFAULT 1, number DEFAULT 1,以下为测试用例:
-返回CORPORATE FLOOR中默认第一次出现OR时字符串的位置:
-
-```
-SELECT INSTRB('CORPORATE FLOOR','OR') "Instring in bytes" FROM DUAL;
- Instring in bytes
--------------------
- 2
-(1 row)
-```
-
-返回corporate floor中从第五个字符开始查询,第二次出现or时字符串的位置:
-
-```
-SELECT INSTRB('CORPORATE FLOOR','OR',5,2) "Instring in bytes" FROM DUAL;
- Instring in bytes
--------------------
- 14
-(1 row)
-```
-
-13、兼容substr函数,功能:截取字符串函数,以字符为单位截取,支持参数:text, integer, 测试用例如下:
-截取’今天天气很好’中从第五个字符开始,往后的字符串:
-
-```
-SELECT SUBSTR('今天天气很好',5) "Substring with bytes" FROM DUAL;
-
- Substring with bytes
-----------------------
- 很好
-(1 row)
-```
-
-14、兼容substrb函数,功能:截取字符串函数,以字节为单位截取,支持参数:varchar2, number/varchar2, number,number,测试用例如下:
-截取’今天天气很好’中从第五个字节开始,往后的字符串:
-
-```
-SELECT SUBSTRB('今天天气很好',5) "Substring with bytes" FROM DUAL;
- Substring with bytes
-----------------------
- 天气很好
-(1 row)
-```
-
-截取’今天天气很好’中从第五个字节开始,第八个字节结束的字符串:
-
-```
-SELECT SUBSTRB('今天天气很好',5,8) "Substring with bytes" FROM DUAL;
- Substring with bytes
-----------------------
- 天气
-(1 row)
-```
-
-15、兼容trim函数,功能:去除指定字符串的左右空格或对应数据,支持参数:varchar2 /varchar2,varchar2,测试用例如下:
-去除' aaa bbb ccc '的左右空格:
-
-```
-select trim(' aaa bbb ccc ')trim from dual;
- trim
--------------
- aaa bbb ccc
-(1 row)
-```
-
-去除'aaa bbb ccc'中的aaa:
-
-```
-select trim('aaa bbb ccc','aaa')trim from dual;
- trim
-----------
- bbb ccc
-(1 row)
-```
-
-16、兼容ltrim函数,功能:去除指定字符串的左侧空格或对应数据,支持参数:varchar2 /varchar2,varchar2,测试用例如下:
-去除' abcdefg '的左侧空格:
-
-```
-select ltrim(' abcdefg ')ltrim from dual;
- ltrim
-------------
- abcdefg
-(1 row)
-```
-
-从'abcdefg'左侧开始遍历,一旦存在某字符出现在'fegab'中就去除,不存在则返回结果:
-
-```
-select ltrim('abcdefg','fegab')ltrim from dual;
- ltrim
--------
- cdefg
-(1 row)
-```
-
-17、兼容rtrim函数,功能:去除指定字符串的右侧空格,测试用例如下:
-去除' abcdefg '的右侧空格:
-
-```
-select rtrim(' abcdefg ')rtrim from dual;
- rtrim
-----------------
- abcdefg
-(1 row)
-```
-
-从'abcdefg'右侧开始遍历,一旦存在某字符出现在'fegab'中就去除,不存在则返回结果:
-
-```
-select rtrim('abcdefg','fegab')rtrim from dual;
- rtrim
--------
- abcd
-(1 row)
-```
-
-18、兼容length函数,功能:求取指定字符串字符的长度,支持参数:char/integer/varchar2测试用例如下:
-查询223的字符长度:
-
-```
-select length(223) from dual;
- length
---------
- 3
-(1 row)
-```
-
-查询'223'的字符长度:
-
-```
-select length('223') from dual;
- length
---------
- 3
-(1 row)
-```
-
-查询'ivorysql数据库'的字符长度:
-
-```
-select length('ivorysql数据库') from dual;
- length
---------
- 11
-(1 row)
-```
-
-19、兼容lengthb功能:求取指定字符串字节的长度,支持参数:char/bytea/varchar2测试用例如下:
-查询'ivorysql'的字节长度:
-
-```
-select lengthb('ivorysq'::char) from dual;
- lengthb
----------
- 1
-(1 row)
-```
-
-查询'0x2C'的字节长度:
-
-```
-select lengthb('0x2C'::bytea) from dual;
- lengthb
----------
- 4
-(1 row)
-```
-
-查询'ivorysql数据库'的字节长度:
-
-```
-select lengthb('ivorysql数据库'::varchar2) from dual;
- lengthb
----------
- 17
-(1 row)
-```
-
-20、兼容replace函数,功能:替换指定字符串中的字符或删除字符,支持参数:text, text, text/varchar2, varchar2, varchar2 DEFAULT NULL::varchar2, 测试用例如下:
-替换'jack and jue'中的'j'为'bl':
-
-```
-select replace('jack and jue','j','bl') from dual;
- replace
-----------------
- black and blue
-(1 row)
-```
-
-删除'jack and jue'中的'j':
-
-```
-select replace('jack and jue','j') from dual;
- replace
-------------
- ack and ue
-(1 row)
-```
-
-21、兼容regexp_replace函数,此函数为replace函数的扩展。功能:用于通过正则表达式来进行匹配替换。支持参数:text, text, text /text, text, text, integer/varchar2, varchar2/varchar2, varchar2 varchar2, 测试用例如下:
-将匹配到的数字替换为*#:
-
-```
-select regexp_replace('01234abcd56789','[0-9]','*#')from dual;
- regexp_replace
---------------------------
- *#*#*#*#*#abcd*#*#*#*#*#
-(1 row)
-```
-
-从第二个数开始将匹配到的数字替换为*#:
-
-```
-select regexp_replace('01234abcd56789','[0-9]','*#',2)from dual;
- regexp_replace
--------------------------
- 0*#*#*#*#abcd*#*#*#*#*#
-```
-
-删除'01234abcd56789'中的'01':
-
-```
-select regexp_replace('01234abcd56789','01')from dual;
- regexp_replace
-----------------
- 234abcd56789
-(1 row)
-```
-
-用'xxx'替换01234abcd56789'中的012:
-
-```
-select regexp_replace('01234abcd56789','012','xxx')from dual;
- regexp_replace
-----------------
- xxx34abcd56789
-(1 row)
-```
-
-22、兼容regexp_substr函数,功能:拾取合符正则表达式描述的字符子串,支持参数:text, text,integer /text, text, integer, integer/ text, text, integer, integer, text /varchar2 ,varchar2,测试用例如下:
-查询'012ab34'中从第一个数开始的012字串:
-
-```
-select regexp_substr('012ab34', '012',1) from dual;
- regexp_substr
----------------
- 012
-(1 row)
-```
-
-查询'012ab34'中从第一个数第一组开始的012字串:
-```
-select regexp_substr('012ab34', '012',1,1) from dual;
- regexp_substr
----------------
- 012
-(1 row)
-```
-
-查询'012a012Ab34'中从第一个数第一组开始不区分大小写的012字串:
-
-```
-select regexp_substr('012a012Ab34', '012A',1,1,'i') from dual;
- regexp_substr
----------------
- 012a
-(1 row)
-```
-
-查询'012a012Ab34'中从第一个数第一组开始区分大小写的012字串:
-
-```
-select regexp_substr('012a012Ab34', '012A',1,1,'c') from dual;
- regexp_substr
----------------
- 012A
-(1 row)
-```
-
-查询'数据库'中 '数据'子串:
-
-```
-select regexp_substr('数据库', '数据') from dual;
- regexp_substr
----------------
- 数据
-(1 row)
-```
-
-23、兼容regexp_instr函数,功能:用于标定符合正则表达式的字符子串的开始位置,支持参数:text, text,integer /text, text, integer, integer/ text, text, integer, integer, text/text, text, integer, integer, text, integer/ varchar2, varchar2,测试用例如下:
-查询'abcaBcabc'中从第一个字符开始,出现abc子串的位置:
-
-```
-SELECT regexp_instr('abcaBcabc', 'abc', 1);
- regexp_instr
---------------
- 1
-(1 row)
-```
-
-查询'abcaBcabc'中从第一个字符开始,第三次出现abc子串的位置:
-
-```
-SELECT regexp_instr('abcaBcabc', 'abc', 1, 3);
- regexp_instr
---------------
- 7
-(1 row)
-```
-
-查询'abcabcabc'中从第一个字符开始,第二次出现abc子串后发生的位置:
-
-```
-SELECT regexp_instr('abcaBcabc', 'abc', 1, 2,1);
- regexp_instr
---------------
- 7
-(1 row)
-```
-
-查询'abcaBcabc'中从第一个字符开始,第一次出现abc子串后发生的位置(区分大小写):
-
-```
-SELECT regexp_instr('abcaBcabc', 'abc',1,2,1,'c');
- regexp_instr
---------------
- 7
-(1 row)
-```
-
-查询'数据库'中'库'出现的位置:
-
-```
-SELECT regexp_instr('数据库', '库');
- regexp_instr
---------------
- 3
-(1 row)
-```
-
-24、兼容regexp_like函数,功能:与like类似,用于模糊查询。支持参数:varchar2, varchar2 /varchar2, varchar2 varchar2,
-首先创建一个regexp_like表用于测试用例查询:
-
-```
-create table t_regexp_like
-(
- id varchar(4),
- value varchar(10)
-
-);
-insert into t_regexp_like values ('1','1234560');
-insert into t_regexp_like values ('2','1234560');
-insert into t_regexp_like values ('3','1b3b560');
-insert into t_regexp_like values ('4','abc');
-insert into t_regexp_like values ('5','abcde');
-insert into t_regexp_like values ('6','ADREasx');
-insert into t_regexp_like values ('7','123 45');
-insert into t_regexp_like values ('8','adc de');
-insert into t_regexp_like values ('9','adc,.de');
-insert into t_regexp_like values ('10','abcbvbnb');
-insert into t_regexp_like values ('11','11114560');
-```
-
-测试用例如下:
-查询t_regexp_like表中带有abc的列:
-
-```
-select * from t_regexp_like where regexp_like(value,'abc');
- id | value
-----+----------
- 4 | abc
- 5 | abcde
- 10 | abcbvbnb
-(3 rows)
-
-```
-
-查询t_regexp_like表中带有ABC的列(不区分大小写):
-
-```
-select * from t_regexp_like where regexp_like(value,'ABC','i');
- id | value
-----+----------
- 4 | abc
- 5 | abcde
- 10 | abcbvbnb
-(3 rows)
-
-```
-
-25、兼容to_number函数,功能:是将一些处理过的按一定格式编排过的字符串变回数值型的格式,支持参数:text/text,text测试用例如下:
-将字符串'-34,338,492'转换为数值型格式:
-
-```
-SELECT to_number('34,338,492', '99,999,999') from dual;
- to_number
------------
- -34338492
-(1 row)
-```
-
-将字符串'5.01-'转换为数值型格式:
-
-```
-SELECT to_number('5.01-', '9.99S');
-
- to_number
------------
- -5.01
-(1 row)
-```
-
-26、兼容to_char函数,功能:将数字或日期转换为字符类型,支持参数:date/date,text/timestamp/timestamp,text测试用例如下:
-将当前系统日期转换为字符格式:
-
-```
-select to_char(sysdate()) from dual;
- to_char
-------------
- 2023-07-10
-(1 row)
-```
-
-将当前系统日期转换为月份/日期/年字符格式:
-
-```
-select to_char(sysdate(),'mm/dd/yyyy') from dual;
- to_char
-------------
- 07/10/2023
-(1 row)
-```
-
-将当前日期的timestamp格式转换为字符格式:
-
-```
-SELECT to_char(sysdate()::timestamp);
- to_char
-----------------------------
- 2023-07-10 09:46:44.000000
-```
-
-将当前日期的timestamp格式转换为月份/日期/年字符格式:
-
-```
-SELECT to_char(sysdate()::timestamp,'MM-YYYY-DD');
- to_char
-------------
- 07-2023-10
-(1 row)
-```
-
-27、兼容to_date函数,功能:将字符类型转换为日期类型,支持参数:text/text,text测试用例如下:
-将'2023/07/06'转换为日期类型:
-
-```
-select to_date('20230706') from dual;
- to_date
-------------
- 2023-07-06
-(1 row)
-```
-
-将'-44-02-01'转换为日期类型:
-
-```
-SELECT to_date('-44,0201','YYYY-MM-DD');
- to_date
-------------
- 0044-02-01
-(1 row)
-```
-
-28、兼容to_timestamp函数,功能:可以存储年、月、日、小时、分钟、秒,同时还可以存储秒的小数部分。支持参数:text/text,text测试用例如下:
-查询'2018-11-02 12:34:56.025'以日期形式输出:
-
-```
-SELECT to_timestamp('20181102.12.34.56.025');
- to_timestamp
-----------------------------
- 2018-11-02 12:34:56.025000
-(1 row)
-```
-
-查询’2011,12,18 11:38’以日期形式输出:
-
-```
-SELECT to_timestamp('2011,12,18 11:38 ', 'YYYY-MM-DD HH24:MI:SS');
- to_timestamp
-----------------------------
- 2011-12-18 11:38:00.000000
-(1 row)
-```
-
-29、兼容to_timestamp_tz函数,功能:根据时间查询,时间字符串有T,Z并有毫秒,时区。测试用例如下:
-查询'2016-10-9 14:10:10.123000'以日期形式输出:
-
-```
- SELECT to_timestamp_tz('2016-10-9 14:10:10.123000') FROM DUAL;
- to_timestamp_tz
------------------------------------
- 2016-10-09 14:10:10.123000 +08:00
-(1 row)
-```
-
-查询'10-9-2016 14:10:10.123000 +8:30'以日期形式输出:
-
-```
- SELECT to_timestamp_tz('10-9-2016 14:10:10.123000 +8:30', 'DD-MM-YYYY HH24:MI:SS.FF TZH:TZM') FROM DUAL;
- to_timestamp_tz
------------------------------------
- 2016-09-10 13:40:10.123000 +08:00
-(1 row)
-```
-
-30、兼容to_yminterval函数,功能:将一个字符串类型转化为年和月的时间差类型,支持参数:text, 测试用例如下:
-查询'20110101'以后两个年零八个月后的日期:
-
-```
-select to_date('20110101','yyyymmdd')+to_yminterval('02-08') from dual;
- ?column?
-------------
- 2013-09-01
-(1 row)
-```
-
-31、兼容to_dsinterval函数,功能:将一个日期加上一定的小时或者天数变成另外一个日期,支持参数:text,测试用例如下:
-查询当前系统时间加上9个半小时后的日期(当前为2023-07-06,18:00):
-
-```
-select sysdate()+to_dsinterval('0 09:30:00')as newdate from dual;
- newdate
-------------
- 2023-07-07
-(1 row)
-```
-
-32、兼容numtodsinterval函数,功能:将数字转换成时间间隔类型的数据。支持参数:double precision, text测试用例如下:
-转换100.00个小时为时间间隔类型数据:
-
-```
-SELECT NUMTODSINTERVAL(100.00, 'hour');
- numtodsinterval
--------------------------------
- +000000004 04:00:00.000000000
-(1 row)
-```
-
-转换100分钟为时间间隔类型数据:
-
-```
-SELECT NUMTODSINTERVAL(100, 'minute');
- numtodsinterval
--------------------------------
- +000000000 01:40:00.000000000
-(1 row)
-```
-
-33、兼容numtoyminterval函数,功能:将数字转换成日期间隔类型的数据。
-支持参数:double precision,text,测试用例如下:
-转换1.00,year为日期间隔:
-
-```
-SELECT NUMTOYMINTERVAL(1.00,'year');
- numtoyminterval
------------------
- +000000001-00
-(1 row)
-```
-
-转换1,mouth为日期间隔:
-
-```
-SELECT NUMTOYMINTERVAL(1,'month');
- numtoyminterval
------------------
- +000000000-01
-(1 row)
-```
-
-34、兼容localtimestamp函数,功能:返回会话中的日期和时间,支持参数:integer, 函数中增加参数为精度,测试用例如下:
-返回当前会话中的日期和时间:
-
-```
-select localtimestamp from dual;
- localtimestamp
-----------------------------
- 2023-07-07 09:18:15.896472
-(1 row)
-```
-
-返回当前会话中的日期和时间(精度为1):
-
-```
-select localtimestamp(1) from dual;
- localtimestamp
-----------------------------
- 2023-07-07 09:18:16.100000
-(1 row)
-```
-
-35、兼容from_tz函数,功能:将时间从一个时区转换为另一个时区,支持参数;timestamp, text ,测试用例如下:
-将'2000-03-28 08:00:00', '3:00'转换为当前时区:
-
-```
-SELECT FROM_TZ(TIMESTAMP '2000-03-28 08:00:00', '3:00') FROM DUAL;
- from_tz
------------------------------------
- 2000-03-28 13:00:00.000000 +08:00
-(1 row)
-```
-
-36、兼容sys_extract_utc函数,功能:将一个timestamptz转换为UTC时区时间。支持参数:timestamp with time zone 测试用例如下:
-查询转换timestamp '2000-03-28 11:30:00.00 -8:00'为UTC时区后的时间:
-
-```
-select sys_extract_utc(timestamp '2000-03-28 11:30:00.00 -8:00') from dual;
- sys_extract_utc
-----------------------------
- 2000-03-28 19:30:00.000000
-(1 row)
-```
-
-37、兼容sessiontimezone函数,功能:查看时区详细信息,测试用例如下:
-查看当前时区的详细信息:
-
-```
-select sessiontimezone() from dual;
- sessiontimezone
------------------
- Asia/Shanghai
-(1 row)
-```
-
-修改timezone后,查看时区相信信息:
-
-```
-set timezone = 'Asia/Hong_Kong';
-SET
-select sessiontimezone() from dual;
- sessiontimezone
------------------
- Asia/Hong_Kong
-(1 row)
-```
-
-38、兼容hextoraw函数,功能:将字符串表示的二进制数值转换为一个raw数值。支持参数:text,测试用例如下:
-将字符串'abcdef'转换为raw数值:
-
-```
-select hextoraw('abcdef')from dual;
- hextoraw
-----------
- \xabcdef
-(1 row)
-```
-
-39、兼容uid函数,功能:获取数据库的实例名。测试用例如下:
-获取当前数据库的实例名:
-
-```
-select uid() from dual;
- uid
------
- 10
-(1 row)
-```
-
-40、兼容USERENV函数,功能:返回当前用户环境的信息,测试用例如下:
-查看当前用户是否是dba,如果是返回ture:
-
-```
-select userenv('isdba')from dual;
- get_isdba
------------
- TRUE
-(1 row)
-```
-
-查看会话标志:
-
-```
-select userenv('sessionid')from dual;
- get_sessionid
----------------
- 1
-(1 row)
-```
-
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 内置数据类型与内置函数
+
+== 内置数据类型
+
+|====
+|char
+|varchar
+|varchar2
+|number
+|binary_float
+|binary_double
+|date
+|timestamp
+|timestamp with time zone
+|timestamp with local time zone
+|interval year to month
+|interval day to second
+|raw
+|long
+|====
+
+== 内置函数类型
+
+|====
+|sysdate
+|systimestamp
+|add_months
+|last_day
+|next_day
+|months_between
+|current_date
+|current_timestamp
+|new_time
+|tz_offset
+|trunc
+|instrb
+|substr
+|substrb
+|trim
+|ltrim
+|rtrim
+|length
+|lengthb
+|replace
+|regexp_replace
+|regexp_substr
+|regexp_instr
+|regexp_like
+|to_number
+|to_char
+|to_date
+|to_timestamp
+|to_timestamp_tz
+|to_yminterval
+|to_dsinterval
+|numtodsinterval
+|numtoyminterval
+|localtimestamp
+|from_tz
+|sys_extract_utc
+|sessiontimezone
+|hextoraw
+|uid
+|USERENV
+|asciistr
+|to_multi_byte
+|to_single_byte
+|compose
+|decompose
+|====
+
+== 内置函数说明
+
+1、兼容sysdate函数,功能:查看对应的日期与时间,测试用例如下:
+查询当前系统的日期:
+
+```
+select sysdate() from dual;
+ sysdate
+------------
+ 2023-07-06
+(1 row)
+```
+
+查询往前推1天的日期:
+
+```
+select sysdate()-1 from dual;
+ ?column?
+------------
+ 2023-07-05
+(1 row)
+```
+
+2、兼容systimestamp函数,功能:返回本机数据库上当前系统日期和时间(包括微秒和时区),测试用例如下:
+查询当前日期的日期和时间:
+
+```
+select systimestamp() from dual;
+ systimestamp
+-----------------------------------
+ 2023-07-06 10:18:31.674322 +08:00
+(1 row)
+```
+
+3、兼容add_months函数,功能:函数将一个月数(n)添加一个日期,并返回相隔n月的同一天,支持参数:date, number;测试用例如下:
+查询当前日期(七月六日)的下个月的同一天:
+
+```
+select add_months(sysdate(),1) from dual;
+ add_months
+------------
+ 2023-08-06
+(1 row)
+```
+
+查询当前日期的上个月的同一天:
+
+```
+select add_months(sysdate(),-1) from dual;
+ add_months
+------------
+ 2023-06-06
+(1 row)
+```
+
+4、兼容last_day函数,功能:返回指定日期所在月份的最后一天,支持参数:date,测试用例如下:
+查询当天所在月份的最后一天:
+
+```
+select last_day(sysdate())from dual;
+ last_day
+------------
+ 2023-07-31
+(1 row)
+```
+
+查询某一天所在月份的最后一天:
+
+```
+select last_day(to_date('2019-09-01'))from dual;
+ last_day
+------------
+ 2019-09-30
+(1 row)
+```
+
+5、兼容next_day函数,功能:返回指定日期的下一个日期。支持参数:date, integer /date ,text, 说明:当函数中第二个参数传的星期数比现有星期数小时,会返回下一个星期的日期;当函数中第二个参数所传的日期比现有星期数大,会返回本周相应星期日期。测试用例如下:
+查询当前日期的下一天:
+
+```
+select next_day(sysdate(),1) from dual;
+ next_day
+------------
+ 2023-07-07
+(1 row)
+```
+
+查询当前日期的下个星期五:
+
+```
+select next_day(sysdate(),'FRIDAY') from dual;
+ next_day
+------------
+ 2023-07-07
+(1 row)
+```
+
+6、兼容months_between函数,功能:返回日期类型的date1和date2之间相差的月份,支持参数:date,date,说明:如果date1晚于date2,返回正数;如果date1早于date2返回负数;如果date1和date2是某月里的同一天,返回结果为整数;如果不是同一天,会在每月31天的基础上返回带有小数部分的结果。测试用例如下:
+查询不同月份同一天之间相差的月份:
+
+```
+select months_between(to_date('2023-07-06'),to_date('2023-08-06')) from dual;
+ months_between
+----------------
+ -1
+(1 row)
+```
+
+查询不同月份不同日期之间相差的月份:
+
+```
+select months_between(to_date('2023-07-06'),to_date('2023-08-05')) from dual;
+ months_between
+--------------------
+ -0.967741935483871
+(1 row)
+```
+
+7、兼容current_date函数,功能:返回当前时区的当前日期,测试用例如下:
+查询当前时区的当前日期:
+
+```
+select current_date from dual;
+ current_date
+--------------
+ 2023-07-06
+(1 row)
+```
+
+8、兼容current_timestamp函数,功能:返回当前时区的当前日期与当前时间,包含当前时区信息。支持参数:integer, 说明:返回的时间可调整精度。测试用例如下:
+查询当前时区的当前日期与时间:
+
+```
+select current_timestamp from dual;
+ current_timestamp
+-----------------------------------
+ 2023-07-06 10:27:01.440600 +08:00
+(1 row)
+```
+
+查询当前时区的当前日期与时间(精度调整为前三位小数):
+
+```
+select current_timestamp(3) from dual;
+ current_timestamp
+-----------------------------------
+ 2023-07-06 10:27:14.182000 +08:00
+(1 row)
+```
+
+9、兼容new_time函数,功能:返回某个时间在某时区所对应的在另一个时区的日期,支持参数:date, text, text ,测试用例如下:
+返回当前日期在另一个时区对应的日期:
+
+```
+select sysdate() bj_time,new_time(sysdate(),'PDT','GMT')los_angles from dual;
+ bj_time | los_angles
+------------+------------
+ 2023-07-06 | 2023-07-06
+(1 row)
+```
+
+10、兼容tz_offset函数,功能:返回给定时区与标准时区的偏移量,支持参数:text,测试用例如下:
+返回给定时区与标准时区偏移量:
+
+```
+select tz_offset('US/Eastern') from dual;
+ tz_offset
+-----------
+ -04:00
+(1 row)
+```
+
+11、兼容trunc函数,功能:可以截取日期,得到想要的数值,如年,月,日,时,分,支持参数:date/date,text,测试用例如下:
+截取当前日期:
+
+```
+select trunc(sysdate()) from dual;
+ trunc
+------------
+ 2023-07-06
+(1 row)
+```
+
+截取年,返回值只有年是正确的,月和日不是准确值:
+
+```
+select trunc(sysdate(),'yyyy') from dual;
+ trunc
+------------
+ 2023-01-01
+(1 row)
+```
+
+截取月,返回值只有月是正确的,年和日不是准确值:
+
+```
+select trunc(sysdate(),'mm') from dual;
+ trunc
+------------
+ 2023-07-01
+(1 row)
+```
+
+12、兼容instrb函数,功能:字符串查找函数,返回字符串的位置,支持参数: varchar2, text, number DEFAULT 1, number DEFAULT 1,以下为测试用例:
+返回CORPORATE FLOOR中默认第一次出现OR时字符串的位置:
+
+```
+SELECT INSTRB('CORPORATE FLOOR','OR') "Instring in bytes" FROM DUAL;
+ Instring in bytes
+-------------------
+ 2
+(1 row)
+```
+
+返回corporate floor中从第五个字符开始查询,第二次出现or时字符串的位置:
+
+```
+SELECT INSTRB('CORPORATE FLOOR','OR',5,2) "Instring in bytes" FROM DUAL;
+ Instring in bytes
+-------------------
+ 14
+(1 row)
+```
+
+13、兼容substr函数,功能:截取字符串函数,以字符为单位截取,支持参数:text, integer, 测试用例如下:
+截取’今天天气很好’中从第五个字符开始,往后的字符串:
+
+```
+SELECT SUBSTR('今天天气很好',5) "Substring with bytes" FROM DUAL;
+
+ Substring with bytes
+----------------------
+ 很好
+(1 row)
+```
+
+14、兼容substrb函数,功能:截取字符串函数,以字节为单位截取,支持参数:varchar2, number/varchar2, number,number,测试用例如下:
+截取’今天天气很好’中从第五个字节开始,往后的字符串:
+
+```
+SELECT SUBSTRB('今天天气很好',5) "Substring with bytes" FROM DUAL;
+ Substring with bytes
+----------------------
+ 天气很好
+(1 row)
+```
+
+截取’今天天气很好’中从第五个字节开始,第八个字节结束的字符串:
+
+```
+SELECT SUBSTRB('今天天气很好',5,8) "Substring with bytes" FROM DUAL;
+ Substring with bytes
+----------------------
+ 天气
+(1 row)
+```
+
+15、兼容trim函数,功能:去除指定字符串的左右空格或对应数据,支持参数:varchar2 /varchar2,varchar2,测试用例如下:
+去除' aaa bbb ccc '的左右空格:
+
+```
+select trim(' aaa bbb ccc ')trim from dual;
+ trim
+-------------
+ aaa bbb ccc
+(1 row)
+```
+
+去除'aaa bbb ccc'中的aaa:
+
+```
+select trim('aaa bbb ccc','aaa')trim from dual;
+ trim
+----------
+ bbb ccc
+(1 row)
+```
+
+16、兼容ltrim函数,功能:去除指定字符串的左侧空格或对应数据,支持参数:varchar2 /varchar2,varchar2,测试用例如下:
+去除' abcdefg '的左侧空格:
+
+```
+select ltrim(' abcdefg ')ltrim from dual;
+ ltrim
+------------
+ abcdefg
+(1 row)
+```
+
+从'abcdefg'左侧开始遍历,一旦存在某字符出现在'fegab'中就去除,不存在则返回结果:
+
+```
+select ltrim('abcdefg','fegab')ltrim from dual;
+ ltrim
+-------
+ cdefg
+(1 row)
+```
+
+17、兼容rtrim函数,功能:去除指定字符串的右侧空格,测试用例如下:
+去除' abcdefg '的右侧空格:
+
+```
+select rtrim(' abcdefg ')rtrim from dual;
+ rtrim
+----------------
+ abcdefg
+(1 row)
+```
+
+从'abcdefg'右侧开始遍历,一旦存在某字符出现在'fegab'中就去除,不存在则返回结果:
+
+```
+select rtrim('abcdefg','fegab')rtrim from dual;
+ rtrim
+-------
+ abcd
+(1 row)
+```
+
+18、兼容length函数,功能:求取指定字符串字符的长度,支持参数:char/integer/varchar2测试用例如下:
+查询223的字符长度:
+
+```
+select length(223) from dual;
+ length
+--------
+ 3
+(1 row)
+```
+
+查询'223'的字符长度:
+
+```
+select length('223') from dual;
+ length
+--------
+ 3
+(1 row)
+```
+
+查询'ivorysql数据库'的字符长度:
+
+```
+select length('ivorysql数据库') from dual;
+ length
+--------
+ 11
+(1 row)
+```
+
+19、兼容lengthb功能:求取指定字符串字节的长度,支持参数:char/bytea/varchar2测试用例如下:
+查询'ivorysql'的字节长度:
+
+```
+select lengthb('ivorysq'::char) from dual;
+ lengthb
+---------
+ 1
+(1 row)
+```
+
+查询'0x2C'的字节长度:
+
+```
+select lengthb('0x2C'::bytea) from dual;
+ lengthb
+---------
+ 4
+(1 row)
+```
+
+查询'ivorysql数据库'的字节长度:
+
+```
+select lengthb('ivorysql数据库'::varchar2) from dual;
+ lengthb
+---------
+ 17
+(1 row)
+```
+
+20、兼容replace函数,功能:替换指定字符串中的字符或删除字符,支持参数:text, text, text/varchar2, varchar2, varchar2 DEFAULT NULL::varchar2, 测试用例如下:
+替换'jack and jue'中的'j'为'bl':
+
+```
+select replace('jack and jue','j','bl') from dual;
+ replace
+----------------
+ black and blue
+(1 row)
+```
+
+删除'jack and jue'中的'j':
+
+```
+select replace('jack and jue','j') from dual;
+ replace
+------------
+ ack and ue
+(1 row)
+```
+
+21、兼容regexp_replace函数,此函数为replace函数的扩展。功能:用于通过正则表达式来进行匹配替换。支持参数:text, text, text /text, text, text, integer/varchar2, varchar2/varchar2, varchar2 varchar2, 测试用例如下:
+将匹配到的数字替换为*#:
+
+```
+select regexp_replace('01234abcd56789','[0-9]','*#')from dual;
+ regexp_replace
+--------------------------
+ *#*#*#*#*#abcd*#*#*#*#*#
+(1 row)
+```
+
+从第二个数开始将匹配到的数字替换为*#:
+
+```
+select regexp_replace('01234abcd56789','[0-9]','*#',2)from dual;
+ regexp_replace
+-------------------------
+ 0*#*#*#*#abcd*#*#*#*#*#
+```
+
+删除'01234abcd56789'中的'01':
+
+```
+select regexp_replace('01234abcd56789','01')from dual;
+ regexp_replace
+----------------
+ 234abcd56789
+(1 row)
+```
+
+用'xxx'替换01234abcd56789'中的012:
+
+```
+select regexp_replace('01234abcd56789','012','xxx')from dual;
+ regexp_replace
+----------------
+ xxx34abcd56789
+(1 row)
+```
+
+22、兼容regexp_substr函数,功能:拾取合符正则表达式描述的字符子串,支持参数:text, text,integer /text, text, integer, integer/ text, text, integer, integer, text /varchar2 ,varchar2,测试用例如下:
+查询'012ab34'中从第一个数开始的012字串:
+
+```
+select regexp_substr('012ab34', '012',1) from dual;
+ regexp_substr
+---------------
+ 012
+(1 row)
+```
+
+查询'012ab34'中从第一个数第一组开始的012字串:
+```
+select regexp_substr('012ab34', '012',1,1) from dual;
+ regexp_substr
+---------------
+ 012
+(1 row)
+```
+
+查询'012a012Ab34'中从第一个数第一组开始不区分大小写的012字串:
+
+```
+select regexp_substr('012a012Ab34', '012A',1,1,'i') from dual;
+ regexp_substr
+---------------
+ 012a
+(1 row)
+```
+
+查询'012a012Ab34'中从第一个数第一组开始区分大小写的012字串:
+
+```
+select regexp_substr('012a012Ab34', '012A',1,1,'c') from dual;
+ regexp_substr
+---------------
+ 012A
+(1 row)
+```
+
+查询'数据库'中 '数据'子串:
+
+```
+select regexp_substr('数据库', '数据') from dual;
+ regexp_substr
+---------------
+ 数据
+(1 row)
+```
+
+23、兼容regexp_instr函数,功能:用于标定符合正则表达式的字符子串的开始位置,支持参数:text, text,integer /text, text, integer, integer/ text, text, integer, integer, text/text, text, integer, integer, text, integer/ varchar2, varchar2,测试用例如下:
+查询'abcaBcabc'中从第一个字符开始,出现abc子串的位置:
+
+```
+SELECT regexp_instr('abcaBcabc', 'abc', 1);
+ regexp_instr
+--------------
+ 1
+(1 row)
+```
+
+查询'abcaBcabc'中从第一个字符开始,第三次出现abc子串的位置:
+
+```
+SELECT regexp_instr('abcaBcabc', 'abc', 1, 3);
+ regexp_instr
+--------------
+ 7
+(1 row)
+```
+
+查询'abcabcabc'中从第一个字符开始,第二次出现abc子串后发生的位置:
+
+```
+SELECT regexp_instr('abcaBcabc', 'abc', 1, 2,1);
+ regexp_instr
+--------------
+ 7
+(1 row)
+```
+
+查询'abcaBcabc'中从第一个字符开始,第一次出现abc子串后发生的位置(区分大小写):
+
+```
+SELECT regexp_instr('abcaBcabc', 'abc',1,2,1,'c');
+ regexp_instr
+--------------
+ 7
+(1 row)
+```
+
+查询'数据库'中'库'出现的位置:
+
+```
+SELECT regexp_instr('数据库', '库');
+ regexp_instr
+--------------
+ 3
+(1 row)
+```
+
+24、兼容regexp_like函数,功能:与like类似,用于模糊查询。支持参数:varchar2, varchar2 /varchar2, varchar2 varchar2,
+首先创建一个regexp_like表用于测试用例查询:
+
+```
+create table t_regexp_like
+(
+ id varchar(4),
+ value varchar(10)
+
+);
+insert into t_regexp_like values ('1','1234560');
+insert into t_regexp_like values ('2','1234560');
+insert into t_regexp_like values ('3','1b3b560');
+insert into t_regexp_like values ('4','abc');
+insert into t_regexp_like values ('5','abcde');
+insert into t_regexp_like values ('6','ADREasx');
+insert into t_regexp_like values ('7','123 45');
+insert into t_regexp_like values ('8','adc de');
+insert into t_regexp_like values ('9','adc,.de');
+insert into t_regexp_like values ('10','abcbvbnb');
+insert into t_regexp_like values ('11','11114560');
+```
+
+测试用例如下:
+查询t_regexp_like表中带有abc的列:
+
+```
+select * from t_regexp_like where regexp_like(value,'abc');
+ id | value
+----+----------
+ 4 | abc
+ 5 | abcde
+ 10 | abcbvbnb
+(3 rows)
+
+```
+
+查询t_regexp_like表中带有ABC的列(不区分大小写):
+
+```
+select * from t_regexp_like where regexp_like(value,'ABC','i');
+ id | value
+----+----------
+ 4 | abc
+ 5 | abcde
+ 10 | abcbvbnb
+(3 rows)
+
+```
+
+25、兼容to_number函数,功能:是将一些处理过的按一定格式编排过的字符串变回数值型的格式,支持参数:text/text,text测试用例如下:
+将字符串'-34,338,492'转换为数值型格式:
+
+```
+SELECT to_number('34,338,492', '99,999,999') from dual;
+ to_number
+-----------
+ -34338492
+(1 row)
+```
+
+将字符串'5.01-'转换为数值型格式:
+
+```
+SELECT to_number('5.01-', '9.99S');
+
+ to_number
+-----------
+ -5.01
+(1 row)
+```
+
+26、兼容to_char函数,功能:将数字或日期转换为字符类型,支持参数:date/date,text/timestamp/timestamp,text测试用例如下:
+将当前系统日期转换为字符格式:
+
+```
+select to_char(sysdate()) from dual;
+ to_char
+------------
+ 2023-07-10
+(1 row)
+```
+
+将当前系统日期转换为月份/日期/年字符格式:
+
+```
+select to_char(sysdate(),'mm/dd/yyyy') from dual;
+ to_char
+------------
+ 07/10/2023
+(1 row)
+```
+
+将当前日期的timestamp格式转换为字符格式:
+
+```
+SELECT to_char(sysdate()::timestamp);
+ to_char
+----------------------------
+ 2023-07-10 09:46:44.000000
+```
+
+将当前日期的timestamp格式转换为月份/日期/年字符格式:
+
+```
+SELECT to_char(sysdate()::timestamp,'MM-YYYY-DD');
+ to_char
+------------
+ 07-2023-10
+(1 row)
+```
+
+27、兼容to_date函数,功能:将字符类型转换为日期类型,支持参数:text/text,text测试用例如下:
+将'2023/07/06'转换为日期类型:
+
+```
+select to_date('20230706') from dual;
+ to_date
+------------
+ 2023-07-06
+(1 row)
+```
+
+将'-44-02-01'转换为日期类型:
+
+```
+SELECT to_date('-44,0201','YYYY-MM-DD');
+ to_date
+------------
+ 0044-02-01
+(1 row)
+```
+
+28、兼容to_timestamp函数,功能:可以存储年、月、日、小时、分钟、秒,同时还可以存储秒的小数部分。支持参数:text/text,text测试用例如下:
+查询'2018-11-02 12:34:56.025'以日期形式输出:
+
+```
+SELECT to_timestamp('20181102.12.34.56.025');
+ to_timestamp
+----------------------------
+ 2018-11-02 12:34:56.025000
+(1 row)
+```
+
+查询’2011,12,18 11:38’以日期形式输出:
+
+```
+SELECT to_timestamp('2011,12,18 11:38 ', 'YYYY-MM-DD HH24:MI:SS');
+ to_timestamp
+----------------------------
+ 2011-12-18 11:38:00.000000
+(1 row)
+```
+
+29、兼容to_timestamp_tz函数,功能:根据时间查询,时间字符串有T,Z并有毫秒,时区。测试用例如下:
+查询'2016-10-9 14:10:10.123000'以日期形式输出:
+
+```
+ SELECT to_timestamp_tz('2016-10-9 14:10:10.123000') FROM DUAL;
+ to_timestamp_tz
+-----------------------------------
+ 2016-10-09 14:10:10.123000 +08:00
+(1 row)
+```
+
+查询'10-9-2016 14:10:10.123000 +8:30'以日期形式输出:
+
+```
+ SELECT to_timestamp_tz('10-9-2016 14:10:10.123000 +8:30', 'DD-MM-YYYY HH24:MI:SS.FF TZH:TZM') FROM DUAL;
+ to_timestamp_tz
+-----------------------------------
+ 2016-09-10 13:40:10.123000 +08:00
+(1 row)
+```
+
+30、兼容to_yminterval函数,功能:将一个字符串类型转化为年和月的时间差类型,支持参数:text, 测试用例如下:
+查询'20110101'以后两个年零八个月后的日期:
+
+```
+select to_date('20110101','yyyymmdd')+to_yminterval('02-08') from dual;
+ ?column?
+------------
+ 2013-09-01
+(1 row)
+```
+
+31、兼容to_dsinterval函数,功能:将一个日期加上一定的小时或者天数变成另外一个日期,支持参数:text,测试用例如下:
+查询当前系统时间加上9个半小时后的日期(当前为2023-07-06,18:00):
+
+```
+select sysdate()+to_dsinterval('0 09:30:00')as newdate from dual;
+ newdate
+------------
+ 2023-07-07
+(1 row)
+```
+
+32、兼容numtodsinterval函数,功能:将数字转换成时间间隔类型的数据。支持参数:double precision, text测试用例如下:
+转换100.00个小时为时间间隔类型数据:
+
+```
+SELECT NUMTODSINTERVAL(100.00, 'hour');
+ numtodsinterval
+-------------------------------
+ +000000004 04:00:00.000000000
+(1 row)
+```
+
+转换100分钟为时间间隔类型数据:
+
+```
+SELECT NUMTODSINTERVAL(100, 'minute');
+ numtodsinterval
+-------------------------------
+ +000000000 01:40:00.000000000
+(1 row)
+```
+
+33、兼容numtoyminterval函数,功能:将数字转换成日期间隔类型的数据。
+支持参数:double precision,text,测试用例如下:
+转换1.00,year为日期间隔:
+
+```
+SELECT NUMTOYMINTERVAL(1.00,'year');
+ numtoyminterval
+-----------------
+ +000000001-00
+(1 row)
+```
+
+转换1,mouth为日期间隔:
+
+```
+SELECT NUMTOYMINTERVAL(1,'month');
+ numtoyminterval
+-----------------
+ +000000000-01
+(1 row)
+```
+
+34、兼容localtimestamp函数,功能:返回会话中的日期和时间,支持参数:integer, 函数中增加参数为精度,测试用例如下:
+返回当前会话中的日期和时间:
+
+```
+select localtimestamp from dual;
+ localtimestamp
+----------------------------
+ 2023-07-07 09:18:15.896472
+(1 row)
+```
+
+返回当前会话中的日期和时间(精度为1):
+
+```
+select localtimestamp(1) from dual;
+ localtimestamp
+----------------------------
+ 2023-07-07 09:18:16.100000
+(1 row)
+```
+
+35、兼容from_tz函数,功能:将时间从一个时区转换为另一个时区,支持参数;timestamp, text ,测试用例如下:
+将'2000-03-28 08:00:00', '3:00'转换为当前时区:
+
+```
+SELECT FROM_TZ(TIMESTAMP '2000-03-28 08:00:00', '3:00') FROM DUAL;
+ from_tz
+-----------------------------------
+ 2000-03-28 13:00:00.000000 +08:00
+(1 row)
+```
+
+36、兼容sys_extract_utc函数,功能:将一个timestamptz转换为UTC时区时间。支持参数:timestamp with time zone 测试用例如下:
+查询转换timestamp '2000-03-28 11:30:00.00 -8:00'为UTC时区后的时间:
+
+```
+select sys_extract_utc(timestamp '2000-03-28 11:30:00.00 -8:00') from dual;
+ sys_extract_utc
+----------------------------
+ 2000-03-28 19:30:00.000000
+(1 row)
+```
+
+37、兼容sessiontimezone函数,功能:查看时区详细信息,测试用例如下:
+查看当前时区的详细信息:
+
+```
+select sessiontimezone() from dual;
+ sessiontimezone
+-----------------
+ Asia/Shanghai
+(1 row)
+```
+
+修改timezone后,查看时区相信信息:
+
+```
+set timezone = 'Asia/Hong_Kong';
+SET
+select sessiontimezone() from dual;
+ sessiontimezone
+-----------------
+ Asia/Hong_Kong
+(1 row)
+```
+
+38、兼容hextoraw函数,功能:将字符串表示的二进制数值转换为一个raw数值。支持参数:text,测试用例如下:
+将字符串'abcdef'转换为raw数值:
+
+```
+select hextoraw('abcdef')from dual;
+ hextoraw
+----------
+ \xabcdef
+(1 row)
+```
+
+39、兼容uid函数,功能:获取数据库的实例名。测试用例如下:
+获取当前数据库的实例名:
+
+```
+select uid() from dual;
+ uid
+-----
+ 10
+(1 row)
+```
+
+40、兼容USERENV函数,功能:返回当前用户环境的信息,测试用例如下:
+查看当前用户是否是dba,如果是返回ture:
+
+```
+select userenv('isdba')from dual;
+ get_isdba
+-----------
+ TRUE
+(1 row)
+```
+
+查看会话标志:
+
+```
+select userenv('sessionid')from dual;
+ get_sessionid
+---------------
+ 1
+(1 row)
+```
+
+41、兼容ASCIISTR函数,功能:传入字符串,返回对应的ASCII字符,测试用例如下:
+只有ASCII字符:
+```
+ select asciistr('Hello, World!') from dual;
+ asciistr
+---------------
+ Hello, World!
+(1 row)
+```
+
+非ASCII字符:
+```
+ select asciistr('你好') from dual;
+ asciistr
+------------
+ \4F60\597D
+```
+
+同时包含ASCII字符和非ASCII字符:
+```
+ select asciistr('ABÄCDE') from dual;
+ asciistr
+------------
+ AB\00C4CDE
+(1 row)
+```
+
+42、兼容TO_MULTI_BYTE函数, 功能:将字符串中的半角字符转换为全角字符:
+输入半角字符,转换为全角字符:
+```
+select to_multi_byte('1.2'::text) ;
+ to_multi_byte
+---------------
+ 1.2
+```
+
+43、兼容TO_SINGLE_BYTE函数, 功能:将字符串中的半角字符转换为全角字符
+输入全角字符,转换为半角字符:
+```
+select to_single_byte('1.2');
+ to_single_byte
+----------------
+ 1.2
+```
+
+44、兼容COMPOSE函数,功能:将基本字符和组合标记组合一个复合Unicode字符:
+输入基本字符a和组合标记768, 返回法语à
+```
+select compose('a'||chr(768)) from dual;
+ compose
+---------
+ à
+(1 row)
+```
+
+
+45、兼容DECOMPOSE函数,功能:将复合Unicode字符(如带有重音或特殊符号的字符)分解为其基本字符和组合标记
+输入法语é,返回基本字符e和组合标记301:
+```
+select asciistr(decompose('é')) from dual;
+ asciistr
+----------
+ e\0301
+```
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v3.0/22.adoc b/CN/modules/ROOT/pages/v1.22/19.adoc
similarity index 95%
rename from CN/modules/ROOT/pages/v3.0/22.adoc
rename to CN/modules/ROOT/pages/v1.22/19.adoc
index 64846f7..e95971b 100644
--- a/CN/modules/ROOT/pages/v3.0/22.adoc
+++ b/CN/modules/ROOT/pages/v1.22/19.adoc
@@ -1,28 +1,28 @@
-:sectnums:
-:sectnumlevels: 5
-
-:imagesdir: ./_images
-
-= 新增Oracle兼容模式的端口与Ip
-
-== 目的
-
-- 为了将Oracle端口、Ip与PG的端口Ip进行区分。现需要增加对ORAPORT和ORAHOST的处理;
-
-== 功能
-
-- 新增ivoryhost:需要在连接时新增参数ivoryhost即可指定,其功能类似 host;
-
-- 新增ivoryport:相较于host,port的功能相对复杂一些。其中涉及到可以在configure阶段配置,连接阶段指定端口;
-
-== 测试用例:
-```
- ./configure --with-oraport=5555
- ./initdb ....
- ./pg_ctl -D ../data start
-
- ./pg_ctl -o “-p 5433 -o 1522” -D ../data
-```
-
-
-
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 新增Oracle兼容模式的端口与Ip
+
+== 目的
+
+- 为了将Oracle端口、Ip与PG的端口Ip进行区分。现需要增加对ORAPORT和ORAHOST的处理;
+
+== 功能
+
+- 新增ivoryhost:需要在连接时新增参数ivoryhost即可指定,其功能类似 host;
+
+- 新增ivoryport:相较于host,port的功能相对复杂一些。其中涉及到可以在configure阶段配置,连接阶段指定端口;
+
+== 测试用例:
+```
+ ./configure --with-oraport=5555
+ ./initdb ....
+ ./pg_ctl -D ../data start
+
+ ./pg_ctl -o “-p 5433 -o 1522” -D ../data
+```
+
+
+
diff --git a/CN/modules/ROOT/pages/v3.0/2.adoc b/CN/modules/ROOT/pages/v1.22/2.adoc
similarity index 77%
rename from CN/modules/ROOT/pages/v3.0/2.adoc
rename to CN/modules/ROOT/pages/v1.22/2.adoc
index 355f2c7..f8126de 100644
--- a/CN/modules/ROOT/pages/v3.0/2.adoc
+++ b/CN/modules/ROOT/pages/v1.22/2.adoc
@@ -13,8 +13,6 @@ IvorySQL社区始终承诺与PostgreSQL数据库保持100%兼容,并且可以
IvorySQL增加了一个名为 `ivorysql.compatible_mode` 的GUC参数用以控制IvorySQL的兼容模式,该参数有 `oracle` 和 `pg` 两种值。在初始化数据目录的时候,通过指定 `-m` 参数来指定数据目录的兼容模式,`-m pg` 则数据目录为PostgreSQL模式,该模式下 `ivorysql.compatible_mode` 参数将会失效,`-m oracle` 或者不指定 `-m` 参数则数据目录为兼容Oracle模式,该模式下 `ivorysql.compatible_mode` 参数初始值为 `oracle` 并且不支持部分PostgreSQL的语法,通过 `set ivorysql.compatible_mode to pg` 就可以使得数据库100%支持PostgreSQL的语法及功能。
-IvorySQL的亮点之一是PL/iSQL过程语言,它支持Oracle的PL/SQL语法。同时,IvorySQL通过增加与内核绑定的插件 *ivorysql_ora* 来实现兼容Oracle的功能,目前实现的功能包括内置函数、数据类型、系统视图、merge以及GUC参数的增加,未来将会继续以绑定内核的插件的形式来实现新的兼容功能。
-
IvorySQL项目是在Apache 2.0许可证下发布的,社区鼓励且欢迎所有类型的贡献和参与。
=== 产品目标和范围
@@ -69,12 +67,12 @@ IvorySQL是一个功能强大的开源对象关系数据库管理系统(ORDBMS)
== 与Oracle的兼容性
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/14[ivorysql框架设计]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/15[GUC框架]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/16[大小写转换]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/17[双模式设计]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/18[兼容Oracle like]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/19[兼容Oracle匿名块]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/20[兼容Oracle函数与存储过程]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/21[内置数据类型与内置函数]
-* https://docs.ivorysql.org/cn/ivorysql-doc/v3.0/v3.0/22[新增Oracle兼容模式的端口与ip]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/11[1.ivorysql框架设计]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/12[2.GUC框架]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/13[3.大小写转换]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/14[4.双模式设计]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/15[5.兼容Oracle like]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/16[6.兼容Oracle匿名块]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/17[7.兼容Oracle函数与存储过程]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/18[8.内置数据类型与内置函数]
+* https://docs.ivorysql.org/cn/ivorysql-doc/v1.22/v1.22/19[9.新增Oracle兼容模式的端口与IP]
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v3.0/10.adoc b/CN/modules/ROOT/pages/v1.22/20.adoc
similarity index 100%
rename from CN/modules/ROOT/pages/v3.0/10.adoc
rename to CN/modules/ROOT/pages/v1.22/20.adoc
diff --git a/CN/modules/ROOT/pages/v3.0/11.adoc b/CN/modules/ROOT/pages/v1.22/21.adoc
similarity index 100%
rename from CN/modules/ROOT/pages/v3.0/11.adoc
rename to CN/modules/ROOT/pages/v1.22/21.adoc
diff --git a/CN/modules/ROOT/pages/v3.0/12.adoc b/CN/modules/ROOT/pages/v1.22/22.adoc
similarity index 100%
rename from CN/modules/ROOT/pages/v3.0/12.adoc
rename to CN/modules/ROOT/pages/v1.22/22.adoc
diff --git a/CN/modules/ROOT/pages/v3.0/3.adoc b/CN/modules/ROOT/pages/v1.22/3.adoc
similarity index 75%
rename from CN/modules/ROOT/pages/v3.0/3.adoc
rename to CN/modules/ROOT/pages/v1.22/3.adoc
index bc66d1a..c807491 100644
--- a/CN/modules/ROOT/pages/v3.0/3.adoc
+++ b/CN/modules/ROOT/pages/v1.22/3.adoc
@@ -3,14 +3,12 @@
:sectnumlevels: 5
:imagesdir: ./_images
-== 用户使用手册
+== **快速开始**
=== 入门指南
==== 新用户指南
-如果您刚开始接触IvorySQL,您可以访问我们的 https://docs.ivorysql.org/cn/ivorysql-doc/beta/beta/1[地址]来初步了解IvorySQL的各项特性。您同样可以前往我们的 https://github.com/IvorySQL/IvorySQL[Github]将我们的项目源代码下载到您的终端中。
-
如果您想快速安装IvorySQL并且进行一些数据库体验,您可以参考如下:
笔者的OS版本如下
@@ -28,18 +26,19 @@ Linux version 3.10.0-1160.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc v
[highgo@ivorysql /]$ cd /home/highgo
----
-**使用git命令下载项目源代码**
+**使用wget命令下载项目源代码**
[source,]
----
-[highgo@ivorysql ~]$ git clone https://github.com/IvorySQL/IvorySQL.git
+[highgo@ivorysql ~]$ wget https://github.com/IvorySQL/IvorySQL/archive/refs/tags/IvorySQL_1.22.tar.gz
+[highgo@ivorysql ~]$ tar -zxvf IvorySQL_1.22.tar.gz
----
**进入下载好的项目目录中**
[source,]
----
-[highgo@ivorysql ~]$ ls
+[highgo@ivorysql ~]$ mv IvorySQL-IvorySQL_1.22 IvorySQL; ls
IvorySQL
[highgo@ivorysql ~]$ cd IvorySQL/
----
@@ -115,7 +114,7 @@ image::p19.png[]
[source,]
----
[highgo@ivorysql ~]$ psql -d postgres
-psql (16devel)
+psql (14.17)
Type "help" for help.
postgres=#
@@ -138,7 +137,7 @@ undefined
[root@localhost ~]# su - ivorysql
Last login: Wed Feb 24 10:47:32 CST 2023 on pts/0
-bash-4.2$ psql
-psql (14.2)
+psql (14.17)
Type "help" for help.
ivorysql=#
@@ -169,28 +168,21 @@ image::p2.png[]
安装包:rpm
-下载YUM源:在Centos7上使用wget下载
+下载RPM包:在Centos7上使用wget下载
-wget https://yum.highgo.ca/dists/ivorysql-rpms/repo/ivorysql-release-1.0-2.noarch.rpm
+wget https://github.com/IvorySQL/IvorySQL/releases/download/Ivory_REL_1_17/IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
-安装源
-[source,]
-----
-yum install ivorysql-release-1.0-2.noarch.rpm
-----
-
-安装库
+安装IvorySQL
[source,]
----
-yum install -y ivorysql2-server
+yum install IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
----
初始化单机数据库
[source,]
----
-cd /usr/local/ivorysql/ivorysql-2/bin
-./initdb -D ../data
+/opt/IvorySQL-1.22/bin/initdb -D data/
----
===== 集群安装(一主一备)
@@ -199,28 +191,23 @@ cd /usr/local/ivorysql/ivorysql-2/bin
安装包:rpm
-下载YUM源:在Centos7上使用wget下载
+下载RPM包:在Centos7上使用wget下载
-wget https://yum.highgo.ca/dists/ivorysql-rpms/repo/ivorysql-release-1.0-2.noarch.rpm
+wget https://github.com/IvorySQL/IvorySQL/releases/download/Ivory_REL_1_17/IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
-安装源
+安装IvorySQL
[source,]
----
-yum install ivorysql-release-1.0-2.noarch.rpm
+yum install IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
----
-安装库
-[source,]
-----
-yum install -y ivorysql2-server
-----
**主节点**
初始化主节点
[source,]
----
-cd /usr/local/ivorysql/ivorysql-2/bin
+/opt/IvorySQL-1.22/bin/initdb -D data/
./initdb ../data-primary -U postgres
----
@@ -247,7 +234,7 @@ host replication all 0.0.0.0/0 trust
1、 基础备份
[source,shell]
----
-cd /usr/local/ivorysql/ivorysql-2/bin
+cd /opt/IvorySQL-1.22/bin
./pg_basebackup -h 127.0.0.1 -p 5333 -U repl -W -Fp -Xs -Pv -R -D ../data-standby01
----
@@ -270,29 +257,20 @@ vi ../data-standby01/postgresql.conf
安装包:rpm
-下载YUM源:在Centos7上使用wget下载
+下载RPM包:在Centos7上使用wget下载
-wget https://yum.highgo.ca/dists/ivorysql-rpms/repo/ivorysql-release-1.0-2.noarch.rpm
+wget https://github.com/IvorySQL/IvorySQL/releases/download/Ivory_REL_1_17/IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
-
-安装源
+安装IvorySQL
[source,]
----
-yum install ivorysql-release-1.0-2.noarch.rpm
-----
-
-
-安装库
-[source,]
-----
-yum install -y ivorysql2-server
+yum install IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
----
初始化主节点
[source,]
----
-cd /usr/local/ivorysql/ivorysql-2/bin
-./initdb ../data-primary -U postgres
+/opt/IvorySQL-1.22/bin/initdb -D data/
----
启动服务,创建用户
@@ -332,22 +310,18 @@ host replication all 0.0.0.0/0 trust
安装包:rpm
-下载YUM源:在Centos7上使用wget下载
-
-wget https://yum.highgo.ca/dists/ivorysql-rpms/repo/ivorysql-release-1.0-2.noarch.rpm
-
-安装源
+下载RPM包:在Centos7上使用wget下载
- yum install ivorysql-release-1.0-2.noarch.rpm
+wget https://github.com/IvorySQL/IvorySQL/releases/download/Ivory_REL_1_17/IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
-安装库
+安装IvorySQL
- yum install -y ivorysql2-server
+ yum install IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
1、 基础备份
[source,shell]
----
-cd /usr/local/ivorysql/ivorysql-2/bin
+cd /opt/IvorySQL-1.22/bin
./pg_basebackup -h 192.168.xx.xx -p 5333 -U repl -W -Fp -Xs -Pv -R -D ../data-standby01
----
diff --git a/CN/modules/ROOT/pages/v1.22/33.adoc b/CN/modules/ROOT/pages/v1.22/33.adoc
new file mode 100644
index 0000000..344ebc5
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/33.adoc
@@ -0,0 +1,27 @@
+:sectnums:
+:sectnumlevels: 5
+
+
+[discrete]
+== IvorySQL生态插件适配列表
+
+IvorySQL 作为一款兼容 Oracle 且基于 PostgreSQL 的高级开源数据库,具备强大的扩展能力,支持丰富的生态系统插件。这些插件可以帮助用户在不同场景下增强数据库功能,包括地理信息处理、向量检索、全文搜索、数据定义提取和路径规划等。以下是当前 IvorySQL 官方兼容和支持的主要插件列表:
+
++
+
+[cols="2,1,3,3"]
+|====
+|*插件名称*|*版本*|*功能描述*|*适用场景*
+| xref:v1.22/9.adoc[PostGIS] | 3.4.0 | 为 IvorySQL 提供地理空间数据支持,包括空间索引、空间函数和地理对象存储 | 地理信息系统(GIS)、地图服务、位置数据分析
+| xref:v1.22/10.adoc[pgvector] | 0.8.0 | 支持向量相似性搜索,可用于存储和检索高维向量数据| AI 应用、图像检索、推荐系统、语义搜索
+| xref:v1.22/34.adoc[PGroonga] | 4.0.1 | 提供多语言全文搜索功能,支持超高速文本检索和模糊匹配 | 日志分析、多语言内容搜索、实时搜索引擎
+| xref:v1.22/35.adoc[pgddl (DDL Extractor)] | 0.20 | 提取数据库中的 DDL(数据定义语言)语句,便于版本管理和迁移 | 数据库版本控制、CI/CD 集成、结构比对与同步
+| xref:v1.22/36.adoc[pgRouting] | 3.5.1 | 基于地理数据的路径规划扩展,支持最短路径、旅行商问题等算法 | 物流规划、交通网络分析、路径优化服务
+| xref:v1.22/37.adoc[pg_cron] | 1.6.0 | 提供数据库内部的定时任务调度功能,支持定期执行SQL语句 | 数据清理、定期统计、自动化维护任务
+| xref:v1.22/38.adoc[pgsql-http] | 1.7.0 | 允许在SQL中发起HTTP请求,与外部Web服务进行交互 | 数据采集、API集成、微服务调用
+| xref:v1.22/40.adoc[pgvectorscale] | 0.8.0 | 提供向量数据的分片和分布式扩展支持,提升大规模向量处理性能 | 分布式向量数据库、高并发向量查询
+|====
+
+这些插件均经过 IvorySQL 团队的测试和适配,确保在 IvorySQL 环境下稳定运行。用户可以根据业务需求选择合适的插件,进一步提升数据库系统的能力和灵活性。
+
+我们也将持续扩展和丰富 IvorySQL 的插件生态,欢迎社区开发者提交新的插件适配建议或代码贡献。如需了解更多每个插件的详细使用方法和最新兼容版本,请参阅各插件对应的文档章节。
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v1.22/34.adoc b/CN/modules/ROOT/pages/v1.22/34.adoc
new file mode 100644
index 0000000..d432776
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/34.adoc
@@ -0,0 +1,111 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+= PGroonga
+
+== 概述
+PostgreSQL 内置了全文搜索功能,但在处理大规模数据、复杂查询以及非英语语言(特别是中日韩等 CJK 语言) 时,其功能和性能可能无法满足高性能应用的需求。
+
+PGroonga 应运而生,它是一个 PostgreSQL 的扩展插件,将 Groonga 这款高性能的全功能全文搜索引擎与 PostgreSQL 数据库深度融合。Groonga 本身是一个优秀的开源搜索引擎,以其极致的速度和丰富的功能著称,尤其擅长处理多语言文本。PGroonga 的使命就是将 Groonga 的强大能力无缝地带入 PostgreSQL 的世界,为用户提供远超原生全文搜索的体验。
+
+== 安装
+根据开发环境,用户可从 https://pgroonga.github.io/install[PGroonga安装] 页面选择适合自己的方式进行PGroonga安装。
+IvorySQL的安装包里已经集成了PGroonga插件,如果使用安装包安装的IvorySQL,通常不需要再手动安装PGroonga即可使用。
+
+=== 源码安装
+除PGroonga社区提供的安装方式以外,IvorySQL社区也提供了源码安装方式,源码安装环境为 Ubuntu 24.04(x86_64)。
+
+[TIP]
+环境中已经安装了IvorySQL1.22及以上版本,安装路径为/usr/local/ivorysql/ivorysql-1
+
+==== 安装 groonga
+
+** 安装依赖 kytea
+[literal]
+----
+git clone https://github.com/neubig/kytea.git
+autoreconf -i
+./configure
+make
+sudo make install
+----
+
+** 安装依赖 libzmq
+[literal]
+----
+从https://github.com/zeromq/libzmq/releases/tag/v4.3.5 下载zeromq-4.3.5.tar.gz
+tar xvf zeromq-4.3.5.tar.gz
+cd zeromq-4.3.5/
+./configure
+make
+sudo make install
+----
+
+** 下载 groonga包,安装指定依赖
+[literal]
+----
+wget https://packages.groonga.org/source/groonga/groonga-latest.tar.gz
+tar xvf groonga-15.1.5.tar.gz
+cd groonga-15.1.5
+#运行这个脚本安装依赖,支持apt和dnf包管理工具
+./ setup.sh
+----
+
+** 编译安装
+[literal]
+----
+# -S 指定groonga源码目录, -B 指定build目录,这个目录是个源码目录之外的一个只用于build的目录
+cmake -S /home/ivorysql/groonga-15.1.5 -B /home/ivorysql/groonga_build --preset=release-maximum
+cmake --build /home/ivorysql/groonga_build
+sudo cmake --install /home/ivorysql/groonga_build
+# 更新动态链接库缓存
+sudo ldconfig
+----
+
+** 验证 groonga安装成功
+[literal]
+----
+$ groonga --version
+Groonga 15.1.5 [Linux,x86_64,utf8,match-escalation-threshold=0,nfkc,mecab,message-pack,mruby,onigmo,zlib,lz4,zstandard,epoll,apache-arrow,xxhash,blosc,bfloat16,h3,simdjson,llama.cpp]
+----
+
+==== 安装 pgroonga
+[literal]
+----
+wget https://packages.groonga.org/source/pgroonga/pgroonga-4.0.1.tar.gz
+tar xvf pgroonga-4.0.1.tar.gz
+cd pgroonga-4.0.1
+----
+
+编译PGroonga,有个选项:HAVE_MSGPACK=1,它是用于支持WAL,使用这个选项需要安装msgpack-c 1.4.1或者更高版本。在基于Debian的平台使用libmsgpack-dev包,在CentOS 7上用msgpack-devel
+[literal]
+----
+#安装依赖
+sudo apt install libmsgpack-dev
+----
+
+运行make前确保pg_config命令的路径在PATH环境变量里
+[literal]
+----
+make HAVE_MSGPACK=1
+make install
+----
+
+== 创建Extension并确认PGroonga版本
+
+psql 连接到数据库,执行如下命令:
+[literal]
+----
+ivorysql=# CREATE extension pgroonga;
+CREATE EXTENSION
+
+ivorysql=# SELECT * FROM pg_available_extensions WHERE name = 'pgroonga';
+ name | default_version | installed_version | comment
+---------+-----------------+-------------------+-------------------------------------------------------------------------------
+ pgroonga| 4.0.1 | 4.0.1 | Super fast and all languages supported full text search index based on Groonga
+(1 row)
+----
+
+== 使用
+关于PGroonga的使用,请参阅 https://pgroonga.github.io/tutorial[PGroonga官方文档]
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v1.22/35.adoc b/CN/modules/ROOT/pages/v1.22/35.adoc
new file mode 100644
index 0000000..5401b9e
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/35.adoc
@@ -0,0 +1,47 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+= pgddl (DDL Extractor)
+
+== 概述
+pgddl 是一个专为 PostgreSQL 数据库设计的 SQL 函数扩展,它能够直接从数据库系统目录中生成清晰、格式化的 SQL DDL (数据定义语言) 脚本,例如 CREATE TABLE 或 ALTER FUNCTION。它解决了 PostgreSQL 原生缺乏类似 SHOW CREATE TABLE 命令的问题,让用户无需借助外部工具(如 pg_dump)即可在纯 SQL 环境中轻松获取对象的创建语句。
+
+该扩展通过一组简单的 SQL 函数提供了一套完整的解决方案,其优势包括:仅需使用 SQL 查询即可操作、支持通过 WHERE 子句灵活筛选对象、并能智能处理对象之间的依赖关系,生成包含 Drop 和 Create 步骤的完整脚本。这使得它特别适用于数据库变更管理、升级脚本编写和结构审计等场景。
+
+需要注意的是,ddlx 仍在发展中,可能尚未覆盖所有 PostgreSQL 对象类型和高级选项。生成的脚本建议始终在非生产环境中先行检查和测试,以确保其正确性与安全性。
+
+== 安装
+IvorySQL的安装包里已经集成了pgddl插件,如果使用安装包安装的IvorySQL,通常不需要再手动安装pgddl即可使用。其它安装方式可以参考下面的源码安装步骤。
+
+[TIP]
+源码安装环境为 Ubuntu 24.04(x86_64),环境中已经安装了IvorySQL1.22及以上版本,安装路径为/usr/local/ivorysql/ivorysql-1
+
+=== 源码安装
+从https://github.com/lacanoid/pgddl/releases/tag/0.20 下载pgddl-0.20.tar.gz,解压缩。
+
+[literal]
+----
+cd pgddl-0.20
+# 设置PG_CONFIG环境变量值为pg_config路径,eg:/usr/local/ivorysql/ivorysql-1/bin/pg_config
+make PG_CONFIG=/path/to/pg_config
+make PG_CONFIG=/path/to/pg_config install
+----
+
+== 创建Extension并确认ddlx版本
+
+psql 连接到数据库,执行如下命令:
+[literal]
+----
+ivorysql=# CREATE extension ddlx;
+CREATE EXTENSION
+
+ivorysql=# SELECT * FROM pg_available_extensions WHERE name = 'ddlx';
+ name | default_version | installed_version | comment
+------+-----------------+-------------------+-------------------------
+ ddlx | 0.20 | 0.20 | DDL eXtractor functions
+(1 row)
+----
+
+== 使用
+关于pgddl的使用,请参阅 https://github.com/lacanoid/pgddl[ddlx官方文档]
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v1.22/36.adoc b/CN/modules/ROOT/pages/v1.22/36.adoc
new file mode 100644
index 0000000..a5b11f9
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/36.adoc
@@ -0,0 +1,61 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+= pgRouting
+
+== 概述
+pgRouting 是一个基于 PostgreSQL/PostGIS 数据库构建的开源地理空间路由扩展库。它为数据库赋予了强大的网络分析功能,使其能够处理复杂的路径规划与图论计算问题,例如计算两点之间的最短路径、执行旅行推销员(TSP)分析或计算服务区范围等。它将路由算法直接嵌入到数据库中,从而避免了在应用层进行复杂的数据传输与计算。
+
+该扩展的核心优势在于能够利用 PostgreSQL 强大的数据管理能力和 PostGIS 丰富的空间函数,直接在数据库内部对空间网络数据执行高效计算。这不仅简化了应用程序的开发流程,还通过减少数据移动大幅提升了大规模网络分析的性能。
+
+pgRouting 广泛应用于物流配送、交通导航、网络分析、城市规划及供应链管理等多个领域。其开源特性吸引了全球开发者持续的贡献与完善,使其成为空间数据库领域进行路径分析和网络求解的首选工具之一。
+
+== 安装
+IvorySQL的安装包里已经集成了pgRouting插件,如果使用安装包安装的IvorySQL,通常不需要再手动安装pgRouting即可使用。其它安装方式可以参考下面的源码安装步骤。
+
+[TIP]
+源码安装环境为 Ubuntu 24.04(x86_64),环境中已经安装了IvorySQL1.22及以上版本,安装路径为/usr/local/ivorysql/ivorysql-1
+
+=== 源码安装
+
+** 安装依赖
+
+对perl有依赖,perl一般在装IvorySQL时已经装上了,这里不用再装。
+CMake版本要求 >= 3.12, Boost版本 >= 1.56
+[literal]
+----
+#安装依赖
+sudo apt install cmake libboost-all-dev
+----
+
+** 编译安装
+[literal]
+----
+wget https://github.com/pgRouting/pgrouting/releases/download/v3.5.1/pgrouting-3.5.1.tar.gz
+tar xvf pgrouting-3.5.1.tar.gz
+cd pgrouting-3.5.1
+mkdir build
+cd build
+cmake .. -DPOSTGRESQL_PG_CONFIG=/path/to/pg_config # eg: /usr/local/ivorysql/ivorysql-1/bin/pg_config
+make
+sudo make install
+----
+
+== 创建Extension并确认ddlx版本
+
+psql 连接到数据库,执行如下命令:
+[literal]
+----
+ivorysql=# CREATE extension pgrouting;
+CREATE EXTENSION
+
+ivorysql=# SELECT * FROM pg_available_extensions WHERE name = 'pgrouting';
+ name | default_version | installed_version | comment
+-----------+-----------------+-------------------+---------------------
+ pgrouting | 3.5.1 | | pgRouting Extension
+(1 row)
+----
+
+== 使用
+关于pgRouting的使用,请参阅 https://docs.pgrouting.org/[pgRouting官方文档]
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v1.22/37.adoc b/CN/modules/ROOT/pages/v1.22/37.adoc
new file mode 100644
index 0000000..438d6e4
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/37.adoc
@@ -0,0 +1,114 @@
+
+:sectnums:
+:sectnumlevels: 5
+:imagesdir: ./_images
+
+= pg_cron
+
+== 概述
+在 PostgreSQL 中运行周期性任务,例如执行 VACUUM或删除旧数据,是一种常见需求。实现这一点的简单方法是配置 cron或其他外部守护进程,使其定期连接到数据库并运行命令。然而,随着数据库越来越多地作为托管服务或独立容器运行,配置和运行一个单独的守护进程通常变得不切实际。此外,很难让您的 cron任务感知故障转移,或者跨集群节点调度任务。
+
+pg_cron 是 PostgreSQL 的开源定时任务扩展,允许直接在数据库内部设置 cron 风格的任务调度,用于自动化数据维护任务(清理,聚合), 数据库健康检查,执行存储过程和自定义函数等操作。它将cron任务存储在表中,周期性任务会随着 PostgreSQL 服务器自动进行故障转移。详情可以参见 https://github.com/citusdata/pg_cron[pg_cron文档]。
+
+== 安装配置
+
+[TIP]
+源码安装环境为 Ubuntu 24.04(x86_64),环境中已经安装了IvorySQL1.22及以上版本,安装路径为/usr/local/ivorysql/ivorysql-1
+
+=== 源码安装
+
+[literal]
+----
+# 拉取pg_cron源码
+git clone https://github.com/citusdata/pg_cron.git
+cd pg_cron
+# 将pg_config的路径设置到PATH环境变量里,eg:
+export PATH=/usr/local/ivorysql/ivorysql-1/bin/:$PATH
+make
+make install
+----
+
+=== 配置文件 (ivorysql.conf)
+
+[literal]
+----
+# 共享预加载扩展
+shared_preload_libraries = 'pg_cron'
+
+# 指定任务元数据存储库(默认当前库)
+cron.database_name = 'ivorysql'
+
+# 允许的最大并发任务数
+cron.max_running_jobs = 5
+----
+
+=== 重启服务
+
+[literal]
+----
+pg_ctl restart -D ./data -l logfile
+----
+
+=== 创建Extension并确认pg_cron版本
+
+psql 连接到数据库,执行如下命令:
+[literal]
+----
+ivorysql=# CREATE extension pg_cron;
+CREATE EXTENSION
+
+ivorysql=# SELECT * FROM pg_available_extensions WHERE name = 'pg_cron';
+ name | default_version | installed_version | comment
+---------+-----------------+-------------------+---------------------------
+ pg_cron | 1.6 | |Job scheduler for PostgreSQL
+(1 row)
+----
+
+== 核心功能使用
+
+=== 创建定时任务
+
+```
+SELECT cron.schedule(
+ 'nightly-data-cleanup', -- 任务名称(唯一标识)
+ '0 3 * * *', -- cron表达式(每天UTC 3:00)
+ $$DELETE FROM logs
+ WHERE created_at < now() - interval '30 days'$$ -- 执行SQL
+);
+```
+
+cron表达式速查表:
+
+|====
+|示例|含义
+|'0 * * * *'|每小时整点执行
+|'*/15 * * * *'|每15分钟执行
+|'0 9 * * 1-5'|工作日早9点执行
+|'0 1 1 * *'|每月1日凌晨1点执行
+|====
+
+pg_cron还允许使用 '$'表示月份的最后一天。
+
+=== 任务管理
+
+```
+# 查看所有任务
+SELECT * FROM cron.job;
+```
+
+image::p31.png[]
+
+```
+# 查看任务执行历史
+SELECT * FROM cron.job_run_details ORDER BY start_time DESC LIMIT 10;
+```
+
+image::p32.png[]
+
+```
+# 删除任务
+SELECT cron.unschedule('nightly-data-cleanup');
+
+# 暂停任务(更新状态)
+UPDATE cron.job SET active = false WHERE jobname = 'delete-job-run-details';
+```
diff --git a/CN/modules/ROOT/pages/v1.22/38.adoc b/CN/modules/ROOT/pages/v1.22/38.adoc
new file mode 100644
index 0000000..c6f3316
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/38.adoc
@@ -0,0 +1,59 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+= pgsql-http
+
+== 概述
+pgsql-http 是一个为 PostgreSQL 数据库设计的开源扩展,它允许用户直接在数据库内部发起 HTTP 请求,扮演了一个内置 Web 客户端的角色。该扩展的核心目的是打通数据库与外部 Web 服务之间的壁垒,使得通过简单的 SQL 函数调用即可与外部 Web 服务、API 端点进行交互,无需依赖外部应用程序或中间件。
+
+借助此扩展,开发者可以在 SQL 查询、触发器或存储过程中直接获取网络数据(GET)、提交数据(POST/PUT)、更新(PATCH)或删除(DELETE)远程资源。它提供了丰富的功能,包括设置请求头、自动处理 URL 编码、发送 JSON 数据以及解析响应状态、头部和内容,极大简化了将外部数据集成到数据库操作中的流程。
+
+其典型应用场景包括:实时获取外部数据(如汇率、天气信息)并存入表;在数据变更时通过触发器自动通知微服务;对数据库中的数据进行清洗后直接提交至外部 API 等。它为构建以数据库为中心的集成应用提供了强大而灵活的解决方案。
+
+== 安装
+IvorySQL的安装包里已经集成了pgsql-http插件,如果使用安装包安装的IvorySQL,通常不需要再手动安装pgsql-http即可使用。其它安装方式可以参考下面的源码安装步骤。
+
+[TIP]
+源码安装环境为 Ubuntu 24.04(x86_64),环境中已经安装了IvorySQL1.22及以上版本,安装路径为/usr/local/ivorysql/ivorysql-1
+
+=== 源码安装
+
+** 安装依赖
+
+对libcurl有依赖,libcurl的开发文件(例如 libcurl4-openssl-dev)需要提前安装上
+[literal]
+----
+#安装依赖
+sudo apt install libcurl4-openssl-dev
+----
+
+** 编译安装
+
+从https://github.com/pramsey/pgsql-http/releases/tag/v1.7.0 下载 1.7.0的源码包 pgsql-http-1.7.0.tar.gz
+[literal]
+----
+tar xvf pgsql-http-1.7.0.tar.gz
+cd pgsql-http-1.7.0
+# 确保pg_config在PATH里可以访问,eg: /usr/local/ivorysql/ivorysql-1/bin/pg_config
+make
+sudo make install
+----
+
+== 创建Extension并确认http版本
+
+psql 连接到数据库,执行如下命令:
+[literal]
+----
+ivorysql=# CREATE extension http;
+CREATE EXTENSION
+
+ivorysql=# SELECT * FROM pg_available_extensions WHERE name = 'http';
+ name | default_version | installed_version | comment
+-----------+-----------------+-------------------+-------------------------------------------------------------------------
+ http | 1.7 | 1.7 | HTTP client for PostgreSQL, allows web page retrieval inside the database.
+(1 row)
+----
+
+== 使用
+关于pgsql-http的使用,请参阅 https://github.com/pramsey/pgsql-http[pgsql-http官方文档]
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v3.0/4.adoc b/CN/modules/ROOT/pages/v1.22/4.adoc
similarity index 99%
rename from CN/modules/ROOT/pages/v3.0/4.adoc
rename to CN/modules/ROOT/pages/v1.22/4.adoc
index be0721b..3b86474 100644
--- a/CN/modules/ROOT/pages/v3.0/4.adoc
+++ b/CN/modules/ROOT/pages/v1.22/4.adoc
@@ -3,7 +3,7 @@
:sectnumlevels: 5
-= 管理员指南
+= **日常监控**
== 监控数据活动
diff --git a/CN/modules/ROOT/pages/v1.22/40.adoc b/CN/modules/ROOT/pages/v1.22/40.adoc
new file mode 100644
index 0000000..94ba76d
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/40.adoc
@@ -0,0 +1,69 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+= pgvectorscale
+
+== 概述
+pgvectorscale 是 Timescale 公司推出的 PostgreSQL 扩展,旨在对流行的 pgvector 扩展进行高性能、高成本效益的补充。它专为 AI 应用中的大规模向量工作负载而设计,通过引入创新的索引算法和压缩技术,显著提升了向量相似性搜索的性能并降低了存储成本。
+
+该扩展的核心特性包括基于微软 DiskANN 研究的新索引类型 StreamingDiskANN、改进的统计二进制量化(SBQ)压缩方法,以及支持标签过滤的向量搜索功能。在基准测试中,它在处理大规模嵌入向量时展现出卓越的性能:与专用向量数据库服务相比,可实现高达 28 倍的低延迟和 16 倍的查询吞吐量,同时节省约 75% 的成本。
+
+pgvectorscale 完全兼容 pgvector 的数据类型和查询语法,确保了无缝的集成和迁移体验。它使用 Rust 语言和 PGRX 框架开发,非常适合需要在 PostgreSQL 内进行高效海量向量搜索的生产级应用。
+
+== 安装
+IvorySQL的安装包里已经集成了pgvectorscale插件,如果使用安装包安装的IvorySQL,通常不需要再手动安装pgvectorscale即可使用。其它安装方式可以参考下面的源码安装步骤。
+
+[TIP]
+源码安装环境为 Ubuntu 24.04(x86_64),环境中已经安装了IvorySQL1.22及以上版本,安装路径为/usr/local/ivorysql/ivorysql-1
+
+=== 源码安装
+
+** 安装Rust工具链
+
+[literal]
+----
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+----
+
+** 下载pgvectorscale源码
+
+从https://github.com/timescale/pgvectorscale/releases/tag/0.8.0 下载 0.8.0的源码包 pgvectorscale-0.8.0.tar.gz
+[literal]
+----
+tar xvf pgvectorscale-0.8.0.tar.gz
+cd pgvectorscale-0.8.0/pgvectorscale
+----
+
+** 安装cargo-pgrx
+
+[literal]
+----
+cargo install --locked cargo-pgrx --version $(cargo metadata --format-version 1 | jq -r '.packages[] | select(.name == "pgrx") | .version')
+cargo pgrx init --pg14 pg_config
+----
+
+** 编译并安装扩展
+
+[literal]
+----
+cargo pgrx install --release
+----
+
+== 创建Extension并确认pgvectorscale版本
+
+psql 连接到数据库,执行如下命令:
+[literal]
+----
+ivorysql=# CREATE EXTENSION IF NOT EXISTS vectorscale CASCADE;
+CREATE EXTENSION
+
+ivorysql=# SELECT * FROM pg_available_extensions WHERE name = 'vectorscale';
+ name | default_version | installed_version | comment
+----------- +-----------------+-------------------+--------------------------------------------
+ vectorscale | 0.8.0 | 0.8.0 | diskann access method for vector search.
+(1 row)
+----
+
+== 使用
+关于pgvectorscale的使用,请参阅 https://github.com/timescale/pgvectorscale[pgvectorscale官方文档]
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v1.22/41.adoc b/CN/modules/ROOT/pages/v1.22/41.adoc
new file mode 100644
index 0000000..b707768
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/41.adoc
@@ -0,0 +1,106 @@
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 全局唯一索引
+
+== 功能介绍
+
+全局唯一索引(Global Unique Index)是 IvorySQL 针对分区表提供的跨分区唯一性约束能力。
+
+标准 PostgreSQL 的唯一索引仅在单个分区内强制执行唯一性,无法保证跨分区的数据唯一。IvorySQL 引入 `GLOBAL` 关键字,在创建唯一索引时指定该关键字后,数据库在执行插入或更新操作时会扫描所有分区,确保整张分区表范围内不存在重复数据。
+
+该功能同时支持 PG 兼容模式与 Oracle 兼容模式。
+
+== 语法
+
+[source,sql]
+----
+CREATE UNIQUE INDEX [ index_name ] ON partitioned_table ( column [, ...] ) GLOBAL;
+----
+
+参数说明:
+
+- `UNIQUE`:必须与 `GLOBAL` 同时使用,指定唯一性约束;
+- `GLOBAL`:启用跨分区唯一性检查,仅对分区表有效;
+- `index_name`:可选,省略时数据库自动生成索引名。
+
+== 测试用例
+
+=== 创建分区表与全局唯一索引
+
+[source,sql]
+----
+-- 创建分区表
+CREATE TABLE gidxpart (a int, b int, c text) PARTITION BY RANGE (a);
+CREATE TABLE gidxpart1 PARTITION OF gidxpart FOR VALUES FROM (1) TO (10);
+CREATE TABLE gidxpart2 PARTITION OF gidxpart FOR VALUES FROM (10) TO (100);
+CREATE TABLE gidxpart3 PARTITION OF gidxpart FOR VALUES FROM (100) TO (200);
+
+-- 在分区表上创建全局唯一索引(指定索引名)
+CREATE UNIQUE INDEX gidx_u ON gidxpart USING btree(b) GLOBAL;
+
+-- 在分区表上创建全局唯一索引(不指定索引名)
+CREATE UNIQUE INDEX ON gidxpart (b) GLOBAL;
+----
+
+=== 插入数据:跨分区唯一性验证
+
+[source,sql]
+----
+-- 以下插入成功(各分区间 b 列无重复)
+INSERT INTO gidxpart VALUES (1, 1, 'first');
+INSERT INTO gidxpart VALUES (11, 11, 'eleventh');
+INSERT INTO gidxpart VALUES (2, 120, 'second');
+INSERT INTO gidxpart VALUES (12, 2, 'twelfth');
+INSERT INTO gidxpart VALUES (150, 13, 'no duplicate b');
+
+-- 以下插入失败:b=11 已存在于其他分区,违反跨分区唯一性约束
+INSERT INTO gidxpart VALUES (2, 11, 'duplicated (b)=(11) on other partition');
+-- ERROR: duplicate key value violates unique constraint
+
+INSERT INTO gidxpart VALUES (12, 1, 'duplicated (b)=(1) on other partition');
+-- ERROR: duplicate key value violates unique constraint
+
+INSERT INTO gidxpart VALUES (150, 11, 'duplicated (b)=(11) on other partition');
+-- ERROR: duplicate key value violates unique constraint
+----
+
+=== 更新数据:跨分区唯一性验证
+
+[source,sql]
+----
+-- 更新操作同样受全局唯一索引约束
+UPDATE gidxpart SET b = 2 WHERE a = 2;
+-- ERROR: duplicate key value violates unique constraint(b=2 已存在)
+
+UPDATE gidxpart SET b = 12 WHERE a = 12;
+-- 成功(b=12 在全局范围内唯一)
+----
+
+=== 分区的 ATTACH 与 DETACH
+
+[source,sql]
+----
+-- 创建一个独立的表,用于后续 ATTACH
+CREATE TABLE gidxpart_new (a int, b int, c text);
+INSERT INTO gidxpart_new VALUES (100001, 11, 'conflict with gidxpart1');
+
+-- ATTACH 时若存在跨分区重复值,操作将失败
+ALTER TABLE gidxpart ATTACH PARTITION gidxpart_new
+ FOR VALUES FROM (100000) TO (199999);
+-- ERROR: duplicate key value violates unique constraint
+
+-- DETACH 分区后,该分区的全局索引类型恢复为普通索引
+ALTER TABLE gidxpart DETACH PARTITION gidxpart2;
+----
+
+== 功能限制
+
+. `GLOBAL` 关键字必须与 `UNIQUE` 配合使用,不支持创建全局非唯一索引;
+. 全局唯一索引仅适用于**分区表**,普通表不支持该关键字;
+. 每次插入或更新操作均需扫描所有分区以验证唯一性,在分区数量较多或数据量较大时存在**性能开销**;
+. 通过 `ATTACH PARTITION` 挂载分区时,若新分区中存在与其他分区重复的数据,挂载操作将失败;
+. 分区被 `DETACH` 后,其对应的全局索引自动降级为普通局部索引;
+. 不支持在子分区(二级分区)上单独创建全局唯一索引,全局唯一性约束由顶层分区表统一管理。
diff --git a/CN/modules/ROOT/pages/v1.22/42.adoc b/CN/modules/ROOT/pages/v1.22/42.adoc
new file mode 100644
index 0000000..b89488f
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/42.adoc
@@ -0,0 +1,129 @@
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 新增无主键表默认支持逻辑复制
+
+== 功能介绍
+
+在 PostgreSQL/IvorySQL 的逻辑复制中,UPDATE 和 DELETE 操作需要依赖复制标识(Replica Identity)来定位订阅端的目标行。默认情况下,表使用 `REPLICA IDENTITY DEFAULT`,此时系统依赖主键(Primary Key)来定位行。如果表没有主键,复制策略将回退为 `REPLICA IDENTITY NOTHING`,此时 UPDATE 和 DELETE 操作将因无法定位行而报错。
+
+IvorySQL 新增了 GUC 参数 `logical_replication_fallback_to_full_identity`。当该参数开启后,如果表的复制标识为 `DEFAULT` 且没有主键,系统会自动将其回退为 `REPLICA IDENTITY FULL`——即在 WAL 中记录完整的旧行数据,使无主键表的 UPDATE 和 DELETE 操作能够通过逻辑复制正常执行。
+
+该功能仅在发布端(Publisher)生效,订阅端无需任何额外配置。
+
+== 参数说明
+
+[source,sql]
+----
+# postgresql.conf
+logical_replication_fallback_to_full_identity = on
+----
+
+参数说明:
+
+- 类型:`boolean`;
+- 默认值:`off`;
+- 作用域:`sighup`,可通过修改 `postgresql.conf` 后执行 `SELECT pg_reload_conf();` 使配置生效,无需重启数据库;
+- 适用节点:仅在发布端(Publisher)生效,订阅端无需配置。
+
+== 测试用例
+
+=== 未开启参数时,无主键表的 UPDATE 和 DELETE 复制失败
+
+[source,sql]
+----
+-- 发布端:创建无主键表
+CREATE TABLE test_no_pk (id int, name text);
+
+-- 订阅端:创建相同的表结构
+CREATE TABLE test_no_pk (id int, name text);
+
+-- 发布端:创建发布并添加表
+CREATE PUBLICATION tap_pub FOR TABLE test_no_pk;
+
+-- 订阅端:创建订阅
+CREATE SUBSCRIPTION tap_sub CONNECTION 'host=publisher dbname=postgres' PUBLICATION tap_pub;
+
+-- 发布端:INSERT 操作始终正常(不依赖复制标识)
+INSERT INTO test_no_pk VALUES (1, 'alice');
+
+-- 发布端:UPDATE 操作失败(无主键,无法定位目标行)
+UPDATE test_no_pk SET name = 'bob' WHERE id = 1;
+-- ERROR: cannot update table "test_no_pk" because it does not have a replica identity and publishes updates
+
+-- 发布端:DELETE 操作同样失败
+DELETE FROM test_no_pk WHERE id = 1;
+-- ERROR: cannot delete from table "test_no_pk" because it does not have a replica identity and publishes deletes
+----
+
+=== 开启参数后,无主键表的 UPDATE 和 DELETE 复制正常
+
+[source,sql]
+----
+-- 发布端:开启参数并重新加载配置
+ALTER SYSTEM SET logical_replication_fallback_to_full_identity = on;
+SELECT pg_reload_conf();
+
+-- 发布端:INSERT 正常
+INSERT INTO test_no_pk VALUES (1, 'alice');
+
+-- 发布端:UPDATE 正常(自动按 FULL 方式记录完整旧行数据)
+UPDATE test_no_pk SET name = 'bob' WHERE id = 1;
+
+-- 发布端:DELETE 正常
+DELETE FROM test_no_pk WHERE id = 1;
+----
+
+=== 参数不影响有主键的表
+
+[source,sql]
+----
+-- 有主键的表始终使用主键定位行,不受该参数影响
+CREATE TABLE test_with_pk (id int PRIMARY KEY, name text);
+
+-- 无论参数是否开启,UPDATE 和 DELETE 均正常工作
+INSERT INTO test_with_pk VALUES (1, 'alice');
+UPDATE test_with_pk SET name = 'bob' WHERE id = 1;
+DELETE FROM test_with_pk WHERE id = 1;
+----
+
+=== 参数不影响显式设置为 REPLICA IDENTITY NOTHING 的表
+
+[source,sql]
+----
+-- 创建表并显式设置为 REPLICA IDENTITY NOTHING
+CREATE TABLE test_nothing (id int, data text);
+ALTER TABLE test_nothing REPLICA IDENTITY NOTHING;
+
+-- 即使开启了 logical_replication_fallback_to_full_identity,
+-- UPDATE 和 DELETE 仍然失败(参数不会覆盖显式的 NOTHING 设置)
+INSERT INTO test_nothing VALUES (1, 'test');
+UPDATE test_nothing SET data = 'modified' WHERE id = 1;
+-- ERROR: cannot update table "test_nothing" because it does not have a replica identity and publishes updates
+
+DELETE FROM test_nothing WHERE id = 1;
+-- ERROR: cannot delete from table "test_nothing" because it does not have a replica identity and publishes deletes
+----
+
+=== 运行时动态切换参数
+
+[source,sql]
+----
+-- 关闭参数:无主键表的 UPDATE/DELETE 将恢复为报错行为
+ALTER SYSTEM SET logical_replication_fallback_to_full_identity = off;
+SELECT pg_reload_conf();
+
+-- 开启参数:无主键表的 UPDATE/DELETE 将正常工作
+ALTER SYSTEM SET logical_replication_fallback_to_full_identity = on;
+SELECT pg_reload_conf();
+----
+
+== 功能限制
+
+. 该参数仅对复制标识为 `REPLICA IDENTITY DEFAULT` 且没有主键的表生效;已显式设置为 `FULL`、`USING INDEX` 或 `NOTHING` 的表不受影响;
+. 开启该参数后,无主键表的 UPDATE 和 DELETE 会在 WAL 中记录完整的旧行数据(与 `REPLICA IDENTITY FULL` 效果相同),相比有主键时只记录主键列,会增加 WAL 体积和网络传输量;
+. 该参数仅在发布端生效,订阅端无需配置;
+. INSERT 操作不依赖复制标识,无论该参数是否开启均可正常复制;
+. 该参数不替代显式的 `ALTER TABLE ... REPLICA IDENTITY FULL` 设置,也不会覆盖显式设置为 `NOTHING` 的表。
diff --git a/CN/modules/ROOT/pages/v1.22/43.adoc b/CN/modules/ROOT/pages/v1.22/43.adoc
new file mode 100644
index 0000000..dfdb6e6
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/43.adoc
@@ -0,0 +1,170 @@
+:sectnums:
+:sectnumlevels: 5
+
+:imagesdir: ./_images
+
+= 修改列类型时自动重建依赖视图
+
+== 功能介绍
+
+在标准 PostgreSQL 中,若某列被视图所引用,执行 `ALTER TABLE ... ALTER COLUMN ... TYPE` 修改该列的数据类型时,数据库会直接报错:
+
+----
+ERROR: cannot alter type of a column used by a view or rule
+----
+
+用户必须手动删除所有依赖视图,完成列类型修改后再逐一重建,操作繁琐且容易出错,在存在多层视图依赖时尤为困难。
+
+IvorySQL 对此行为进行了增强:执行列类型变更时,数据库会自动保存所有依赖视图(包括间接依赖的级联视图)的定义,在完成类型修改后按正确顺序重建这些视图
+,对用户完全透明。若重建过程中发生错误(例如视图使用了新类型不支持的操作符),整个 `ALTER TABLE` 操作将整体回滚,保证数据一致性。
+
+该功能同时支持 PG 兼容模式与 Oracle 兼容模式。
+
+== 语法
+
+语法与标准 `ALTER TABLE` 完全一致,无需额外关键字:
+
+[source,sql]
+----
+ALTER TABLE table_name ALTER COLUMN column_name TYPE new_type;
+----
+
+参数说明:
+
+- `table_name`:目标表名,可带 schema 前缀;
+- `column_name`:需要修改类型的列名;
+- `new_type`:目标数据类型,需与原类型兼容或可隐式转换。
+
+== 测试用例
+
+=== 单视图依赖:自动重建
+
+[source,sql]
+----
+-- 创建基表
+CREATE TABLE t (a int, b text);
+
+-- 创建依赖列 a 的视图
+CREATE VIEW v AS SELECT a, b FROM t;
+
+-- 标准 PostgreSQL 此处会报错,IvorySQL 自动重建视图
+ALTER TABLE t ALTER COLUMN a TYPE bigint;
+
+-- 验证视图仍然有效,且列类型已更新
+SELECT pg_typeof(a) FROM v LIMIT 1;
+-- 返回 bigint
+ pg_typeof
+-----------
+(0 rows)
+
+
+\d v
+ View "public.v"
+ Column | Type | Collation | Nullable | Default
+--------+--------+-----------+----------+---------
+ a | bigint | | |
+ b | text | | |
+----
+
+=== 级联视图依赖:按序自动重建
+
+[source,sql]
+----
+-- 创建基表
+CREATE TABLE t (a int, b text);
+
+-- 创建两层视图依赖:v2 依赖 v1,v1 依赖 t
+CREATE VIEW v1 AS SELECT a, b FROM t;
+CREATE VIEW v2 AS SELECT a FROM v1;
+
+-- 修改列类型,自动按依赖顺序重建 v1、v2
+ALTER TABLE t ALTER COLUMN a TYPE bigint;
+
+-- 验证两个视图均已正确重建
+SELECT pg_typeof(a) FROM v1 LIMIT 1;
+-- 返回 bigint
+ pg_typeof
+-----------
+(0 rows)
+
+SELECT pg_typeof(a) FROM v2 LIMIT 1;
+-- 返回 bigint
+ pg_typeof
+-----------
+(0 rows)
+----
+
+=== 保留视图选项:security_barrier
+
+[source,sql]
+----
+-- 创建带 security_barrier 选项的视图
+CREATE VIEW v WITH (security_barrier) AS SELECT a, b FROM t;
+
+ALTER TABLE t ALTER COLUMN a TYPE bigint;
+
+-- 验证 security_barrier 选项在重建后被正确保留
+SELECT relname, reloptions FROM pg_class WHERE relname = 'v';
+-- reloptions: {security_barrier=true}
+ relname | reloptions
+---------+-------------------------
+ v | {security_barrier=true}
+(1 row)
+----
+
+=== 保留视图选项:WITH CHECK OPTION
+
+[source,sql]
+----
+-- 创建带 WITH LOCAL CHECK OPTION 的视图
+CREATE VIEW v AS SELECT a, b FROM t WHERE a > 0
+ WITH LOCAL CHECK OPTION;
+
+ALTER TABLE t ALTER COLUMN a TYPE bigint;
+
+-- 验证 CHECK OPTION 在重建后被正确保留
+\d+ v
+ View "public.v"
+ Column | Type | Collation | Nullable | Default | Storage | Description
+--------+--------+-----------+----------+---------+----------+-------------
+ a | bigint | | | | plain |
+ b | text | | | | extended |
+View definition:
+ SELECT t.a,
+ t.b
+ FROM t
+ WHERE t.a > 0;
+Options: check_option=local
+----
+
+=== 重建失败时整体回滚
+
+[source,sql]
+----
+CREATE TABLE t (a int, b text);
+CREATE VIEW v AS SELECT a::integer + 1 AS a_plus FROM t;
+
+-- 若新类型与视图中的表达式不兼容,整个操作回滚
+-- 例如将 a 改为 text 类型,视图中的 a::integer + 1 将无法执行
+ALTER TABLE t ALTER COLUMN a TYPE text;
+ERROR: operator does not exist: text + integer
+LINE 1: ALTER TABLE t ALTER COLUMN a TYPE text;
+ ^
+HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
+
+-- 确认表结构与视图均未受影响
+\d t
+ Table "public.t"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+---------
+ a | integer | | |
+ b | text | | |
+----
+
+== 功能限制
+
+. 若视图中使用了与新列类型不兼容的操作符或函数(例如对 `text` 类型列执行算术运算),重建将失败,整个 `ALTER TABLE` 操作回滚;
+. 仅支持视图(view)的自动重建,依赖该列的**规则(rule)**仍会报错;
+. 列类型变更需满足 PostgreSQL 类型转换规则,不支持任意两种类型之间的直接转换;
+. 视图重建按依赖拓扑顺序执行,循环依赖(通常由数据库约束避免)不在处理范围内;
+. 重建过程在同一事务内完成,期间依赖视图处于不可用状态,高并发场景下需注意对查询的影响。
diff --git a/CN/modules/ROOT/pages/v3.0/5.adoc b/CN/modules/ROOT/pages/v1.22/5.adoc
similarity index 99%
rename from CN/modules/ROOT/pages/v3.0/5.adoc
rename to CN/modules/ROOT/pages/v1.22/5.adoc
index b50ea7b..601ee64 100644
--- a/CN/modules/ROOT/pages/v3.0/5.adoc
+++ b/CN/modules/ROOT/pages/v1.22/5.adoc
@@ -3,7 +3,7 @@
:sectnumlevels: 5
-= 运维人员指南
+= **日常维护**
== 日常清理
diff --git a/CN/modules/ROOT/pages/v1.22/6.adoc b/CN/modules/ROOT/pages/v1.22/6.adoc
new file mode 100644
index 0000000..3ba012f
--- /dev/null
+++ b/CN/modules/ROOT/pages/v1.22/6.adoc
@@ -0,0 +1,539 @@
+
+:sectnums:
+:sectnumlevels: 5
+
+
+= **安装指南**
+
+== CentOS安装概述
+
+本文介绍 IvorySQL 在Linux平台(以CentOS 7为例)的安装过程及注意事项。本文主要演示数据库在Centos 7环境下rpm包安装步骤、源码安装步骤。
+
+=== 软硬件要求
+
+==== 软件资源介绍
+
+|====
+|操作系统|RPM包下载地址
+|CentOS 7|https://github.com/IvorySQL/IvorySQL/releases
+|====
+
+
+==== 硬件资源准备
+|====
+|**配置参数**|**最低配置**|**推荐配置**
+|**CPU**|4核|16核
+|**内存**|4GB|64GB
+|**存储**|800MB,机械硬盘|5GB以上,SSD或NvMe
+|**网络**|千兆网络|万兆网络
+|====
+
+=== 环境和配置检查
+
+部署 IvorySQL 数据库前,您需要进行系统环境和配置检查
+
+==== 查看资源
+
+IvorySQL 数据库支持CentOS 7.X操作系统。详细信息,参考<<#_软硬件要求>>
+
+
+==== 查看操作系统
+
+**CentOS 7.X**
+
+运行以下命令,查看操作系统信息:
+
+ cat /etc/redhat-release
+
+==== 查看内核参数
+
+ uname -r
+
+==== 查看内存,清理缓存
+----
+ free -g
+
+ echo 3 > /proc/sys/vm/drop_caches
+----
+
+=== 获取安装包
+
+您可以通过 源码安装 IvorySQL 数据库或 RPM 包安装。
+
+==== 使用源码构建IvorySQL数据库
+
+1.获取源代码:运行以下命令,克隆 IvorySQL 数据库源代码到您的构建机器:
+----
+git clone https://github.com/IvorySQL/IvorySQL.git
+----
+
+> 注意:克隆代码需要先安装配置 Git。详细信息,参考 https://git-scm.com/doc[Git 文档]
+
+
+2.安装依赖包:要从源代码编译 IvorySQL,必须确保系统上有可用的先决条件包。 执行以下命令安装相关包:
+----
+sudo yum install -y bison-devel readline-devel zlib-devel openssl-devel wget
+sudo yum groupinstall -y 'Development Tools'
+----
+
+> 说明:“Development Tools” 包含了gcc,make,flex,bison。
+
+3.自行编译安装:前面通过获取的源码在文件夹IvorySQL里,接下来我们就进入这个文件夹进行操作。
+
+3.1 配置:Root用户执行以下命令进行配置:
+----
+git checkout tags/Ivory_REL_1_17
+./configure --prefix=/usr/local/ivorysql/ivorysql-1.22
+----
+> 说明: 如果没有提供 `--prefix`,默认将安装在 `/usr/local/ivorysql`。
+>
+> 注意:我们要记住指定的目录,因为系统查不出已经编译安装的程序在哪。更多 configure 参数通过 `./configure --help` 查看。还可以查看 PostgreSQL 手册。
+
+3.2 编译安装:配置完成后,执行 make 进行编译:
+
+ make
+
+要在安装新编译的服务之前使用回归测试测试一下,以下命令均可:
+
+----
+make check
+make all-check-world
+----
+
+然后安装:
+
+ sudo make install
+
+
+==== 使用 RPM 包安装 IvorySql 数据库
+
+1. 运行以下命令,下载 IvorySQL 安装包。
+----
+wget https://github.com/IvorySQL/IvorySQL/releases/download/Ivory_REL_1_17/IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
+----
+
+> 注意:示例中的安装包可能不是最新版本,建议您下载最新的安装包。
+
+2.运行以下命令,安装 IvorySQL 。
+----
+-- 先安装依赖
+yum install -y libicu libxslt python3
+rpm -ivh IvorySQL-1.22-5a0861c-20260416.x86_64.rpm
+----
+
+=== 初始化数据库服务
+
+==== 初始化数据库
+
+1. 创建操作系统用户:用户root会话下,新建用户 ivorysql:
+----
+/usr/sbin/groupadd ivorysql
+/usr/sbin/useradd -g ivorysql ivorysql -c "IvorySQL1.22"
+passwd ivorysql
+----
+
+
+2.环境变量:切换到用户ivorysql,修改文件 `/home/ivorysql/.bash_profile`,配置环境变量:
+----
+umask 022
+export LD_LIBRARY_PATH=/opt//lib:$LD_LIBRARY_PATH
+export PATH=/opt//bin:$PATH
+export PGDATA=/home/ivorysql/data
+----
+
+使环境变量在当前ivorysql用户会话中生效:
+
+ source .bash_profile
+
+也可以重新登录或开启一个新的用户ivorysql的会话。
+
+3.设置防火墙:如果开启了防火墙,还需要将端口1521或者5432开放:
+----
+firewall-cmd --zone=public --add-port=1521/tcp --permanent
+firewall-cmd --reload
+----
+
+> 说明:默认端口是1521,如果不开放该端口,外部客户端通过ip连接会失败。
+
+4.初始化:在用户ivorysql下,简单执行initdb就可以完成初始化:
+
+ initdb
+
+
+> 说明:initdb操作与PostgreSQL一样,可以按照PG的习惯去初始化。
+
+5.启动数据库:使用pg_ctl启动数据库服务:
+
+ pg_ctl start
+
+查看状态,启动成功:
+
+ pg_ctl status
+
+=== 配置服务
+
+1. 客户端验证:修改 /home/ivorysql/data/pg_hba.conf,追加以下内容:
+
+ host all all 0.0.0.0/0 trust
+
+
+> 注意:trust,设置免密登录。
+
+执行以下命令加载配置:
+
+ pg_ctl reload
+
+2.基本参数
+
+通过psql连接数据库:
+
+ psql
+
+修改监听地址
+
+ alter system set listen_address = '*';
+
+> 说明:默认是监听在127.0.0.1,主机外是连不上服务的。
+
+3.守护服务
+
+创建service文件:
+
+ touch /usr/lib/systemd/system/ivorysql.service
+
+编辑内容如下:
+----
+[Unit]
+Description=IvorySQL 1.22 database server
+Documentation=https://www.ivorysql.org
+Requires=network.target local-fs.target
+After=network.target local-fs.target
+
+[Service]
+Type=forking
+
+User=ivorysql
+Group=ivorysql
+
+Environment=PGDATA=/home/ivorysql/data
+
+OOMScoreAdjust=-1000
+
+ExecStart=/opt//bin/pg_ctl start -D ${PGDATA}
+ExecStop=/opt//bin/pg_ctl stop -D ${PGDATA}
+ExecReload=/opt//bin/pg_ctl reload -D ${PGDATA}
+
+TimeoutSec=0
+
+[Install]
+WantedBy=multi-user.target
+
+----
+
+> 说明:service的写法有很多,在生产环境使用时需谨慎,请多次重复测试。
+
+停止pg_ctl启动的数据库服务,启用systemd服务并启动:
+
+ systemctl enable --now ivorysql.service
+
+IvorSQL数据库服务操作命令:
+----
+systemctl start ivorysql.service --启动数据库服务
+systemctl stop ivorysql.service --停止数据库服务
+systemctl restart ivorysql.service --重启数据库
+systemctl status ivorysql.service --查看数据库状态
+systemctl reload ivorysql.service --可以满足部分数据库配置修改完后生效
+----
+
+=== 卸载 IvorySQL 数据库
+
+==== 编译卸载
+
+1.备份数据:我们需要将数据目录保护好,最好停止数据库服务后做备份。
+
+```
+systemctl stop ivorysql.service
+```
+
+2.编译卸载:root会话下切到源码目录下,分别执行以下命令:
+
+```
+make uninstall
+make clean
+```
+
+3.删除残余目录和文件:
+
+```
+systemctl disable ivorysql.servicemake --禁用服务
+mv /usr/lib/systemd/system/ivorysql.service /tmp/ --服务文件移到/tmp,删除也可以
+rm -fr /opt/ --删除残留安装目录
+```
+
+> 说明:还有用户ivorysql以及对应的环境变量,可以根据情况是否清理。剩下的就是数据目录了,请务必做好备份再做处理。还有安装的依赖包,可根据情况决定是否卸载。
+
+== Ubuntu安装概述
+
+本文介绍 IvorySQL 在Linux平台Ubuntu(以Ubuntu2404为例)的安装过程及注意事项。演示数据库在Ubuntu 2404环境下deb包安装步骤、源码安装步骤。
+
+=== 软硬件要求
+
+==== 软件资源介绍
+
+|====
+|操作系统|DEB包下载地址
+|Ubuntu 2404|https://github.com/IvorySQL/IvorySQL/releases
+|====
+
+
+==== 硬件资源准备
+|====
+|**配置参数**|**最低配置**|**推荐配置**
+|**CPU**|4核|16核
+|**内存**|4GB|64GB
+|**存储**|800MB,机械硬盘|5GB以上,SSD或NvMe
+|**网络**|千兆网络|万兆网络
+|====
+
+=== 环境和配置检查
+
+部署 IvorySQL 数据库前,您需要进行系统环境和配置检查
+
+==== 查看资源
+
+IvorySQL 数据库支持Ubuntu24.x操作系统。详细信息,参考<<#_软硬件要求>>
+
+
+==== 查看操作系统
+
+**Ubuntu 24/22.0x**
+
+运行以下命令,查看操作系统信息:
+
+ cat /etc/os-release
+
+==== 查看内核参数
+
+ uname -r
+
+=== 获取安装包
+
+您可以通过源码安装IvorySQL数据库或DEB包安装。
+
+==== 使用源码构建IvorySQL数据库
+
+1.获取源代码:运行以下命令,克隆 IvorySQL 数据库源代码到您的构建机器:
+----
+git clone https://github.com/IvorySQL/IvorySQL.git
+----
+
+> 注意:克隆代码需要先安装配置 Git。详细信息,参考 https://git-scm.com/doc[Git 文档]
+
+
+2.安装依赖包:要从源代码编译 IvorySQL,必须确保系统上有可用的先决条件包。 执行以下命令安装相关包:
+----
+sudo apt install -y bison-devel readline-devel zlib-devel openssl-devel wget
+sudo apt install -y gcc make flex bison
+----
+
+3.自行编译安装:前面通过获取的源码在文件夹IvorySQL里,接下来我们就进入这个文件夹进行操作。
+
+3.1 配置:Root用户执行以下命令进行配置:
+----
+git checkout tags/Ivory_REL_1_17
+./configure --prefix=/usr/local/ivorysql/
+
+----
+> 说明: 如果没有提供 `--prefix`,默认将安装在 `/usr/local/ivorysql`。
+>
+> 注意:我们要记住指定的目录,因为系统查不出已经编译安装的程序在哪。更多 configure 参数通过 `./configure --help` 查看。还可以查看 PostgreSQL 手册。
+
+3.2 编译安装:配置完成后,执行 make 进行编译:
+
+ make
+
+在安装新编译的服务之前,建议先进行回归测试以确保稳定性,可以使用以下任意命令执行测试:
+
+----
+make check
+make all-check-world
+----
+
+然后安装:
+
+ sudo make install
+
+
+==== 使用 DEB 包安装 IvorySQL 数据库
+
+1. 运行以下命令,下载 IvorySQL 安装包。
+----
+wget https://github.com/IvorySQL/IvorySQL/releases/download/IvorySQL_1.22/IvorySQL-1.22-5a0861c-20260416.amd64.deb
+----
+
+> 注意:示例中的安装包可能不是最新版本,建议您下载最新的安装包。
+
+2.运行以下命令,安装 IvorySQL 。
+----
+sudo apt install ./IvorySQL-1.22-5a0861c-20260416.amd64.deb
+----
+
+=== 初始化数据库服务
+
+==== 初始化数据库
+
+1. 创建操作系统用户:用户root会话下,新建用户 ivorysql:
+----
+/usr/sbin/groupadd ivorysql
+/usr/sbin/useradd -m -g ivorysql -s /bin/bash -c "IvorySQL1.22" ivorysql
+usermod -a -G sudo ivorysql
+passwd ivorysql
+
+mkdir /home/ivorysql
+chown -R ivorysql:ivorysql /home/ivorysql
+chmod 755 /home/ivorysql
+----
+
+
+2.环境变量:切换到用户ivorysql,修改文件 `/home/ivorysql/.bashrc`,配置环境变量:
+----
+umask 022
+export LD_LIBRARY_PATH=/opt//lib:$LD_LIBRARY_PATH
+export PATH=/opt//bin:/usr/local/ivorysql//bin:$PATH #取决于安装路径
+export PGDATA=/home/ivorysql/data
+----
+
+使环境变量在当前ivorysql用户会话中生效:
+
+ source .bashrc
+
+也可以重新登录或开启一个新的用户ivorysql的会话。
+
+3.设置防火墙:如果开启了防火墙,还需要将端口1521或者5432开放:
+----
+firewall-cmd --zone=public --add-port=1521/tcp --permanent
+firewall-cmd --reload
+----
+
+> 说明:默认端口是1521,外部客户端若想通过此端口连接需开放该端口。
+
+4.初始化:在用户ivorysql下,简单执行initdb就可以完成初始化:
+
+ initdb -D $PGDATA
+
+
+> 说明:initdb操作与PostgreSQL一样,可以按照PG的习惯去初始化。
+
+5.启动数据库:使用pg_ctl启动数据库服务:
+
+ pg_ctl -D $PGDATA -l logfile start
+
+查看状态:
+
+ pg_ctl -D $PGDATA status
+
+启动成功会有如下输出:
+
+ pg_ctl: server is running (PID: 2273)
+
+=== 配置服务
+
+1. 客户端验证:修改 $PGDATA/pg_hba.conf,追加以下内容:
+
+ host all all 0.0.0.0/0 trust
+
+
+> 注意:trust,设置免密登录。
+
+监听地址:修改$PGDATA/postgresql.conf ,追加以下内容:
+
+ listen_addresses = '*'
+
+> 说明:默认是监听在127.0.0.1,主机外是连不上服务的。
+
+执行以下命令加载配置:
+
+ pg_ctl reload
+
+2.连接数据库
+
+通过psql连接数据库:
+
+ psql
+
+3.守护服务
+
+创建service文件:
+
+ sudo vi /etc/systemd/system/ivorysql.service
+
+编辑内容如下:
+----
+[Unit]
+Description=IvorySQL 1.22 database server
+Documentation=https://www.ivorysql.org
+Requires=network.target local-fs.target
+After=network.target local-fs.target
+
+[Service]
+Type=forking
+
+User=ivorysql
+Group=ivorysql
+
+Environment=PGDATA=/home/ivorysql/data
+
+OOMScoreAdjust=-1000
+
+ExecStart=/usr/local/ivorysql//bin/pg_ctl start -D ${PGDATA}
+ExecStop=/usr/local/ivorysql//bin/pg_ctl stop -D ${PGDATA}
+ExecReload=/usr/local/ivorysql//bin/pg_ctl reload -D ${PGDATA}
+
+TimeoutSec=0
+
+[Install]
+WantedBy=multi-user.target
+
+----
+
+> 说明:service的写法有很多,在生产环境使用时需谨慎,请多次重复测试。
+
+停止pg_ctl启动的数据库服务,启用systemd服务并启动:
+
+ systemctl enable --now ivorysql.service
+
+IvorSQL数据库服务操作命令:
+----
+systemctl start ivorysql.service --启动数据库服务
+systemctl stop ivorysql.service --停止数据库服务
+systemctl restart ivorysql.service --重启数据库
+systemctl status ivorysql.service --查看数据库状态
+systemctl reload ivorysql.service --可以满足部分数据库配置修改完后生效
+----
+
+=== 卸载 IvorySQL 数据库
+
+==== 编译卸载
+
+1.备份数据:我们需要将数据目录保护好,最好停止数据库服务后做备份。
+
+```
+systemctl stop ivorysql.service
+```
+
+2.编译卸载:root会话下切到源码目录下,分别执行以下命令:
+
+```
+make uninstall
+make clean
+```
+
+3.删除残余目录和文件:
+
+```
+systemctl disable ivorysql.service --禁用服务
+mv /usr/lib/systemd/system/ivorysql.service /tmp/ --服务文件移到/tmp
+rm -fr /usr/local/ivorysql/ --删除残留安装目录
+```
+
+> 说明:还有用户ivorysql以及对应的环境变量,可以根据情况是否清理。剩下的就是数据目录了,请务必做好备份再做处理。还有安装的依赖包,可根据情况决定是否卸载。
\ No newline at end of file
diff --git a/CN/modules/ROOT/pages/v3.0/7.adoc b/CN/modules/ROOT/pages/v1.22/7.adoc
similarity index 62%
rename from CN/modules/ROOT/pages/v3.0/7.adoc
rename to CN/modules/ROOT/pages/v1.22/7.adoc
index b57fff6..90b9d09 100644
--- a/CN/modules/ROOT/pages/v3.0/7.adoc
+++ b/CN/modules/ROOT/pages/v1.22/7.adoc
@@ -16,7 +16,7 @@ IvorySQL提供的扩展功能将使用户能够建立高性能和可扩展的Pos
### 架构概述
-为了对原有的 PostgreSQL 改动最小的前提下,实现对 Oracle 兼容。我们需要实现双 parser、双端口、模式 PL/pgSQL 实现 PL/iSQL 的框架。实现流程图如下:
+在对原有的PostgreSQL改动最小的前提下,实现对Oracle的兼容。我们需要实现双parser、双端口、模式PL/pgSQL实现PL/iSQL的框架。实现流程图如下:
image::p4.png[]
image::p5.png[]
@@ -31,9 +31,9 @@ image::p6.png[]
=== 创建一个数据库
-看看你能否访问数据库服务器的第一个例子就是试着创建一个数据库。 一台运行着的IvorySQL服务器可以管理许多数据库。 通常我们会为每个项目和每个用户单独使用一个数据库。
+看看你能否访问数据库服务器的第一个例子就是试着创建一个数据库。一台运行着的IvorySQL服务器可以管理许多数据库。通常我们会为每个项目和每个用户单独使用一个数据库。
-你的站点管理员可能已经为你创建了可以使用的数据库。 如果这样你就可以省略这一步, 并且跳到下一节。
+你的站点管理员可能已经为你创建了可以使用的数据库。如果这样你就可以省略这一步,并且跳到下一节。
要创建一个新的数据库,在我们这个例子里叫`mydb`,你可以使用下面的命令:
@@ -49,7 +49,7 @@ $ createdb mydb
createdb: command not found
```
-那么就是IvorySQL没有安装好。或者是根本没安装, 或者是你的shell搜索路径没有设置正确。尝试用绝对路径调用该命令试试:
+那么就是IvorySQL没有安装好。或者是根本没安装,或者是你的shell搜索路径没有设置正确。尝试用绝对路径调用该命令试试:
```
$ /usr/local/pgsql/bin/createdb mydb
@@ -64,7 +64,7 @@ createdb: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No
Is the server running locally and accepting connections on that socket?
```
-这意味着该服务器没有启动,或者在`createdb`期望去连接它的时候没有在监听。同样, 你也要查看安装指导或者咨询管理员。
+这意味着该服务器没有启动,或者在`createdb`期望去连接它的时候没有在监听。同样,你也要查看安装指导或者咨询管理员。
另外一个响应可能是这样:
@@ -72,7 +72,7 @@ createdb: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No
createdb: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL: role "joe" does not exist
```
-在这里提到了你自己的登录名。如果管理员没有为你创建IvorySQL用户帐号, 就会发生这些现象。(IvorySQL用户帐号和操作系统用户帐号是不同的。) 如果你是管理员,参阅 http://www.postgres.cn/docs/14/user-manag.html[第 22 章] 获取创建用户帐号的帮助。 你需要变成安装IvorySQL的操作系统用户的身份(通常是 `postgres`)才能创建第一个用户帐号。 也有可能是赋予你的IvorySQL用户名和你的操作系统用户名不同; 这种情况下,你需要使用`-U`选项或者使用`PGUSER`环境变量指定你的IvorySQL用户名。
+在这里提到了你自己的登录名。如果管理员没有为你创建IvorySQL用户帐号,就会发生这些现象。(IvorySQL用户帐号和操作系统用户帐号是不同的。) 如果你是管理员,参阅 http://www.postgresql.org/docs/17/user-manag.html[第 22 章] 获取创建用户帐号的帮助。你需要变成安装IvorySQL的操作系统用户的身份(通常是 `postgres`)才能创建第一个用户帐号。也有可能是赋予你的IvorySQL用户名和你的操作系统用户名不同;这种情况下,你需要使用`-U`选项或者使用`PGUSER`环境变量指定你的IvorySQL用户名。
如果你有个数据库用户帐号,但是没有创建数据库所需要的权限,那么你会看到下面的信息:
@@ -80,25 +80,23 @@ createdb: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: FAT
createdb: error: database creation failed: ERROR: permission denied to create database
```
-并非所有用户都被许可创建新数据库。 如果IvorySQL拒绝为你创建数据库, 那么你需要让站点管理员赋予你创建数据库的权限。出现这种情况时请咨询你的站点管理员。 如果你自己安装了IvorySQL, 那么你应该以你启动数据库服务器的用户身份登录然后参考手册完成权限的赋予工作。 http://www.postgres.cn/docs/14/tutorial-createdb.html#ftn.id-1.4.3.4.10.4[[1\]]
+并非所有用户都被许可创建新数据库。如果IvorySQL拒绝为你创建数据库,那么你需要让站点管理员赋予你创建数据库的权限。出现这种情况时请咨询你的站点管理员。如果你自己安装了IvorySQL,那么你应该以你启动数据库服务器的用户身份登录然后参考手册完成权限的赋予工作。http://www.postgresql.org/docs/17/tutorial-createdb.html#ftn.id-1.4.3.4.10.4[[1\]]
-你还可以用其它名字创建数据库。IvorySQL允许你在一个站点上创建任意数量的数据库。 数据库名必须是以字母开头并且小于 63 个字符长。 一个方便的做法是创建和你当前用户名同名的数据库。 许多工具假设该数据库名为缺省数据库名,所以这样可以节省你的敲键。 要创建这样的数据库,只需要键入:
+你还可以用其它名字创建数据库。IvorySQL允许你在一个站点上创建任意数量的数据库。数据库名必须是以字母开头并且小于63个字符长。一个方便的做法是创建和你当前用户名同名的数据库。许多工具假设该数据库名为缺省数据库名,所以这样可以节省你的敲键。要创建这样的数据库,只需要键入:
```
$ createdb
```
-
-
-如果你再也不想使用你的数据库了,那么你可以删除它。 比如,如果你是数据库`mydb`的所有人(创建人), 那么你就可以用下面的命令删除它:
+如果你再也不想使用你的数据库了,那么你可以删除它。比如,如果你是数据库`mydb`的所有人(创建人),那么你就可以用下面的命令删除它:
```
$ dropdb mydb
```
-(对于这条命令而言,数据库名不是缺省的用户名,因此你就必须声明它) 。这个动作将在物理上把所有与该数据库相关的文件都删除并且不可取消, 因此做这中操作之前一定要考虑清楚。
+(对于这条命令而言,数据库名不是缺省的用户名,因此你就必须声明它)。这个动作将在物理上把所有与该数据库相关的文件都删除并且不可取消,因此做这中操作之前一定要考虑清楚。
-更多关于 `createdb` 和 `dropdb` 的信息可以分别在 http://www.postgres.cn/docs/14/app-createdb.html[createdb] 和 http://www.postgres.cn/docs/14/app-dropdb.html[dropdb] 中找到。
+更多关于 `createdb` 和 `dropdb` 的信息可以分别在 http://www.postgresql.org/docs/17/app-createdb.html[createdb]和 http://www.postgresql.org/docs/17/app-dropdb.html[dropdb]中找到。
=== 创建一个新表
@@ -116,11 +114,11 @@ CREATE TABLE weather (
你可以在 `psql` 输入这些命令以及换行符。`psql` 可以识别该命令直到分号才结束。
-你可以在 SQL 命令中自由使用空白(即空格、制表符和换行符)。 这就意味着你可以用和上面不同的对齐方式键入命令,或者将命令全部放在一行中。两个划线(“`--`”)引入注释。 任何跟在它后面直到行尾的东西都会被忽略。SQL 是对关键字和标识符大小写不敏感的语言,只有在标识符用双引号包围时才能保留它们的大小写(上例没有这么做)。
+你可以在SQL命令中自由使用空白(即空格、制表符和换行符)。这就意味着你可以用和上面不同的对齐方式键入命令,或者将命令全部放在一行中。两个划线(“`--`”)引入注释。任何跟在它后面直到行尾的东西都会被忽略。SQL是对关键字和标识符大小写不敏感的语言,只有在标识符用双引号包围时才能保留它们的大小写(上例没有这么做)。
-`varchar(80)` 指定了一个可以存储最长 80 个字符的任意字符串的数据类型。 `int` 是普通的整数类型。 `real` 是一种用于存储单精度浮点数的类型。 `date` 类型应该可以自解释(没错,类型为`date`的列名字也是 `date`。 这么做可能比较方便或者容易让人混淆 — 你自己选择)。
+`varchar(80)` 指定了一个可以存储最长80个字符的任意字符串的数据类型。`int` 是普通的整数类型。`real` 是一种用于存储单精度浮点数的类型。`date` 类型应该可以自解释(没错,类型为`date`的列名字也是`date`。这么做可能比较方便或者容易让人混淆 — 你自己选择)。
-IvorySQL支持标准的SQL类型 `int`、`smallint`、`real`、`double precision`、`char(*N*)`、`varchar(*N*)`、`date`、`time`、`timestamp` 和 `interval`,还支持其他的通用功能的类型和丰富的几何类型。IvorySQL中可以定制任意数量的用户定义数据类型。因而类型名并不是语法关键字,除了SQL标准要求支持的特例外。
+IvorySQL支持标准的SQL类型`int`、`smallint`、`real`、`double precision`、`char(*N*)`、`varchar(*N*)`、`date`、`time`、`timestamp`和`interval`,还支持其他的通用功能的类型和丰富的几何类型。IvorySQL中可以定制任意数量的用户定义数据类型。因而类型名并不是语法关键字,除了SQL标准要求支持的特例外。
第二个例子将保存城市和它们相关的地理位置:
@@ -131,7 +129,7 @@ CREATE TABLE cities (
);
```
-类型 `point` 就是一种IvorySQL特有数据类型的例子。
+类型`point`就是一种IvorySQL特有数据类型的例子。
最后,我们还要提到如果你不再需要某个表,或者你想以不同的形式重建它,那么你可以用下面的命令删除它:
@@ -143,7 +141,7 @@ DROP TABLE tablename;
当一个表被创建后,它不包含任何数据。在数据库发挥作用之前,首先要做的是插入数据。一次插入一行数据。你也可以在一个命令中插入多行,但不能插入不完整的行。即使只知道其中一些列的值,也必须创建完整的行。
-要创建一个新行,使用 http://www.postgres.cn/docs/14/sql-insert.html[INSERT] 命令。这条命令要求提供表的名字和其中列的值。例如,考虑 http://www.postgres.cn/docs/14/ddl.html[第 5 章] 中的产品表:
+要创建一个新行,使用 http://www.postgresql.org/docs/17/sql-insert.html[INSERT]命令。这条命令要求提供表的名字和其中列的值。例如,考虑 http://www.postgresql.org/docs/17/ddl.html[第 5 章]中的产品表:
```
CREATE TABLE products (
@@ -186,8 +184,6 @@ INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', DEFAULT);
INSERT INTO products DEFAULT VALUES;
```
-
-
你可以在一个命令中插入多行:
```
@@ -197,8 +193,6 @@ INSERT INTO products (product_no, name, price) VALUES
(3, 'Milk', 2.99);
```
-
-
也可以插入查询的结果(可能没有行、一行或多行):
```
@@ -207,18 +201,18 @@ INSERT INTO products (product_no, name, price)
WHERE release_date = 'today';
```
-这提供了用于计算要插入的行的SQL查询机制( http://www.postgres.cn/docs/14/queries.html[第 7 章] )的全部功能。
+这提供了用于计算要插入的行的SQL查询机制( http://www.postgresql.org/docs/17/queries.html[第 7 章])的全部功能。
.提示
****
-在一次性插入大量数据时,考虑使用 http://www.postgres.cn/docs/14/sql-copy.html[COPY] 命令。它不如 http://www.postgres.cn/docs/14/sql-insert.html[INSERT] 命令那么灵活,但是更高效。
+在一次性插入大量数据时,考虑使用 http://www.postgresql.org/docs/17/sql-copy.html[COPY]命令。它不如 http://www.postgresql.org/docs/17/sql-insert.html[INSERT]命令那么灵活,但是更高效。
****
== 查询数据 参考 第七章查询的组合查询 第十五章 并行查询
=== 组合查询
-两个查询的结果可以用集合操作并、交、差进行组合。语法是
+两个查询的结果可以用集合操作并、交、差进行组合。语法是:
```
query1 UNION [ALL] query2
@@ -226,7 +220,7 @@ query1 INTERSECT [ALL] query2
query1 EXCEPT [ALL] query2
```
-*`query1`*和*`query2`*都是可以使用以上所有特性的查询。集合操作也可以嵌套和级连,例如
+*`query1`*和*`query2`*都是可以使用以上所有特性的查询。集合操作也可以嵌套和级连,例如:
```
query1 UNION query2 UNION query3
@@ -238,15 +232,13 @@ query1 UNION query2 UNION query3
(query1 UNION query2) UNION query3
```
+`UNION`有效地把*`query2`*的结果附加到*`query1`*的结果上(不过我们不能保证这就是这些行实际被返回的顺序)。此外,它将删除结果中所有重复的行,就像`DISTINCT`做的那样,除非你使用了`UNION ALL`。
-
-`UNION`有效地把*`query2`*的结果附加到*`query1`*的结果上(不过我们不能保证这就是这些行实际被返回的顺序)。此外,它将删除结果中所有重复的行, 就象`DISTINCT`做的那样,除非你使用了`UNION ALL`。
-
-`INTERSECT`返回那些同时存在于*`query1`*和*`query2`*的结果中的行,除非声明了`INTERSECT ALL`, 否则所有重复行都被消除。
+`INTERSECT`返回那些同时存在于*`query1`*和*`query2`*的结果中的行,除非声明了`INTERSECT ALL`,否则所有重复行都被消除。
`EXCEPT`返回所有在*`query1`*的结果中但是不在*`query2`*的结果中的行(有时侯这叫做两个查询的*差*)。同样的,除非声明了`EXCEPT ALL`,否则所有重复行都被消除。
-为了计算两个查询的并、交、差,这两个查询必须是“并操作兼容的”,也就意味着它们都返回同样数量的列, 并且对应的列有兼容的数据类型,如 http://www.postgres.cn/docs/14/typeconv-union-case.html[第 10.5 节] 中描述的那样。
+为了计算两个查询的并、交、差,这两个查询必须是“并操作兼容的”,也就意味着它们都返回同样数量的列,并且对应的列有兼容的数据类型,如 http://www.postgresql.org/docs/17/typeconv-union-case.html[第 10.5 节]中描述的那样。
=== 并行查询
@@ -265,11 +257,9 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
(4 rows)
```
-
-
在所有的情形下,`Gather`或*Gather Merge*节点都只有一个子计划,它是将被并行执行的计划的一部分。如果`Gather`或*Gather Merge*节点位于计划树的最顶层,那么整个查询将并行执行。如果它位于计划树的其他位置,那么只有查询中在它之下的那一部分会并行执行。在上面的例子中,查询只访问了一个表,因此除`Gather`节点本身之外只有一个计划节点。因为该计划节点是`Gather`节点的孩子节点,所以它会并行执行。
-http://www.postgres.cn/docs/14/using-explain.html[使用 EXPLAIN] 命令, 你能看到规划器选择的工作者数量。当查询执行期间到达`Gather`节点时,实现用户会话的进程将会请求和规划器选中的工作者数量一样多的 http://www.postgres.cn/docs/14/bgworker.html[后台工作者进程] 。规划器将考虑使用的后台工作者的数量被限制为最多 http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER[max_parallel_workers_per_gather] 个。任何时候能够存在的后台工作者进程的总数由 http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES[max_worker_processes] 和 http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS[max_parallel_workers] 限制。因此,一个并行查询可能会使用比规划中少的工作者来运行,甚至有可能根本不使用工作者。最优的计划可能取决于可用的工作者的数量,因此这可能会导致不好的查询性能。如果这种情况经常发生,那么就应当考虑一下提高`max_worker_processes`和`max_parallel_workers`的值,这样更多的工作者可以同时运行;或者降低`max_parallel_workers_per_gather`,这样规划器会要求少一些的工作者。
+http://www.postgresql.org/docs/17/using-explain.html[使用 EXPLAIN]命令, 你能看到规划器选择的工作者数量。当查询执行期间到达`Gather`节点时,实现用户会话的进程将会请求和规划器选中的工作者数量一样多的 http://www.postgresql.org/docs/17/bgworker.html[后台工作者进程]。规划器将考虑使用的后台工作者的数量被限制为最多 http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER[max_parallel_workers_per_gather]个。任何时候能够存在的后台工作者进程的总数由 http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES[max_worker_processes]和 http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS[max_parallel_workers]限制。因此,一个并行查询可能会使用比规划中少的工作者来运行,甚至有可能根本不使用工作者。最优的计划可能取决于可用的工作者的数量,因此这可能会导致不好的查询性能。如果这种情况经常发生,那么就应当考虑一下提高`max_worker_processes`和`max_parallel_workers`的值,这样更多的工作者可以同时运行;或者降低`max_parallel_workers_per_gather`,这样规划器会要求少一些的工作者。
为一个给定并行查询成功启动的后台工作者进程都将会执行计划的并行部分。这些工作者的领导者也将执行该计划,不过它还有一个额外的任务:它还必须读取所有由工作者产生的元组。当整个计划的并行部分只产生了少量元组时,领导者通常将表现为一个额外的加速查询执行的工作者。反过来,当计划的并行部分产生大量的元组时,领导者将几乎全用来读取由工作者产生的元组并且执行`Gather`或`Gather Merge`节点上层计划节点所要求的任何进一步处理。在这些情况下,领导者所作的执行并行部分的工作将会很少。
@@ -279,22 +269,22 @@ http://www.postgres.cn/docs/14/using-explain.html[使用 EXPLAIN] 命令, 你能
有几种设置会导致查询规划器在任何情况下都不生成并行查询计划。为了让并行查询计划能够被生成,必须配置好下列设置。
-- http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER[max_parallel_workers_per_gather] 必须被设置为大于零的值。这是一种特殊情况,更加普遍的原则是所用的工作者数量不能超过`max_parallel_workers_per_gather`所配置的数量。
+- http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER[max_parallel_workers_per_gather]必须被设置为大于零的值。这是一种特殊情况,更加普遍的原则是所用的工作者数量不能超过`max_parallel_workers_per_gather`所配置的数量。
此外,系统一定不能运行在单用户模式下。因为在单用户模式下,整个数据库系统运行在单个进程中,没有后台工作者进程可用。
如果下面的任一条件为真,即便对一个给定查询通常可以产生并行查询计划,规划器都不会为它产生并行查询计划:
-- 查询要写任何数据或者锁定任何数据库行。如果一个查询在顶层或者 CTE 中包含了数据修改操作,那么不会为该查询产生并行计划。一种例外是,`CREATE TABLE ... AS`、`SELECT INTO`以及`CREATE MATERIALIZED VIEW`这些创建新表并填充它的命令可以使用并行计划。
-- 查询可能在执行过程中被暂停。只要在系统认为可能发生部分或者增量式执行,就不会产生并行计划。例如:用 http://www.postgres.cn/docs/14/sql-declare.html[DECLARE CURSOR] 创建的游标将永远不会使用并行计划。类似地,一个`FOR x IN query LOOP .. END LOOP`形式的 PL/pgSQL 循环也永远不会使用并行计划,因为当并行查询进行时,并行查询系统无法验证循环中的代码执行起来是安全的。
-- 使用了任何被标记为`PARALLEL UNSAFE`的函数的查询。大多数系统定义的函数都被标记为`PARALLEL SAFE`,但是用户定义的函数默认被标记为`PARALLEL UNSAFE`。参见 http://www.postgres.cn/docs/14/parallel-safety.html[第 15.4 节] 中的讨论。
+- 查询要写任何数据或者锁定任何数据库行。如果一个查询在顶层或者CTE中包含了数据修改操作,那么不会为该查询产生并行计划。一种例外是,`CREATE TABLE ... AS`、`SELECT INTO`以及`CREATE MATERIALIZED VIEW`这些创建新表并填充它的命令可以使用并行计划。
+- 查询可能在执行过程中被暂停。只要在系统认为可能发生部分或者增量式执行,就不会产生并行计划。例如:用 http://www.postgresql.org/docs/17/sql-declare.html[DECLARE CURSOR]创建的游标将永远不会使用并行计划。类似地,一个`FOR x IN query LOOP .. END LOOP`形式的 PL/pgSQL 循环也永远不会使用并行计划,因为当并行查询进行时,并行查询系统无法验证循环中的代码执行起来是安全的。
+- 使用了任何被标记为`PARALLEL UNSAFE`的函数的查询。大多数系统定义的函数都被标记为`PARALLEL SAFE`,但是用户定义的函数默认被标记为`PARALLEL UNSAFE`。参见 http://www.postgresql.org/docs/17/parallel-safety.html[第 15.4 节]中的讨论。
- 该查询运行在另一个已经存在的并行查询内部。例如,如果一个被并行查询调用的函数自己发出一个 SQL 查询,那么该查询将不会使用并行计划。这是当前实现的一个限制,但是或许不值得移除这个限制,因为它会导致单个查询使用大量的进程。
即使对于一个特定的查询已经产生了并行查询计划,在一些情况下执行时也不会并行执行该计划。如果发生这种情况,那么领导者将会自己执行该计划在`Gather`节点之下的部分,就好像`Gather`节点不存在一样。上述情况将在满足下面的任一条件时发生:
-- 因为后台工作者进程的总数不能超过 http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES[max_worker_processes],导致不能得到后台工作者进程。
-- 由于为并行查询目的启动的后台工作者数量不能超过 http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS[max_parallel_workers] 这一限制而不能得到后台工作者。
-- 客户端发送了一个执行消息,并且消息中要求取元组的数量不为零。执行消息可见 http://www.postgres.cn/docs/14/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY[扩展查询协议] 中的讨论。因为 http://www.postgres.cn/docs/14/libpq.html[libpq] 当前没有提供方法来发送这种消息,所以这种情况只可能发生在不依赖 libpq 的客户端中。如果这种情况经常发生,那在它可能发生的会话中设置 http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER[max_parallel_workers_per_gather] 为零是一个很好的主意,这样可以避免产生连续运行时次优的查询计划。
+- 因为后台工作者进程的总数不能超过 http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES[max_worker_processes],导致不能得到后台工作者进程。
+- 由于为并行查询目的启动的后台工作者数量不能超过 http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS[max_parallel_workers]这一限制而不能得到后台工作者。
+- 客户端发送了一个执行消息,并且消息中要求取元组的数量不为零。执行消息可见 http://www.postgresql.org/docs/17/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY[扩展查询协议]中的讨论。因为 http://www.postgresql.org/docs/17/libpq.html[libpq]当前没有提供方法来发送这种消息,所以这种情况只可能发生在不依赖 libpq 的客户端中。如果这种情况经常发生,那在它可能发生的会话中设置 http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER[max_parallel_workers_per_gather]为零是一个很好的主意,这样可以避免产生连续运行时次优的查询计划。
==== 并行计划
@@ -324,7 +314,7 @@ IvorySQL通过按两个阶段进行聚集来支持并行聚集。首先,每个
因为`Finalize Aggregate`节点运行在领导者进程上,如果查询产生的分组数相对于其输入行数来说比较大,则查询规划器不会喜欢它。例如,在最坏的情况下,`Finalize Aggregate`节点看到的分组数可能与所有工作者进程在`Partial Aggregate`阶段看到的输入行数一样多。对于这类情况,使用并行聚集显然得不到性能收益。查询规划器会在规划过程中考虑这一点并且不太会在这种情况下选择并行聚集。
-并行聚集并非在所有情况下都被支持。每一个聚集都必须是对并行 http://www.postgres.cn/docs/14/parallel-safety.html[安全的] 并且必须有一个组合函数。如果该聚集有一个类型为`internal`的转移状态,它必须有序列化和反序列化函数。更多细节请参考 http://www.postgres.cn/docs/14/sql-createaggregate.html[CREATE AGGREGATE]。如果任何聚集函数调用包含`DISTINCT`或`ORDER BY`子句,则不支持并行聚集。对于有序集聚集或者当查询涉及`GROUPING SETS`时,也不支持并行聚集。只有在查询中涉及的所有连接也是该计划并行部分的组成部分时,才能使用并行聚集。
+并行聚集并非在所有情况下都被支持。每一个聚集都必须是对并行 http://www.postgresql.org/docs/17/parallel-safety.html[安全的]并且必须有一个组合函数。如果该聚集有一个类型为`internal`的转移状态,它必须有序列化和反序列化函数。更多细节请参考 http://www.postgresql.org/docs/17/sql-createaggregate.html[CREATE AGGREGATE]。如果任何聚集函数调用包含`DISTINCT`或`ORDER BY`子句,则不支持并行聚集。对于有序集聚集或者当查询涉及`GROUPING SETS`时,也不支持并行聚集。只有在查询中涉及的所有连接也是该计划并行部分的组成部分时,才能使用并行聚集。
===== 并行Append
@@ -334,11 +324,11 @@ IvorySQL通过按两个阶段进行聚集来支持并行聚集。首先,每个
此外,和常规的`Append`节点不同(在并行计划中使用时仅有部分子计划),`Parallel Append`节点既可以有部分子计划也可以有非部分子计划。非部分子计划将仅被单个进程扫描,因为扫描它们不止一次会产生重复的结果。因此涉及到追加多个结果集的计划即使在没有有效的部分计划可用时,也能实现粗粒度的并行。例如,考虑一个针对分区表的查询,它只能通过使用一个不支持并行扫描的索引来实现。规划器可能会选择常规`Index Scan`计划的`Parallel Append`。每个索引扫描必须被单一的进程执行完,但不同的扫描可以由不同的进程同时执行。
-http://www.postgres.cn/docs/14/runtime-config-query.html#GUC-ENABLE-PARALLEL-APPEND[enable_parallel_append] 可以被用来禁用这种特性。
+http://www.postgresql.org/docs/17/runtime-config-query.html#GUC-ENABLE-PARALLEL-APPEND[enable_parallel_append]可以被用来禁用这种特性。
===== 并行计划小贴士
-如果我们想要一个查询能产生并行计划但事实上又没有产生,可以尝试减小 http://www.postgres.cn/docs/14/runtime-config-query.html#GUC-PARALLEL-SETUP-COST[parallel_setup_cost] 或者 http://www.postgres.cn/docs/14/runtime-config-query.html#GUC-PARALLEL-TUPLE-COST[parallel_tuple_cost]。当然,这个计划可能比规划器优先产生的顺序计划还要慢,但也不总是如此。如果将这些设置为很小的值(例如把它们设置为零)也不能得到并行计划,那就可能是有某种原因导致查询规划器无法为你的查询产生并行计划。可能的原因可见 http://www.postgres.cn/docs/14/when-can-parallel-query-be-used.html[第 15.2 节] 和 http://www.postgres.cn/docs/14/parallel-safety.html[第 15.4 节]。
+如果我们想要一个查询能产生并行计划但事实上又没有产生,可以尝试减小 http://www.postgresql.org/docs/17/runtime-config-query.html#GUC-PARALLEL-SETUP-COST[parallel_setup_cost]或者 http://www.postgresql.org/docs/17/runtime-config-query.html#GUC-PARALLEL-TUPLE-COST[parallel_tuple_cost]。当然,这个计划可能比规划器优先产生的顺序计划还要慢,但也不总是如此。如果将这些设置为很小的值(例如把它们设置为零)也不能得到并行计划,那就可能是有某种原因导致查询规划器无法为你的查询产生并行计划。可能的原因可见 http://www.postgresql.org/docs/17/when-can-parallel-query-be-used.html[第 15.2 节]和 http://www.postgresql.org/docs/17/parallel-safety.html[第 15.4 节]。
在执行一个并行计划时,可以用`EXPLAIN (ANALYZE,VERBOSE)`来显示每个计划节点在每个工作者上的统计信息。这些信息有助于确定是否所有的工作被均匀地分发到所有计划节点以及从总体上理解计划的性能特点。
@@ -354,7 +344,7 @@ ABORT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
==== 描述
-`ABORT`回滚当前事务并且导致由该事务所作的所有更新被丢弃。这个命令的行为与标准SQL命令 http://www.postgres.cn/docs/14/sql-rollback.html[`ROLLBACK`] 的行为一样,并且只是为了历史原因存在。
+`ABORT`回滚当前事务并且导致由该事务所作的所有更新被丢弃。这个命令的行为与标准SQL命令 http://www.postgresql.org/docs/17/sql-rollback.html[`ROLLBACK`]的行为一样,并且只是为了历史原因存在。
==== 参数
@@ -364,11 +354,11 @@ ABORT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
- `AND CHAIN`
- 如果规定了`AND CHAIN` ,新事务立即启动,具有与刚刚完成的事务相同的事务特征(参见 http://www.postgres.cn/docs/14/sql-set-transaction.html[`SET TRANSACTION`])。否则,不会启动新事务。
+ 如果规定了`AND CHAIN` ,新事务立即启动,具有与刚刚完成的事务相同的事务特征(参见 http://www.postgresql.org/docs/17/sql-set-transaction.html[`SET TRANSACTION`])。否则,不会启动新事务。
==== 注解
-使用 http://www.postgres.cn/docs/14/sql-commit.html[`COMMIT`] 成功地终止一个事务。
+使用 http://www.postgresql.org/docs/17/sql-commit.html[`COMMIT`]成功地终止一个事务。
在一个事务块之外发出`ABORT`会发出一个警告消息并且不会产生效果。
@@ -382,7 +372,7 @@ ABORT;
==== 兼容性
-这个命令是一个因为历史原因而存在的IvorySQL扩展。`ROLLBACK`是等效的标准 SQL 命令。
+这个命令是一个因为历史原因而存在的IvorySQL扩展。`ROLLBACK`是等效的标准SQL命令。
=== BEGIN — 开始一个事务块
@@ -399,28 +389,28 @@ BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
```
==== 描述
+
+`BEGIN` 开始一个事务块,也就是说所有 `BEGIN` 命令之后的所有语句将被在一个事务中执行,直到给出一个显式的 http://www.postgresql.org/docs/17/sql-commit.html[`COMMIT`]或者 http://www.postgresql.org/docs/17/sql-rollback.html[`ROLLBACK`]。默认情况下(没有 `BEGIN` ),IvorySQL在“自动提交”模式中执行事务,也就是说每个语句都在自己的事务中执行并且在语句结束时隐式地执行一次提交(如果执行成功,否则会完成一次回滚)。
-`BEGIN`开始一个事务块,也就是说所有 `BEGIN`命令之后的所有语句将被在一个 事务中执行,直到给出一个显式的 http://www.postgres.cn/docs/14/sql-commit.html[`COMMIT`] 或者 http://www.postgres.cn/docs/14/sql-rollback.html[`ROLLBACK`]。 默认情况下(没有`BEGIN`), IvorySQL在 “自动提交”模式中执行事务,也就是说每个语句都 在自己的事务中执行并且在语句结束时隐式地执行一次提交(如果执 行成功,否则会完成一次回滚)。
-
-在一个事务块内的语句会执行得更快,因为事务的开始/提交也要求可观 的 CPU 和磁盘活动。在进行多个相关更改时,在一个事务内执行多个语 句也有助于保证一致性:在所有相关更新还没有完成之前,其他会话将不 能看到中间状态。
+在一个事务块内的语句会执行得更快,因为事务的开始/提交也要求可观的CPU和磁盘活动。在进行多个相关更改时,在一个事务内执行多个语句也有助于保证一致性:在所有相关更新还没有完成之前,其他会话将不能看到中间状态。
-如果指定了隔离级别、读/写模式或者延迟模式,新事务也会有那些特性, 就像执行了 http://www.postgres.cn/docs/14/sql-set-transaction.html[`SET TRANSACTION`]一样。
+如果指定了隔离级别、读/写模式或者延迟模式,新事务也会有那些特性,就像执行了 http://www.postgresql.org/docs/17/sql-set-transaction.html[`SET TRANSACTION`]一样。
==== 参数
-- `WORK` `TRANSACTION`
+- `WORK``TRANSACTION`
可选的关键词。它们没有效果。
-这个语句其他参数的含义请参考 http://www.postgres.cn/docs/14/sql-set-transaction.html[SET TRANSACTION]。
+这个语句其他参数的含义请参考 http://www.postgresql.org/docs/17/sql-set-transaction.html[SET TRANSACTION]。
==== 注解
-http://www.postgres.cn/docs/14/sql-start-transaction.html[`START TRANSACTION`]具有和`BEGIN` 相同的功能。
+http://www.postgresql.org/docs/17/sql-start-transaction.html[`START TRANSACTION`]具有和`BEGIN` 相同的功能。
-使用 http://www.postgres.cn/docs/14/sql-commit.html[`COMMIT`] 或者 http://www.postgres.cn/docs/14/sql-rollback.html[`ROLLBACK`]来终止一个事务块。
+使用 http://www.postgresql.org/docs/17/sql-commit.html[`COMMIT`]或者 http://www.postgresql.org/docs/17/sql-rollback.html[`ROLLBACK`]来终止一个事务块。
-在已经在一个事务块中时发出`BEGIN`将惹出一个警告 消息。事务状态不会被影响。要在一个事务块中嵌套事务,可以使用保 存点(见 http://www.postgres.cn/docs/14/sql-savepoint.html[SAVEPOINT])。
+在已经在一个事务块中时发出`BEGIN`将惹出一个警告消息。事务状态不会被影响。要在一个事务块中嵌套事务,可以使用保存点(见 http://www.postgresql.org/docs/17/sql-savepoint.html[SAVEPOINT])。
由于向后兼容的原因,连续的 *`transaction_modes`* 之间的逗号可以被省略。
@@ -434,11 +424,11 @@ BEGIN;
==== 兼容性
-`BEGIN` 是一种 IvorySQL语言扩展。它等效于 SQL 标准的命令 http://www.postgres.cn/docs/14/sql-start-transaction.html[`START TRANSACTION`],它的参考页 包含额外的兼容性信息。
+`BEGIN` 是一种IvorySQL语言扩展。它等效于SQL标准的命令 http://www.postgresql.org/docs/17/sql-start-transaction.html[`START TRANSACTION`],它的参考页包含额外的兼容性信息。
`DEFERRABLE` *`transaction_mode`* 是一种IvorySQL语言扩展。
-附带地,`BEGIN` 关键词被用于嵌入式 SQL 中的一种 不同目的。在移植数据库应用时,我们建议小心对待事务语义。
+附带地,`BEGIN`关键词被用于嵌入式SQL中的一种不同目的。在移植数据库应用时,我们建议小心对待事务语义。
=== COMMIT — 提交当前事务
@@ -453,13 +443,13 @@ BEGIN;
可选的关键词。它们没有效果。
`AND CHAIN`::
-如果指定了 `AND CHAIN`,则立即启动与刚刚完成的事务具有相同事务特征(参见 http://www.postgres.cn/docs/14/sql-set-transaction.html[SET TRANSACTION])的新事务。 否则,没有新事务被启动。
+如果指定了 `AND CHAIN`,则立即启动与刚刚完成的事务具有相同事务特征(参见 http://www.postgresql.org/docs/17/sql-set-transaction.html[SET TRANSACTION])的新事务。否则,没有新事务被启动。
==== 注解
-使用http://www.postgres.cn/docs/14/sql-rollback.html[ROLLBACK]中止一个事务。
+使用 http://www.postgresql.org/docs/17/sql-rollback.html[ROLLBACK]中止一个事务。
-当不在一个事务内时发出 `COMMIT` 不会 产生危害,但是它会产生一个警告消息。当 `COMMIT AND CHAIN` 不在事务内时是一个错误。
+当不在一个事务内时发出 `COMMIT` 不会产生危害,但是它会产生一个警告消息。当`COMMIT AND CHAIN`不在事务内时是一个错误。
==== 示例
@@ -471,7 +461,7 @@ COMMIT;
==== 兼容性
-命令 `COMMIT` 符合 SQL 标准。 表单 `COMMIT TRANSACTION` 为IvorySQL扩展。
+命令 `COMMIT`符合SQL标准。表单`COMMIT TRANSACTION`为IvorySQL扩展。
=== COMMIT PREPARED — 提交一个早前为两阶段提交预备的事务
@@ -483,7 +473,7 @@ COMMIT PREPARED transaction_id
==== 描述
-`COMMIT PREPARED` 提交一个处于预备状态的事务。
+`COMMIT PREPARED`提交一个处于预备状态的事务。
==== 参数
@@ -492,11 +482,11 @@ COMMIT PREPARED transaction_id
==== 注解
-要提交一个预备的事务,你必须是原先执行该事务的同一用户或者超级用户。 但是不需要处于执行该事务的同一会话中。
+要提交一个预备的事务,你必须是原先执行该事务的同一用户或者超级用户。但是不需要处于执行该事务的同一会话中。
这个命令不能在一个事务块中执行。该预备事务将被立刻提交。
-http://www.postgres.cn/docs/14/view-pg-prepared-xacts.html[`pg_prepared_xacts`] 系统视图中列出了所有当前可用的预备事务。
+http://www.postgresql.org/docs/17/view-pg-prepared-xacts.html[`pg_prepared_xacts`]系统视图中列出了所有当前可用的预备事务。
==== 例子
@@ -508,7 +498,7 @@ COMMIT PREPARED 'foobar';
==== 兼容性
-`COMMIT PREPARED` 是一种 IvorySQL扩展。其意图是用于 外部事务管理系统,其中有些已经被标准涵盖(例如 X/Open XA), 但是那些系统的 SQL 方面未被标准化。
+`COMMIT PREPARED` 是一种IvorySQL扩展。其意图是用于外部事务管理系统,其中有些已经被标准涵盖(例如 X/Open XA),但是那些系统的SQL方面未被标准化。
=== END - 提交当前事务
@@ -520,7 +510,7 @@ END [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
==== 描述
-`END`提交当前事务。 所有该事务做的更改便得对他人可见并且被保证发生崩溃时仍然是持久的。 这个命令是一种IvorySQL扩展,它等效于 http://www.postgres.cn/docs/14/sql-commit.html[`COMMIT`]。
+`END` 提交当前事务。所有该事务做的更改便得对他人可见并且被保证发生崩溃时仍然是持久的。这个命令是一种IvorySQL扩展,它等效于 http://www.postgresql.org/docs/17/sql-commit.html[`COMMIT`]。
==== 参数
@@ -528,13 +518,13 @@ END [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
可选关键词,它们没有效果。
`AND CHAIN`::
-如果规定了`AND CHAIN`,则立即启动与刚完成事务具有相同事务特征(参见 http://www.postgres.cn/docs/14/sql-set-transaction.html[SET TRANSACTION])的新事务。否则,没有新事务被启动。
+如果规定了`AND CHAIN`,则立即启动与刚完成事务具有相同事务特征(参见 http://www.postgresql.org/docs/17/sql-set-transaction.html[SET TRANSACTION])的新事务。否则,没有新事务被启动。
==== 注解
-使用 http://www.postgres.cn/docs/14/sql-rollback.html[`ROLLBACK`]可以中止一个事务。
+使用 http://www.postgresql.org/docs/17/sql-rollback.html[`ROLLBACK`]可以中止一个事务。
-当不在一个事务中时发出 `END` 没有危害,但是会 产生一个警告消息。
+当不在一个事务中时发出`END`没有危害,但是会产生一个警告消息。
==== 示例
@@ -546,7 +536,7 @@ END;
==== 兼容性
-`END` 是一种IvorySQL扩展,它提供和 http://www.postgres.cn/docs/14/sql-commit.html[`COMMIT`]等效的功能,后者在 SQL 标准中指定。
+`END` 是一种IvorySQL扩展,它提供和 http://www.postgresql.org/docs/17/sql-commit.html[`COMMIT`]等效的功能,后者在SQL标准中指定。
=== PREPARE TRANSACTION — 为两阶段提交准备当前事务
@@ -558,40 +548,40 @@ PREPARE TRANSACTION transaction_id
==== 描述
-`PREPARE TRANSACTION` 为两阶段提交准备 当前事务。在这个命令之后,该事务不再与当前会话关联。相反,它的状态 被完全存储在磁盘上,并且有很高的可能性它会被提交成功(即便在请求提 交前发生数据库崩溃)。
+`PREPARE TRANSACTION`为两阶段提交准备当前事务。在这个命令之后,该事务不再与当前会话关联。相反,它的状态被完全存储在磁盘上,并且有很高的可能性它会被提交成功(即便在请求提交前发生数据库崩溃)。
-一旦被准备好,事务稍后就可以分别用 http://www.postgres.cn/docs/14/sql-commit-prepared.html[`COMMIT PREPARED`]或者 http://www.postgres.cn/docs/14/sql-rollback-prepared.html[`ROLLBACK PREPARED`]提交或者回滚。 可以从任何会话而不仅仅是执行原始事务的会话中发出这些命令。
+一旦被准备好,事务稍后就可以分别用 http://www.postgresql.org/docs/17/sql-commit-prepared.html[`COMMIT PREPARED`]或者 http://www.postgresql.org/docs/17/sql-rollback-prepared.html[`ROLLBACK PREPARED`]提交或者回滚。可以从任何会话而不仅仅是执行原始事务的会话中发出这些命令。
-从发出命令的会话的角度来看,`PREPARE TRANSACTION`不像 `ROLLBACK` 命令: 在执行它之后,就没有活跃的当前事务,并且该预备事务的效果也不再可见( 如果该事务被提交,效果将重新变得可见)。
+从发出命令的会话的角度来看,`PREPARE TRANSACTION`不像`ROLLBACK`命令:在执行它之后,就没有活跃的当前事务,并且该预备事务的效果也不再可见(如果该事务被提交,效果将重新变得可见)。
-如果由于任何原因 `PREPARE TRANSACTION` 命令失败,它会变成一个 `ROLLBACK` :当前事务会被取消。
+如果由于任何原因`PREPARE TRANSACTION`命令失败,它会变成一个`ROLLBACK`:当前事务会被取消。
==== 参数
*`transaction_id`*::
-一个任意的事务标识符, `COMMIT PREPARED` 或者`ROLLBACK PREPARED` 以后将用这个标识符来标识这个事务。该标识符必须写成一个字符串,并且长度必须小于 200 字节。它也不能与任何当前已经准备好的事务的标识符相同。
+一个任意的事务标识符,`COMMIT PREPARED`或者`ROLLBACK PREPARED`以后将用这个标识符来标识这个事务。该标识符必须写成一个字符串,并且长度必须小于200字节。它也不能与任何当前已经准备好的事务的标识符相同。
==== 注解
-`PREPARE TRANSACTION` 并不是设计为在应用或者交互式 会话中使用。它的目的是允许一个外部事务管理器在多个数据库或者其他事务性 来源之间执行原子的全局事务。除非你在编写一个事务管理器,否则你可能不会 用到`PREPARE TRANSACTION`。
+`PREPARE TRANSACTION`并不是设计为在应用或者交互式会话中使用。它的目的是允许一个外部事务管理器在多个数据库或者其他事务性来源之间执行原子的全局事务。除非你在编写一个事务管理器,否则你可能不会用到`PREPARE TRANSACTION`。
-这个命令必须在一个事务块中使用。事务块用 http://www.postgres.cn/docs/14/sql-begin.html[`BEGIN`]开始。
+这个命令必须在一个事务块中使用。事务块用 http://www.postgresql.org/docs/17/sql-begin.html[`BEGIN`]开始。
-当前在已经执行过任何涉及到临时表或者会话的临时命名空间、创建带 `WITH HOLD` 的游标或者执行 `LISTEN`、`UNLISTEN` 或 `NOTIFY` 的 事务中,不允许`PREPARE`该事务。这些特性与当前会话 绑定得太过紧密,所以对一个要被准备的事务来说没有什么用处。
+当前在已经执行过任何涉及到临时表或者会话的临时命名空间、创建带`WITH HOLD`的游标或者执行`LISTEN`、`UNLISTEN`或 `NOTIFY`的事务中,不允许`PREPARE`该事务。这些特性与当前会话绑定得太过紧密,所以对一个要被准备的事务来说没有什么用处。
-如果用 `SET`(不带 `LOCAL` 选项)修改过事务的 任何运行时参数,这些效果会持续到 `PREPARE TRANSACTION` 之后,并且将不会被后续的任何 `COMMIT PREPARED` 或 `ROLLBACK PREPARED` 所影响。因此,在这一 方面`PREPARE TRANSACTION` 的行为更像 `COMMIT` 而不是`ROLLBACK`。
+如果用`SET`(不带`LOCAL`选项)修改过事务的任何运行时参数,这些效果会持续到`PREPARE TRANSACTION`之后,并且将不会被后续的任何`COMMIT PREPARED`或`ROLLBACK PREPARED`所影响。因此,在这一 方面`PREPARE TRANSACTION`的行为更像`COMMIT`而不是`ROLLBACK`。
-所有当前可用的准备好事务被列在 http://www.postgres.cn/docs/14/view-pg-prepared-xacts.html[`pg_prepared_xacts`]系统视图中。
+所有当前可用的准备好事务被列在 http://www.postgresql.org/docs/17/view-pg-prepared-xacts.html[`pg_prepared_xacts`]系统视图中。
==== 小心
-让一个事务处于准备好状态太久是不明智的。这将会干扰 `VACUUM` 回收存储的能力,并且在极限情况下可能导致 数据库关闭以阻止事务 ID 回卷(见 http://www.postgres.cn/docs/14/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND[第 25.1.5 节])。还要记住,该事务会继续持有 它已经持有的锁。该特性的设计用法是,只要一个外部事务管理器已经验证 其他数据库也准备好了要提交,一个准备好的事务将被正常地提交或者回滚。
+让一个事务处于准备好状态太久是不明智的。这将会干扰`VACUUM`回收存储的能力,并且在极限情况下可能导致数据库关闭以阻止事务ID回卷(见 http://www.postgresql.org/docs/17/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND[第 25.1.5 节])。还要记住,该事务会继续持有它已经持有的锁。该特性的设计用法是,只要一个外部事务管理器已经验证其他数据库也准备好了要提交,一个准备好的事务将被正常地提交或者回滚。
-如果没有建立一个外部事务管理器来跟踪准备好的事务并且确保它们被迅速地 结束,最好禁用准备好事务特性(设置 http://www.postgres.cn/docs/14/runtime-config-resource.html#GUC-MAX-PREPARED-TRANSACTIONS[max_prepared_transactions] 为零)。这将防止意外 地创建准备好事务,不然该事务有可能被忘记并且最终导致问题。
+如果没有建立一个外部事务管理器来跟踪准备好的事务并且确保它们被迅速地结束,最好禁用准备好事务特性(设置 http://www.postgresql.org/docs/17/runtime-config-resource.html#GUC-MAX-PREPARED-TRANSACTIONS[max_prepared_transactions]为零)。这将防止意外地创建准备好事务,不然该事务有可能被忘记并且最终导致问题。
==== 例子
-为两阶段提交准备当前事务,使用 `foobar` 作为事务标识符:
+为两阶段提交准备当前事务,使用`foobar`作为事务标识符:
```
PREPARE TRANSACTION 'foobar';
@@ -599,7 +589,7 @@ PREPARE TRANSACTION 'foobar';
==== 兼容性
-`PREPARE TRANSACTION` 是一种 IvorySQL扩展。其意图是用于 外部事务管理系统,其中有些已经被标准涵盖(例如 X/Open XA), 但是那些系统的 SQL 方面未被标准化。
+`PREPARE TRANSACTION`是一种IvorySQL扩展。其意图是用于外部事务管理系统,其中有些已经被标准涵盖(例如 X/Open XA),但是那些系统的SQL方面未被标准化。
=== ROLLBACK — 中止当前事务
@@ -611,7 +601,7 @@ ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
==== 描述
-`ROLLBACK` 回滚当前事务并且导致 该事务所作的所有更新都被抛弃。
+`ROLLBACK`回滚当前事务并且导致该事务所作的所有更新都被抛弃。
==== 参数
@@ -619,13 +609,13 @@ ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]
可选关键词,没有效果。
`AND CHAIN`::
-如果指定了 `AND CHAIN` ,则立即启动与刚刚完成事务具有相同事务特征(参见 http://www.postgres.cn/docs/14/sql-set-transaction.html[SET TRANSACTION])的新事务。 否则,不会启动任何新事务。
+如果指定了`AND CHAIN`,则立即启动与刚刚完成事务具有相同事务特征(参见 http://www.postgresql.org/docs/17/sql-set-transaction.html[SET TRANSACTION])的新事务。否则,不会启动任何新事务。
==== 注解
-使用 http://www.postgres.cn/docs/14/sql-commit.html[`COMMIT`]可成功地终止一个事务。
+使用 http://www.postgresql.org/docs/17/sql-commit.html[`COMMIT`]可成功地终止一个事务。
-在一个事务块之外发出 `ROLLBACK` 会发出一个警告并且不会有效果。 事务块之外的 `ROLLBACK AND CHAIN` 是一个错误。
+在一个事务块之外发出`ROLLBACK`会发出一个警告并且不会有效果。事务块之外的`ROLLBACK AND CHAIN`是一个错误。
==== 示例
@@ -637,7 +627,7 @@ ROLLBACK;
==== 兼容性
-命令 `ROLLBACK` 符合 SQL 标准。窗体 `ROLLBACK TRANSACTION` 是一个IvorySQL扩展。
+命令`ROLLBACK`符合SQL标准。窗体`ROLLBACK TRANSACTION`是一个IvorySQL扩展。
=== ROLLBACK PREPARED — 取消一个之前为两阶段提交准备好的事务
@@ -649,7 +639,7 @@ ROLLBACK PREPARED transaction_id
==== 描述
-`ROLLBACK PREPARED` 回滚一个处于准备好状态的事务。
+`ROLLBACK PREPARED`回滚一个处于准备好状态的事务。
==== 参数
@@ -658,15 +648,15 @@ ROLLBACK PREPARED transaction_id
==== 注解
-要回滚一个准备好的事务,你必须是原先执行该事务的同一个用户或者 是一个超级用户。但是你必须处在执行该事务的同一个会话中。
+要回滚一个准备好的事务,你必须是原先执行该事务的同一个用户或者是一个超级用户。但是你必须处在执行该事务的同一个会话中。
这个命令不能在一个事务块内被执行。准备好的事务会被立刻回滚。
-http://www.postgres.cn/docs/14/view-pg-prepared-xacts.html[`pg_prepared_xacts`] 系统视图中列出了当前可用的所有准备好的事务。
+http://www.postgresql.org/docs/17/view-pg-prepared-xacts.html[`pg_prepared_xacts`]系统视图中列出了当前可用的所有准备好的事务。
==== 例子
-用事务标识符 `foobar` 回滚对应的事务:
+用事务标识符`foobar`回滚对应的事务:
```
ROLLBACK PREPARED 'foobar';
@@ -674,7 +664,7 @@ ROLLBACK PREPARED 'foobar';
==== 兼容性
-`ROLLBACK PREPARED` 是一种 IvorySQL扩展。其意图是用于 外部事务管理系统,其中有些已经被标准涵盖(例如 X/Open XA), 但是那些系统的 SQL 方面未被标准化。
+`ROLLBACK PREPARED`是一种IvorySQL扩展。其意图是用于外部事务管理系统,其中有些已经被标准涵盖(例如 X/Open XA),但是那些系统的SQL方面未被标准化。
=== SAVEPOINT — 在当前事务中定义一个新的保存点
@@ -686,7 +676,7 @@ SAVEPOINT savepoint_name
==== 描述
-`SAVEPOINT` 在当前事务中建立一个新保存点。
+`SAVEPOINT`在当前事务中建立一个新保存点。
保存点是事务内的一种特殊标记,它允许所有在它被建立之后执行的命令被回滚,把该事务的状态恢复到它处于保存点时的样子。
@@ -697,7 +687,7 @@ SAVEPOINT savepoint_name
==== 注解
-使用 http://www.postgres.cn/docs/14/sql-rollback-to.html[`ROLLBACK TO`]回滚到一个保存点。 使用 http://www.postgres.cn/docs/14/sql-release-savepoint.html[`RELEASE SAVEPOINT`]销毁一个保存点, 但保持在它被建立之后执行的命令的效果。
+使用 http://www.postgresql.org/docs/17/sql-rollback-to.html[`ROLLBACK TO`]回滚到一个保存点。使用 http://www.postgresql.org/docs/17/sql-release-savepoint.html[`RELEASE SAVEPOINT`]销毁一个保存点,但保持在它被建立之后执行的命令的效果。
保存点只能在一个事务块内建立。可以在一个事务内定义多个保存点。
@@ -732,7 +722,7 @@ COMMIT;
==== 兼容性
-当建立另一个同名保存点时,SQL要求之前的那个保存点自动被销毁。在IvorySQL中,旧的保存点会被保留,不过在进行 回滚或释放时只能使用最近的那一个(用 `RELEASE SAVEPOINT`释放较新的保存点将会导致较旧的保存点再次变得可以被 `ROLLBACK TO SAVEPOINT` 和 `RELEASE SAVEPOINT` 访问)。在其他方面,`SAVEPOINT`完全符合SQL。
+当建立另一个同名保存点时,SQL要求之前的那个保存点自动被销毁。在IvorySQL中,旧的保存点会被保留,不过在进行回滚或释放时只能使用最近的那一个(用 `RELEASE SAVEPOINT`释放较新的保存点将会导致较旧的保存点再次变得可以被`ROLLBACK TO SAVEPOINT`和`RELEASE SAVEPOINT`访问)。在其他方面,`SAVEPOINT`完全符合SQL。
=== SET CONSTRAINTS — 为当前事务设置约束检查时机
@@ -744,27 +734,27 @@ SET CONSTRAINTS { ALL | name [, ...] } { DEFERRED | IMMEDIATE }
==== 描述
-`SET CONSTRAINTS` 设置当前事务内约束检查的行为。`IMMEDIATE` 约束在每个语句结束时被检查。 `DEFERRED` 约束直到事务提交时才被检查。每个约束都有 自己的 `IMMEDIATE` 或 `DEFERRED` 模式。
+`SET CONSTRAINTS`设置当前事务内约束检查的行为。`IMMEDIATE`约束在每个语句结束时被检查。`DEFERRED`约束直到事务提交时才被检查。每个约束都有自己的`IMMEDIATE`或`DEFERRED`模式。
-在创建时,一个约束会被给定三种特性之一: `DEFERRABLE INITIALLY DEFERRED`、 `DEFERRABLE INITIALLY IMMEDIATE` 或者 `NOT DEFERRABLE` 。第三类总是 `IMMEDIATE` 并且不会受到 `SET CONSTRAINTS` 命令的影响。前两类在每个 事务开始时都处于指定的模式,但是它们的行为可以在一个事务内用 `SET CONSTRAINTS` 更改。
+在创建时,一个约束会被给定三种特性之一:`DEFERRABLE INITIALLY DEFERRED`、`DEFERRABLE INITIALLY IMMEDIATE`或者`NOT DEFERRABLE`。第三类总是`IMMEDIATE`并且不会受到`SET CONSTRAINTS`命令的影响。前两类在每个事务开始时都处于指定的模式,但是它们的行为可以在一个事务内用`SET CONSTRAINTS`更改。
-带有一个约束名称列表的 `SET CONSTRAINTS` 只更改那些约束(都必须是可延迟的)的模式。每一个约束名称都可以是 模式限定的。如果没有指定模式名称,则当前的模式搜索路径将被用来寻找 第一个匹配的名称。`SET CONSTRAINTS ALL` 更改所有可延迟约束的模式。
+带有一个约束名称列表的`SET CONSTRAINTS`只更改那些约束(都必须是可延迟的)的模式。每一个约束名称都可以是模式限定的。如果没有指定模式名称,则当前的模式搜索路径将被用来寻找第一个匹配的名称。`SET CONSTRAINTS ALL`更改所有可延迟约束的模式。
-当 `SET CONSTRAINTS` 把一个约束的模式从 `DEFERRED` 改成 `IMMEDIATE` 时, 新模式会有追溯效果:任何还没有解决的数据修改(本来会在事务结束时 被检查)会转而在 `SET CONSTRAINTS` 命令 的执行期间被检查。如果任何这种约束被违背, `SET CONSTRAINTS` 将会失败(并且不会改 变该约束模式)。这样,`SET CONSTRAINTS` 可以被用来在一个事务中的特定点强制进 行约束检查。
+当`SET CONSTRAINTS`把一个约束的模式从`DEFERRED`改成`IMMEDIATE`时,新模式会有追溯效果:任何还没有解决的数据修改(本来会在事务结束时被检查)会转而在`SET CONSTRAINTS`命令的执行期间被检查。如果任何这种约束被违背,`SET CONSTRAINTS`将会失败(并且不会改变该约束模式)。这样,`SET CONSTRAINTS` 可以被用来在一个事务中的特定点强制进行约束检查。
-当前,只有 `UNIQUE`、`PRIMARY KEY`、 `REFERENCES`(外键)以及 `EXCLUDE` 约束受到这个设置的影响。 `NOT NULL` 以及 `CHECK` 约束总是在一行 被插入或修改时立即检查(**不是**在语句结束时)。 没有被声明为 `DEFERRABLE` 的唯一和排除约束也会被 立刻检查。
+当前,只有`UNIQUE`、`PRIMARY KEY`、`REFERENCES`(外键)以及`EXCLUDE`约束受到这个设置的影响。`NOT NULL`以及`CHECK`约束总是在一行被插入或修改时立即检查(**不是**在语句结束时)。没有被声明为`DEFERRABLE`的唯一和排除约束也会被立刻检查。
-被声明为“约束触发器”的触发器的引发也受到这个设置 的控制 — 它们会在相关约束被检查的同时被引发。
+被声明为“约束触发器”的触发器的引发也受到这个设置的控制 — 它们会在相关约束被检查的同时被引发。
==== 注解
-因为IvorySQL并不要求约束名称在模式内唯一(但是在表内要求唯一),可能有多于一个约束匹配指定的约束名称。在这种 情况下 `SET CONSTRAINTS` 将会在所有的匹配上操作。 对于一个非模式限定的名称,一旦在搜索路径中的某个模式中发现一个或者多个匹配,路径中后面的模式将不会被搜索。
+因为IvorySQL并不要求约束名称在模式内唯一(但是在表内要求唯一),可能有多于一个约束匹配指定的约束名称。在这种情况下`SET CONSTRAINTS`将会在所有的匹配上操作。对于一个非模式限定的名称,一旦在搜索路径中的某个模式中发现一个或者多个匹配,路径中后面的模式将不会被搜索。
这个命令只修改当前事务内约束的行为。在事务块外部发出这个命令会产生一个警告并且也不会有任何效果。
==== 兼容性
-这个命令符合 SQL 标准中定义的行为,但有一点限制:在 IvorySQL中,它不会应用在 `NOT NULL` 和 `CHECK` 约束上。还有,IvorySQL会立刻检查非可延迟的 唯一约束,而不是按照标准建议的在语句结束时检查。
+这个命令符合SQL标准中定义的行为,但有一点限制:在 IvorySQL中,它不会应用在`NOT NULL`和`CHECK`约束上。还有,IvorySQL会立刻检查非可延迟的唯一约束,而不是按照标准建议的在语句结束时检查。
=== SET TRANSACTION — 设置当前事务的特性
@@ -775,7 +765,7 @@ SET TRANSACTION transaction_mode [, ...]
SET TRANSACTION SNAPSHOT snapshot_id
SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]
-其中 transaction_mode 是下列之一:
+其中transaction_mode是下列之一:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
READ WRITE | READ ONLY
@@ -784,9 +774,9 @@ SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]
==== 描述
-`SET TRANSACTION` 命令设置当前 会话的特性。`SET SESSION CHARACTERISTICS` 设置一个会话后续事务的默认 事务特性。在个体事务中可以用 `SET TRANSACTION`覆盖这些默认值。
+`SET TRANSACTION`命令设置当前会话的特性。`SET SESSION CHARACTERISTICS`设置一个会话后续事务的默认事务特性。在个体事务中可以用`SET TRANSACTION`覆盖这些默认值。
-可用的事务特性是事务隔离级别、事务访问模式(读/写或只读)以及 可延迟模式。此外,可以选择一个快照,不过只能用于当前事务而不能 作为会话默认值。
+可用的事务特性是事务隔离级别、事务访问模式(读/写或只读)以及可延迟模式。此外,可以选择一个快照,不过只能用于当前事务而不能作为会话默认值。
一个事务的隔离级别决定当其他事务并行运行时该事务能看见什么数据:
@@ -799,29 +789,29 @@ SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]
`SERIALIZABLE`::
当前事务的所有语句只能看到这个事务中执行的第一个查询或者数据修改语句之前提交的行。如果并发的可序列化事务间的读写模式可能导致一种那些事务串行(一次一个)执行时不可能出现的情况,其中之一将会被回滚并且得到一个 `serialization_failure`错误。
-SQL 标准定义了一种额外的级别:`READ UNCOMMITTED`。在IvorySQL中 `READ UNCOMMITTED` 被视作 `READ COMMITTED`。
+SQL标准定义了一种额外的级别:`READ UNCOMMITTED`。在IvorySQL中`READ UNCOMMITTED`被视作`READ COMMITTED`。
-一个事务执行了第一个查询或者数据修改语句( `SELECT`、 `INSERT`、`DELETE`、 `UPDATE`、`FETCH` 或 `COPY`)之后就无法更改事务隔离级别。 更多有关事务隔离级别和并发控制的信息可见 http://www.postgres.cn/docs/14/mvcc.html[第 13 章]。
+一个事务执行了第一个查询或者数据修改语句(`SELECT`、`INSERT`、`DELETE`、`UPDATE`、`FETCH`或`COPY`)之后就无法更改事务隔离级别。更多有关事务隔离级别和并发控制的信息可见 http://www.postgresql.org/docs/17/mvcc.html[第 13 章]。
-事务的访问模式决定该事务是否为读/写或者只读。读/写是默认值。 当一个事务为只读时,如果SQL命令 `INSERT`、`UPDATE`、 `DELETE` 和 `COPY FROM` 要写的表不是一个临时表,则它们不被允许。不允许 `CREATE`、`ALTER`以及 `DROP` 命令。不允许 `COMMENT`、 `GRANT`、`REVOKE`、 `TRUNCATE`。如果 `EXPLAIN ANALYZE` 和`EXECUTE` 要执行的命令是上述命令之一,则它们也不被允许。这是一种高层的只读概念,它不能阻止所有对磁盘的写入。
+事务的访问模式决定该事务是否为读/写或者只读。读/写是默认值。当一个事务为只读时,如果SQL命令`INSERT`、`UPDATE`、`DELETE`和`COPY FROM`要写的表不是一个临时表,则它们不被允许。不允许`CREATE`、`ALTER`以及`DROP`命令。不允许`COMMENT`、`GRANT`、`REVOKE`、`TRUNCATE`。如果`EXPLAIN ANALYZE`和`EXECUTE`要执行的命令是上述命令之一,则它们也不被允许。这是一种高层的只读概念,它不能阻止所有对磁盘的写入。
-只有事务也是 `SERIALIZABLE` 以及 `READ ONLY` 时,`DEFERRABLE` 事务属性才会有效。当一个事务的所有这三个属性都被选择时,该事务在第一次获取其快照时可能会阻塞,在那之后它运行时就不会有 `SERIALIZABLE` 事务的开销并且不会有任何牺牲或者被一次序列化失败取消的风险。这种模式很适合于长时间运行的报表或者备份。
+只有事务也是`SERIALIZABLE`以及`READ ONLY`时,`DEFERRABLE`事务属性才会有效。当一个事务的所有这三个属性都被选择时,该事务在第一次获取其快照时可能会阻塞,在那之后它运行时就不会有`SERIALIZABLE`事务的开销并且不会有任何牺牲或者被一次序列化失败取消的风险。这种模式很适合于长时间运行的报表或者备份。
-`SET TRANSACTION SNAPSHOT` 命令允许新的事务使用与一个现有事务相同的 *快照* 运行。已经存在的事务必须已经把它的快照用 `pg_export_snapshot` 函数(见 http://www.postgres.cn/docs/14/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION[第 9.27.5 节])导出。该函数会返回一个快照标识符,`SET TRANSACTION SNAPSHOT` 需要被给定一个快照标识符来指定要导入的快照。在这个命令中该标识符必须被写成一个字符串,例如 `'000003A1-1'`。 `SET TRANSACTION SNAPSHOT` 只能在一个事务的开始执行,并且要在该事务的第一个查询或者数据修改语句( `SELECT`、 `INSERT`、`DELETE`、 `UPDATE`、`FETCH`或 `COPY`)之前执行。此外,该事务必须已经被设置为`SERIALIZABLE` 或者 `REPEATABLE READ` 隔离级别(否则,该快照将被立刻抛弃,因为 `READ COMMITTED` 模式会为每一个命令取一个新快照)。如果导入事务使用了`SERIALIZABLE` 隔离级别,那么导入快照的事务必须也使用该隔离级别。还有,一个非只读可序列化事务不能导入来自只读事务的快照。
+`SET TRANSACTION SNAPSHOT`命令允许新的事务使用与一个现有事务相同的*快照*运行。已经存在的事务必须已经把它的快照用`pg_export_snapshot` 函数(见 http://www.postgresql.org/docs/17/functions-admin.html#FUNCTIONS-SNAPSHOT-SYNCHRONIZATION[第 9.27.5 节])导出。该函数会返回一个快照标识符,`SET TRANSACTION SNAPSHOT`需要被给定一个快照标识符来指定要导入的快照。在这个命令中该标识符必须被写成一个字符串,例如`'000003A1-1'`。`SET TRANSACTION SNAPSHOT`只能在一个事务的开始执行,并且要在该事务的第一个查询或者数据修改语句(`SELECT`、`INSERT`、`DELETE`、`UPDATE`、`FETCH`或 `COPY`)之前执行。此外,该事务必须已经被设置为`SERIALIZABLE`或者`REPEATABLE READ`隔离级别(否则,该快照将被立刻抛弃,因为`READ COMMITTED`模式会为每一个命令取一个新快照)。如果导入事务使用了`SERIALIZABLE`隔离级别,那么导入快照的事务必须也使用该隔离级别。还有,一个非只读可序列化事务不能导入来自只读事务的快照。
==== 注解
-如果执行 `SET TRANSACTION` 之前没有 `START TRANSACTION` 或者 `BEGIN`,它会发出一个警告并且不会有任何效果。
+如果执行`SET TRANSACTION`之前没有`START TRANSACTION`或者`BEGIN`,它会发出一个警告并且不会有任何效果。
-可以通过在 `BEGIN` 或者 `START TRANSACTION` 中指定想要的 `*transaction_modes*` 来省掉 `SET TRANSACTION`。但是在 `SET TRANSACTION SNAPSHOT` 中该选项不可用。
+可以通过在`BEGIN`或者`START TRANSACTION`中指定想要的`*transaction_modes*`来省掉`SET TRANSACTION`。但是在`SET TRANSACTION SNAPSHOT`中该选项不可用。
-会话默认的事务模式也可以通过配置参数 http://www.postgres.cn/docs/14/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATION[default_transaction_isolation]、 http://www.postgres.cn/docs/14/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-READ-ONLY[default_transaction_read_only] 和 http://www.postgres.cn/docs/14/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-DEFERRABLE[default_transaction_deferrable] 来设置或检查(实际上 `SET SESSION CHARACTERISTICS`只是用 `SET` 设置这些变量的等效体)。这意味着可以通过配置文件、 `ALTER DATABASE` 等方式设置默认值。详见 http://www.postgres.cn/docs/14/runtime-config.html[第 20 章]。
+会话默认的事务模式也可以通过配置参数 http://www.postgresql.org/docs/17/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATION[default_transaction_isolation]、http://www.postgresql.org/docs/17/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-READ-ONLY[default_transaction_read_only]和 http://www.postgresql.org/docs/17/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-DEFERRABLE[default_transaction_deferrable]来设置或检查(实际上`SET SESSION CHARACTERISTICS`只是用`SET`设置这些变量的等效体)。这意味着可以通过配置文件、`ALTER DATABASE` 等方式设置默认值。详见 http://www.postgresql.org/docs/17/runtime-config.html[第 20 章]。
-当前事务的模式可以类似的通过配置参数 http://www.postgres.cn/docs/14/runtime-config-client.html#GUC-TRANSACTION-ISOLATION[transaction_isolation]、 http://www.postgres.cn/docs/14/runtime-config-client.html#GUC-TRANSACTION-READ-ONLY[transaction_read_only]、和 http://www.postgres.cn/docs/14/runtime-config-client.html#GUC-TRANSACTION-DEFERRABLE[transaction_deferrable] 来设置或检查。设置这其中一个参数的作用与相应的 `SET TRANSACTION` 选项相同,在它何时可以完成方面,也有相同的限制。但是,这些参数不能在配置文件中设置,或者从活动SQL以外的任何来源来设置。
+当前事务的模式可以类似的通过配置参数 http://www.postgresql.org/docs/17/runtime-config-client.html#GUC-TRANSACTION-ISOLATION[transaction_isolation]、 http://www.postgresql.org/docs/17/runtime-config-client.html#GUC-TRANSACTION-READ-ONLY[transaction_read_only]、和 http://www.postgresql.org/docs/17/runtime-config-client.html#GUC-TRANSACTION-DEFERRABLE[transaction_deferrable]来设置或检查。设置这其中一个参数的作用与相应的`SET TRANSACTION`选项相同,在它何时可以完成方面,也有相同的限制。但是,这些参数不能在配置文件中设置,或者从活动SQL以外的任何来源来设置。
==== 示例
-要用一个已经存在的事务的同一快照开始一个新事务,首先要从该现有 事务导出快照。这将会返回快照标识符,例如:
+要用一个已经存在的事务的同一快照开始一个新事务,首先要从该现有事务导出快照。这将会返回快照标识符,例如:
```
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
@@ -832,7 +822,7 @@ SELECT pg_export_snapshot();
(1 row)
```
-然后在一个新开始的事务的开头把该快照标识符用在一个 `SET TRANSACTION SNAPSHOT` 命令中:
+然后在一个新开始的事务的开头把该快照标识符用在一个`SET TRANSACTION SNAPSHOT`命令中:
```
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
@@ -841,13 +831,13 @@ SET TRANSACTION SNAPSHOT '00000003-0000001B-1';
==== 兼容性
-SQL标准中定义了这些命令,不过 `DEFERRABLE` 事务模式和 `SET TRANSACTION SNAPSHOT` 形式除外,这两者是 IvorySQL扩展。
+SQL标准中定义了这些命令,不过`DEFERRABLE`事务模式和`SET TRANSACTION SNAPSHOT`形式除外,这两者是IvorySQL扩展。
-`SERIALIZABLE` 是标准中默认的事务隔离级别。在 IvorySQL中默认值是普通的 `READ COMMITTED`,但是你可以按上述的方式更改。
+`SERIALIZABLE`是标准中默认的事务隔离级别。在IvorySQL中默认值是普通的`READ COMMITTED`,但是你可以按上述的方式更改。
-在SQL标准中,可以用这些命令设置一个其他的事务特性:诊断区域 的尺寸。这个概念与嵌入式SQL有关,并且因此没有在IvorySQL服务器中实现。
+在SQL标准中,可以用这些命令设置一个其他的事务特性:诊断区域的尺寸。这个概念与嵌入式SQL有关,并且因此没有在IvorySQL服务器中实现。
-SQL 标准要求连续的 *`transaction_modes`* 之间有逗号,但是出于历史原因IvorySQL允许省略逗号。
+SQL标准要求连续的 *`transaction_modes`* 之间有逗号,但是出于历史原因IvorySQL允许省略逗号。
=== START TRANSACTION — 开始一个事务块
@@ -865,15 +855,15 @@ START TRANSACTION [ transaction_mode [, ...] ]
==== 描述
-这个命令开始一个新的事务块。如果指定了隔离级别、读写模式 或者可延迟模式,新的事务将会具有这些特性,就像执行了 http://www.postgres.cn/docs/14/sql-set-transaction.html[`SET TRANSACTION`]一样。这和 http://www.postgres.cn/docs/14/sql-begin.html[`BEGIN`]命令一样。
+这个命令开始一个新的事务块。如果指定了隔离级别、读写模式或者可延迟模式,新的事务将会具有这些特性,就像执行了 http://www.postgresql.org/docs/17/sql-set-transaction.html[`SET TRANSACTION`]一样。这和 http://www.postgresql.org/docs/17/sql-begin.html[`BEGIN`]命令一样。
==== 参数
-这些参数对于这个语句的含义可参考 http://www.postgres.cn/docs/14/sql-set-transaction.html[SET TRANSACTION]。
+这些参数对于这个语句的含义可参考 http://www.postgresql.org/docs/17/sql-set-transaction.html[SET TRANSACTION]。
==== 兼容性
-在标准中,没有必要发出 `START TRANSACTION` 来开始一个事务块:任何SQL命令会隐式地开始一个块。 IvorySQL的行为可以被视作在每个命令之后隐式地发出一个没有跟随在 `START TRANSACTION` ( 或者`BEGIN`)之后的 `COMMIT` 并且因此通常被称作 “自动提交”。为了方便,其他关系型数据库系统也可能会 提供自动提交特性。
+在标准中,没有必要发出`START TRANSACTION`来开始一个事务块:任何SQL命令会隐式地开始一个块。IvorySQL的行为可以被视作在每个命令之后隐式地发出一个没有跟随在`START TRANSACTION`(或者`BEGIN`)之后的`COMMIT`并且因此通常被称作 “自动提交”。为了方便,其他关系型数据库系统也可能会提供自动提交特性。
`DEFERRABLE` *`transaction_mode`* 是一种IvorySQL语言扩展。
@@ -899,15 +889,15 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there');
另外,*注释* 也可以出现在SQL输入中。它们不是记号,它们和空白完全一样。
-根据标识命令、操作符、参数的记号不同,SQL的语法不很一致。最前面的一些记号通常是命令名,因此在上面的例子中我们通常会说一个“SELECT”、一个“UPDATE”和一个“INSERT”命令。但是例如 `UPDATE` 命令总是要求一个 `SET` 记号出现在一个特定位置,而 `INSERT` 则要求一个 `VALUES` 来完成命令。每个命令的精确语法规则在 http://www.postgres.cn/docs/14/reference.html[第 VI 部分] 中介绍。
+根据标识命令、操作符、参数的记号不同,SQL的语法不很一致。最前面的一些记号通常是命令名,因此在上面的例子中我们通常会说一个“SELECT”、一个“UPDATE”和一个“INSERT”命令。但是例如`UPDATE`命令总是要求一个`SET`记号出现在一个特定位置,而`INSERT`则要求一个`VALUES`来完成命令。每个命令的精确语法规则在 http://www.postgresql.org/docs/17/reference.html[第 VI 部分]中介绍。
==== 标识符和关键词
-上例中的 `SELECT`、`UPDATE` 或 `VALUES` 记号是 *关键词* 的例子,即SQL语言中具有特定意义的词。记号 `MY_TABLE` 和 `A` 则是 *标识符* 的例子。它们标识表、列或者其他数据库对象的名字,取决于使用它们的命令。因此它们有时也被简称为“名字”。关键词和标识符具有相同的词法结构,这意味着我们无法在没有语言知识的前提下区分一个标识符和关键词。一个关键词的完整列表可以在 http://www.postgres.cn/docs/14/sql-keywords-appendix.html[附录 C]中找到。
+上例中的`SELECT`、`UPDATE`或`VALUES`记号是 *关键词* 的例子,即SQL语言中具有特定意义的词。记号`MY_TABLE`和`A`则是 *标识符* 的例子。它们标识表、列或者其他数据库对象的名字,取决于使用它们的命令。因此它们有时也被简称为“名字”。关键词和标识符具有相同的词法结构,这意味着我们无法在没有语言知识的前提下区分一个标识符和关键词。一个关键词的完整列表可以在 http://www.postgresql.org/docs/17/sql-keywords-appendix.html[附录 C]中找到。
-SQL标识符和关键词必须以一个字母(`a`-`z`,也可以是带变音符的字母和非拉丁字母)或一个下划线( _ )开始。后续字符可以是字母、下划线( `_`)、数字(`0`-`9`)或美元符号(`$`)。注意根据SQL标准的字母规定,美元符号是不允许出现在标识符中的,因此它们的使用可能会降低应用的可移植性。SQL标准不会定义包含数字或者以下划线开头或结尾的关键词,因此这种形式的标识符不会与未来可能的标准扩展冲突 。
+SQL标识符和关键词必须以一个字母(`a`-`z`,也可以是带变音符的字母和非拉丁字母)或一个下划线( _ )开始。后续字符可以是字母、下划线(`_`)、数字(`0`-`9`)或美元符号(`$`)。注意根据SQL标准的字母规定,美元符号是不允许出现在标识符中的,因此它们的使用可能会降低应用的可移植性。SQL标准不会定义包含数字或者以下划线开头或结尾的关键词,因此这种形式的标识符不会与未来可能的标准扩展冲突。
-系统中一个标识符的长度不能超过 `NAMEDATALEN`-1 字节,在命令中可以写超过此长度的标识符,但是它们会被截断。默认情况下,`NAMEDATALEN` 的值为64,因此标识符的长度上限为63字节。如果这个限制有问题,可以在 `src/include/pg_config_manual.h` 中修改 `NAMEDATALEN` 常量。
+系统中一个标识符的长度不能超过`NAMEDATALEN`-1字节,在命令中可以写超过此长度的标识符,但是它们会被截断。默认情况下,`NAMEDATALEN`的值为64,因此标识符的长度上限为63字节。如果这个限制有问题,可以在`src/include/pg_config_manual.h`中修改`NAMEDATALEN`常量。
关键词和不被引号修饰的标识符是大小写不敏感的。因此:
@@ -927,9 +917,7 @@ uPDaTE my_TabLE SeT a = 5;
UPDATE my_table SET a = 5;
```
-
-
-这里还有第二种形式的标识符:*受限标识符*或*被引号修饰的标识符*。它是由双引号(`"`)包围的一个任意字符序列。一个受限标识符总是一个标识符而不会是一个关键字。因此 `"select"` 可以用于引用一个名为“select”的列或者表,而一个没有引号修饰的 `select` 则会被当作一个关键词,从而在本应使用表或列名的地方引起解析错误。在上例中使用受限标识符的例子如下:
+这里还有第二种形式的标识符:*受限标识符*或*被引号修饰的标识符*。它是由双引号(`"`)包围的一个任意字符序列。一个受限标识符总是一个标识符而不会是一个关键字。因此`"select"`可以用于引用一个名为“select”的列或者表,而一个没有引号修饰的`select`则会被当作一个关键词,从而在本应使用表或列名的地方引起解析错误。在上例中使用受限标识符的例子如下:
```
UPDATE "my_table" SET "a" = 5;
@@ -937,25 +925,22 @@ UPDATE "my_table" SET "a" = 5;
受限标识符可以包含任何字符,除了代码为0的字符(如果要包含一个双引号,则写两个双引号)。这使得可以构建原本不被允许的表或列的名称,例如包含空格或花号的名字。但是长度限制依然有效。
-引用标识符也使其区分大小写,而未引用的名称总是折叠成小写。例如,标识符 `FOO`、`foo` 和 `"foo"` 在IvorySQL中被认为是相同的,但是 `"Foo"` 和 `"FOO"` 与这三个不同,并且彼此不同。(在IvorySQL中,将不带引号的名称折叠为小写与SQL标准不兼容,SQL标准规定不带引号的名称应折叠为大写。因此,根据标准,`foo` 应等同于 `"FOO"` 而不是 `"foo"`。如果您想编写可移植应用程序,建议您始终引用某个特定的名称,或者永远不要引用它。)
+引用标识符也使其区分大小写,而未引用的名称总是折叠成小写。例如,标识符`FOO`、`foo`和`"foo"`在IvorySQL中被认为是相同的,但是`"Foo"`和`"FOO"`与这三个不同,并且彼此不同。(在IvorySQL中,将不带引号的名称折叠为小写与SQL标准不兼容,SQL标准规定不带引号的名称应折叠为大写。因此,根据标准,`foo`应等同于`"FOO"`而不是`"foo"`。如果您想编写可移植应用程序,建议您始终引用某个特定的名称,或者永远不要引用它。)
-
-一种受限标识符的变体允许包括转义的用代码点标识的Unicode字符。这种变体以 `U&` (大写或小写U跟上一个花号)开始,后面紧跟双引号修饰的名称,两者之间没有任何空白,如 `U&"foo"`(注意这里与操作符 `&` 似乎有一些混淆,但是在`&`操作符周围使用空白避免了这个问题) 。在引号内,Unicode字符可以以转义的形式指定:反斜线接上4位16进制代码点号码或者反斜线和加号接上6位16进制代码点号码。例如,标识符 `"data"` 可以写成:
+一种受限标识符的变体允许包括转义的用代码点标识的Unicode字符。这种变体以`U&`(大写或小写U跟上一个花号)开始,后面紧跟双引号修饰的名称,两者之间没有任何空白,如`U&"foo"`(注意这里与操作符`&`似乎有一些混淆,但是在`&`操作符周围使用空白避免了这个问题)。在引号内,Unicode字符可以以转义的形式指定:反斜线接上4位16进制代码点号码或者反斜线和加号接上6位16进制代码点号码。例如,标识符`"data"`可以写成:
```
U&"d\0061t\+000061"
```
-下面的例子用斯拉夫语字母写出了俄语单词 “slon”(大象):
+下面的例子用斯拉夫语字母写出了俄语单词“slon”(大象):
```
U&"\0441\043B\043E\043D"
```
-
-
-如果希望使用其他转义字符来代替反斜线,可以在字符串后使用 `UESCAPE` 子句,例如:
+如果希望使用其他转义字符来代替反斜线,可以在字符串后使用`UESCAPE`子句,例如:
```
U&"d!0061t!+000061" UESCAPE '!'
@@ -975,7 +960,7 @@ U&"d!0061t!+000061" UESCAPE '!'
===== 字符串常量
-在SQL中,一个字符串常量是一个由单引号( `'` )包围的任意字符序列,例如 `'This is a string'`。为了在一个字符串中包括一个单引号,可以写两个相连的单引号,例如 `'Dianne''s horse'`。注意这和一个双引号( `"` )**不**同。
+在SQL中,一个字符串常量是一个由单引号( `'` )包围的任意字符序列,例如`'This is a string'`。为了在一个字符串中包括一个单引号,可以写两个相连的单引号,例如`'Dianne''s horse'`。注意这和一个双引号(`"`)**不**同。
两个只由空白及**至少一个新行**分隔的字符串常量会被连接在一起,并且将作为一个写在一起的字符串常量来对待。例如:
@@ -1000,7 +985,7 @@ SELECT 'foo' 'bar';
===== C风格转义的字符串常量
-IvorySQL也接受“转义”字符串常量,这也是SQL标准的一个扩展。一个转义字符串常量可以通过在开单引号前面写一个字母 `E`(大写或小写形式)来指定,例如 `E'foo'`(当一个转义字符串常量跨行时,只在第一个开引号之前写 `E` )。在一个转义字符串内部,一个反斜线字符( `\` )会开始一个 C 风格的 *反斜线转义* 序列,在其中反斜线和后续字符的组合表示一个特殊的字节值(如 http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-BACKSLASH-TABLE[表 4.1] 中所示)。
+IvorySQL也接受“转义”字符串常量,这也是SQL标准的一个扩展。一个转义字符串常量可以通过在开单引号前面写一个字母`E`(大写或小写形式)来指定,例如`E'foo'`(当一个转义字符串常量跨行时,只在第一个开引号之前写`E`)。在一个转义字符串内部,一个反斜线字符(`\`)会开始一个C风格的 *反斜线转义* 序列,在其中反斜线和后续字符的组合表示一个特殊的字节值(如 http://www.postgresql.org/docs/17/sql-syntax-lexical.html#SQL-BACKSLASH-TABLE[表 4.1]中所示)。
**表 4.1. 反斜线转义序列**
|====
@@ -1015,18 +1000,18 @@ IvorySQL也接受“转义”字符串常量,这也是SQL标准的一个扩展
| `\u*`xxxx`*`, `\U*`xxxxxxxx`*` (*`x`* = 0–9, A–F) | 16 或 32-位十六进制 Unicode 字符值
|====
-跟随在一个反斜线后面的任何其他字符被当做其字面意思。因此,要包括一个反斜线字符,请写两个反斜线( `\\` )。在一个转义字符串中包括一个单引号除了普通方法 `''` 之外,还可以写成 `\'` 。
+跟随在一个反斜线后面的任何其他字符被当做其字面意思。因此,要包括一个反斜线字符,请写两个反斜线(`\\`)。在一个转义字符串中包括一个单引号除了普通方法`''`之外,还可以写成`\'`。
-你要负责保证你创建的字节序列由服务器字符集编码中合法的字符组成,特别是在使用八进制或十六进制转义时。一个有用的替代方法是使用Unicode转义或替代的Unicode转义语法,如 http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE[第 4.1.2.3 节] 中所述;然后服务器将检查字符转换是否可行。
+你要负责保证你创建的字节序列由服务器字符集编码中合法的字符组成,特别是在使用八进制或十六进制转义时。一个有用的替代方法是使用Unicode转义或替代的Unicode转义语法,如 http://www.postgresql.org/docs/17/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-UESCAPE[第 4.1.2.3 节]中所述;然后服务器将检查字符转换是否可行。
.小心
****
-如果配置参数 http://www.postgres.cn/docs/14/runtime-config-compatible.html#GUC-STANDARD-CONFORMING-STRINGS[standard_conforming_strings] 为 `off` ,那么IvorySQL对常规字符串常量和转义字符串常量中的反斜线转义都识别。不过,从IvorySQL 9.1 开始,该参数的默认值为 `on` ,意味着只在转义字符串常量中识别反斜线转义。这种行为更兼容标准,但是可能打断依赖于历史行为(反斜线转义总是会被识别)的应用。作为一种变通,你可以设置该参数为 `off` ,但是最好迁移到符合新的行为。如果你需要使用一个反斜线转义来表示一个特殊字符,为该字符串常量写上一个 `E`。在 `standard_conforming_strings` 之外,配置参数 http://www.postgres.cn/docs/14/runtime-config-compatible.html#GUC-ESCAPE-STRING-WARNING[escape_string_warning] 和 http://www.postgres.cn/docs/14/runtime-config-compatible.html#GUC-BACKSLASH-QUOTE[backslash_quote] 也决定了如何对待字符串常量中的反斜线。代码零的字符不能出现在一个字符串常量中。
+如果配置参数 http://www.postgresql.org/docs/17/runtime-config-compatible.html#GUC-STANDARD-CONFORMING-STRINGS[standard_conforming_strings]为`off`,那么IvorySQL对常规字符串常量和转义字符串常量中的反斜线转义都识别。不过,在IvorySQL中该参数的默认值为`on`,意味着只在转义字符串常量中识别反斜线转义。这种行为更兼容标准,但是可能打断依赖于历史行为(反斜线转义总是会被识别)的应用。作为一种变通,你可以设置该参数为`off`,但是最好迁移到符合新的行为。如果你需要使用一个反斜线转义来表示一个特殊字符,为该字符串常量写上一个`E`。在`standard_conforming_strings`之外,配置参数 http://www.postgresql.org/docs/17/runtime-config-compatible.html#GUC-ESCAPE-STRING-WARNING[escape_string_warning]和 http://www.postgresql.org/docs/17/runtime-config-compatible.html#GUC-BACKSLASH-QUOTE[backslash_quote]也决定了如何对待字符串常量中的反斜线。代码零的字符不能出现在一个字符串常量中。
****
===== 带有 Unicode 转义的字符串常量
-IvorySQL也支持另一种类型的字符串转义语法,它允许用代码点指定任意 Unicode 字符。一个 Unicode 转义字符串常量开始于 `U&` (大写或小写形式的字母 U,后跟花号),后面紧跟着开引号,之间没有任何空白,例如 `U&'foo'` (注意这产生了与操作符 `&` 的混淆。在操作符周围使用空白来避免这个问题)。在引号内,Unicode 字符可以通过写一个后跟 4 位十六进制代码点编号或者一个前面有加号的 6 位十六进制代码点编号的反斜线来指定。例如,字符串 `'data'` 可以被写为
+IvorySQL也支持另一种类型的字符串转义语法,它允许用代码点指定任意Unicode字符。一个Unicode转义字符串常量开始于`U&`(大写或小写形式的字母U,后跟花号),后面紧跟着开引号,之间没有任何空白,例如`U&'foo'`(注意这产生了与操作符`&`的混淆。在操作符周围使用空白来避免这个问题)。在引号内,Unicode字符可以通过写一个后跟4位十六进制代码点编号或者一个前面有加号的6位十六进制代码点编号的反斜线来指定。例如,字符串`'data'`可以被写为
```
U&'d\0061t\+000061'
@@ -1039,8 +1024,7 @@ U&'\0441\043B\043E\043D'
```
-
-如果想要一个不是反斜线的转义字符,可以在字符串之后使用 `UESCAPE` 子句来指定,例如:
+如果想要一个不是反斜线的转义字符,可以在字符串之后使用`UESCAPE`子句来指定,例如:
```
U&'d!0061t!+000061' UESCAPE '!'
@@ -1050,15 +1034,15 @@ U&'d!0061t!+000061' UESCAPE '!'
要在一个字符串中包括一个表示其字面意思的转义字符,把它写两次。
-4位或6位转义形式可用于指定UTF-16代理项对,以组成代码点大于U+FFFF的字符,尽管从技术上讲,6位形式的可用性使得这是不必要的(代理项对不是直接存储的,而是合并到单个代码点中。)
+4位或6位转义形式可用于指定UTF-16代理项对,以组成代码点大于U+FFFF的字符,尽管从技术上讲,6位形式的可用性使得这是不必要的(代理项对不是直接存储的,而是合并到单个代码点中。)
-如果服务器编码不是 UTF-8,则由这些转义序列之一标识的 Unicode 代码点将转换为实际的服务器编码; 如果不可能,则会报告错误。
+如果服务器编码不是UTF-8,则由这些转义序列之一标识的Unicode代码点将转换为实际的服务器编码;如果不可能,则会报告错误。
-此外,字符串常量的 Unicode 转义语法仅在配置参数 http://www.postgres.cn/docs/14/runtime-config-compatible.html#GUC-STANDARD-CONFORMING-STRINGS[standard_conforming_strings] 开启时才有效。 这是因为否则这种语法可能会混淆解析 SQL 语句的客户端,可能导致 SQL 注入和类似的安全问题。 如果该参数设置为 off,则此语法将被拒绝并显示错误消息。
+此外,字符串常量的Unicode转义语法仅在配置参数 http://www.postgresql.org/docs/17/runtime-config-compatible.html#GUC-STANDARD-CONFORMING-STRINGS[standard_conforming_strings]开启时才有效。这是因为否则这种语法可能会混淆解析SQL语句的客户端,可能导致SQL注入和类似的安全问题。如果该参数设置为off,则此语法将被拒绝并显示错误消息。
===== 美元引用的字符串常量
-虽然用于指定字符串常量的标准语法通常都很方便,但是当字符串中包含了很多单引号或反斜线时很难理解它,因为每一个都需要被双写。要在这种情形下允许可读性更好的查询,IvorySQL提供了另一种被称为“美元引用”的方式来书写字符串常量。一个美元引用的字符串常量由一个美元符号( `$` )、一个可选的另个或更多字符的“标签”、另一个美元符号、一个构成字符串内容的任意字符序列、一个美元符号、开始这个美元引用的相同标签和一个美元符号组成。例如,这里有两种不同的方法使用美元引用指定字符串“Dianne's horse”:
+虽然用于指定字符串常量的标准语法通常都很方便,但是当字符串中包含了很多单引号或反斜线时很难理解它,因为每一个都需要被双写。要在这种情形下允许可读性更好的查询,IvorySQL提供了另一种被称为“美元引用”的方式来书写字符串常量。一个美元引用的字符串常量由一个美元符号(`$`)、一个可选的另个或更多字符的“标签”、另一个美元符号、一个构成字符串内容的任意字符序列、一个美元符号、开始这个美元引用的相同标签和一个美元符号组成。例如,这里有两种不同的方法使用美元引用指定字符串“Dianne's horse”:
```
$$Dianne's horse$$
@@ -1077,9 +1061,9 @@ END;
$function$
```
-这里,序列 `$q$[\t\r\n\v\\]$q$` 表示一个美元引用的文字串 `[\t\r\n\v\\]`,当该函数体被IvorySQL执行时它将被识别。但是因为该序列不匹配外层的美元引用的定界符 `$function$`,它只是一些在外层字符串所关注的常量中的字符而已。
+这里,序列`$q$[\t\r\n\v\\]$q$`表示一个美元引用的文字串`[\t\r\n\v\\]`,当该函数体被IvorySQL执行时它将被识别。但是因为该序列不匹配外层的美元引用的定界符`$function$`,它只是一些在外层字符串所关注的常量中的字符而已。
-一个美元引用字符串的标签(如果有)遵循一个未被引用标识符的相同规则,除了它不能包含一个美元符号之外。标签是大小写敏感的,因此 `$tag$String content$tag$` 是正确的,但是 `$TAG$String content$tag$` 不正确。
+一个美元引用字符串的标签(如果有)遵循一个未被引用标识符的相同规则,除了它不能包含一个美元符号之外。标签是大小写敏感的,因此`$tag$String content$tag$`是正确的,但是`$TAG$String content$tag$`不正确。
一个跟着一个关键词或标识符的美元引用字符串必须用空白与之分隔开,否则美元引用定界符可能会被作为前面标识符的一部分。
@@ -1087,9 +1071,9 @@ $function$
===== 位串常量
-位串常量看起来像常规字符串常量在开引号之前(中间无空白)加了一个 `B`(大写或小写形式),例如 `B'1001'` 。位串常量中允许的字符只有 `0` 和 `1` 。
+位串常量看起来像常规字符串常量在开引号之前(中间无空白)加了一个`B`(大写或小写形式),例如`B'1001'`。位串常量中允许的字符只有`0`和`1`。
-作为一种选择,位串常量可以用十六进制记号法指定,使用一个前导 `X`(大写或小写形式),例如 `X'1FF'`。这种记号法等价于一个用四个二进制位取代每个十六进制位的位串常量。
+作为一种选择,位串常量可以用十六进制记号法指定,使用一个前导`X`(大写或小写形式),例如`X'1FF'`。这种记号法等价于一个用四个二进制位取代每个十六进制位的位串常量。
两种形式的位串常量可以以常规字符串常量相同的方式跨行继续。美元引用不能被用在位串常量中。
@@ -1104,7 +1088,7 @@ digits.[digits][e[+-]digits]
digitse[+-]digits
```
-其中 *`digits`* 是一个或多个十进制数字(0 到 9)。如果使用了小数点,在小数点前面或后面必须至少有一个数字。如果存在一个指数标记( `e` ),在其后必须跟着至少一个数字。在该常量中不能嵌入任何空白或其他字符。注意任何前导的加号或减号并不实际被考虑为常量的一部分,它是一个应用到该常量的操作符。
+其中 *`digits`* 是一个或多个十进制数字(0到9)。如果使用了小数点,在小数点前面或后面必须至少有一个数字。如果存在一个指数标记(`e`),在其后必须跟着至少一个数字。在该常量中不能嵌入任何空白或其他字符。注意任何前导的加号或减号并不实际被考虑为常量的一部分,它是一个应用到该常量的操作符。
这些是合法数字常量的例子:
@@ -1118,9 +1102,9 @@ digitse[+-]digits
----
-如果一个不包含小数点和指数的数字常量的值适合类型 `integer` (32 位),它首先被假定为类型 `integer` 。否则如果它的值适合类型 `bigint` (64 位),它被假定为类型 `bigint` 。再否则它会被取做类型 `numeric` 。包含小数点和/或指数的常量总是首先被假定为类型 `numeric` 。
+如果一个不包含小数点和指数的数字常量的值适合类型`integer`(32 位),它首先被假定为类型`integer`。否则如果它的值适合类型`bigint`(64 位),它被假定为类型`bigint`。再否则它会被取做类型`numeric`。包含小数点和/或指数的常量总是首先被假定为类型`numeric`。
-一个数字常量初始指派的数据类型只是类型转换算法的一个开始点。在大部分情况中,常量将被根据上下文自动被强制到最合适的类型。必要时,你可以通过造型它来强制一个数字值被解释为一种指定数据类型。例如,你可以这样强制一个数字值被当做类型 `real` ( `float4` ):
+一个数字常量初始指派的数据类型只是类型转换算法的一个开始点。在大部分情况中,常量将被根据上下文自动被强制到最合适的类型。必要时,你可以通过造型它来强制一个数字值被解释为一种指定数据类型。例如,你可以这样强制一个数字值被当做类型`real`(`float4`):
```
REAL '1.23' -- string style
@@ -1141,7 +1125,7 @@ CAST ( 'string' AS type )
字符串常量的文本被传递到名为 *`type`* 的类型的输入转换例程中。其结果是指定类型的一个常量。如果对该常量的类型没有歧义(例如,当它被直接指派给一个表列时),显式类型造型可以被忽略,在那种情况下它会被自动强制。
-字符串常量可以使用常规 SQL 记号或美元引用书写。
+字符串常量可以使用常规SQL记号或美元引用书写。
也可以使用一个类似函数的语法来指定一个类型强制:
@@ -1149,15 +1133,15 @@ CAST ( 'string' AS type )
typename ( 'string' )
```
-但是并非所有类型名都可以用在这种方法中,详见 http://www.postgres.cn/docs/14/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS[第 4.2.9 节]。
+但是并非所有类型名都可以用在这种方法中,详见 http://www.postgresql.org/docs/17/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS[第 4.2.9 节]。
-如 http://www.postgres.cn/docs/14/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS[第 4.2.9 节] 中讨论的,`::`、`CAST()` 以及函数调用语法也可以被用来指定任意表达式的运行时类型转换。要避免语法歧义,`*type 'string'*` 语法只能被用来指定简单文字常量的类型。`*type 'string'*` 语法上的另一个限制是它无法对数组类型工作,指定一个数组常量的类型可使用 `::` 或 `CAST()` 。
+如 http://www.postgresql.org/docs/17/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS[第 4.2.9 节]中讨论的,`::`、`CAST()`以及函数调用语法也可以被用来指定任意表达式的运行时类型转换。要避免语法歧义,`*type 'string'*`语法只能被用来指定简单文字常量的类型。`*type 'string'*` 语法上的另一个限制是它无法对数组类型工作,指定一个数组常量的类型可使用`::`或`CAST()`。
-`CAST()` 语法符合SQL。`type 'string'` 语法是该标准的一般化:SQL指定这种语法只用于一些数据类型,但是IvorySQL允许它用于所有类型。带有 `::` 的语法是IvorySQL的历史用法,就像函数调用语法一样。
+`CAST()`语法符合SQL。`type 'string'`语法是该标准的一般化:SQL指定这种语法只用于一些数据类型,但是IvorySQL允许它用于所有类型。带有`::`的语法是IvorySQL的历史用法,就像函数调用语法一样。
==== 操作符
-一个操作符名是最多 `NAMEDATALEN` -1(默认为 63)的一个字符序列,其中的字符来自下面的列表:
+一个操作符名是最多`NAMEDATALEN`-1(默认为63)的一个字符序列,其中的字符来自下面的列表:
----
\+ - * / < > = ~ ! @ # % ^ & | ` ?
@@ -1165,18 +1149,17 @@ typename ( 'string' )
不过,在操作符名上有一些限制:
-- `--` 和 `/*` 不能在一个操作符名的任何地方出现,因为它们将被作为一段注释的开始。
+- `--`和`/*`不能在一个操作符名的任何地方出现,因为它们将被作为一段注释的开始。
-- 一个多字符操作符名不能以 `+` 或 `-` 结尾,除非该名称也至少包含这些字符中的一个:
+- 一个多字符操作符名不能以`+`或`-`结尾,除非该名称也至少包含这些字符中的一个:
~ ! @ # % ^ & | ` ?
-例如,`@-` 是一个被允许的操作符名,但 `*-` 不是。这些限制允许IvorySQL解析 SQL 兼容的查询而不需要在记号之间有空格。
-
+例如,`@-`是一个被允许的操作符名,但`*-`不是。这些限制允许IvorySQL解析SQL兼容的查询而不需要在记号之间有空格。
-当使用非 SQL 标准的操作符名时,你通常需要用空格分隔相邻的操作符来避免歧义。例如,如果你定义了一个名为 `@` 的前缀操作符,你不能写 `X*@Y`,你必须写 `X* @Y` 来确保IvorySQL把它读作两个操作符名而不是一个。
+当使用非SQL标准的操作符名时,你通常需要用空格分隔相邻的操作符来避免歧义。例如,如果你定义了一个名为`@`的前缀操作符,你不能写`X*@Y`,你必须写`X* @Y`来确保IvorySQL把它读作两个操作符名而不是一个。
==== 特殊字符
@@ -1184,10 +1167,10 @@ typename ( 'string' )
- 跟随在一个美元符号( `$` )后面的数字被用来表示在一个函数定义或一个预备语句中的位置参数。在其他上下文中该美元符号可以作为一个标识符或者一个美元引用字符串常量的一部分。
- 圆括号( `()` )具有它们通常的含义,用来分组表达式并且强制优先。在某些情况中,圆括号被要求作为一个特定 SQL 命令的固定语法的一部分。
-- 方括号( `[]` )被用来选择一个数组中的元素。更多关于数组的信息见 http://www.postgres.cn/docs/14/arrays.html[第 8.15 节]。
+- 方括号( `[]` )被用来选择一个数组中的元素。更多关于数组的信息见 http://www.postgresql.org/docs/17/arrays.html[第 8.15 节]。
- 逗号( `,` )被用在某些语法结构中来分割一个列表的元素。
- 分号( `;` )结束一个 SQL 命令。它不能出现在一个命令中间的任何位置,除了在一个字符串常量中或者一个被引用的标识符中。
-- 冒号( `:` )被用来从数组中选择“切片”(见 http://www.postgres.cn/docs/14/arrays.html[第 8.15 节])。在某些 SQL 的“方言”(例如嵌入式 SQL)中,冒号被用来作为变量名的前缀。
+- 冒号( `:` )被用来从数组中选择“切片”(见 http://www.postgresql.org/docs/17/arrays.html[第 8.15 节])。在某些 SQL 的“方言”(例如嵌入式 SQL)中,冒号被用来作为变量名的前缀。
- 星号( `*` )被用在某些上下文中标记一个表的所有域或者组合值。当它被用作一个聚集函数的参数时,它还有一种特殊的含义,即该聚集不要求任何显式参数。
- 句点( `.` )被用在数字常量中,并且被用来分割模式、表和列名。
@@ -1207,13 +1190,13 @@ typename ( 'string' )
*/
```
-这里该注释开始于 `/*` 并且延伸到匹配出现的 `*/`。这些注释块可按照 SQL 标准中指定的方式嵌套,但和 C 中不同。这样我们可以注释掉一大段可能包含注释块的代码。
+这里该注释开始于 `/*` 并且延伸到匹配出现的 `*/`。这些注释块可按照SQL标准中指定的方式嵌套,但和C中不同。这样我们可以注释掉一大段可能包含注释块的代码。
在进一步的语法分析前,注释会被从输入流中被移除并且实际被替换为空白。
===== 操作符优先级
-http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-PRECEDENCE-TABLE[表 4.2] 显示了IvorySQL中操作符的优先级和结合性。大部分操作符具有相同的优先并且是左结合的。操作符的优先级和结合性被硬写在解析器中。 如果您希望以不同于优先级规则所暗示的方式解析具有多个运算符的表达式,请添加括号。
+http://www.postgresql.org/docs/17/sql-syntax-lexical.html#SQL-PRECEDENCE-TABLE[表 4.2]显示了IvorySQL中操作符的优先级和结合性。大部分操作符具有相同的优先并且是左结合的。操作符的优先级和结合性被硬写在解析器中。如果您希望以不同于优先级规则所暗示的方式解析具有多个运算符的表达式,请添加括号。
**表 4.2. 操作符优先级(从高到低)**
|====
@@ -1242,16 +1225,16 @@ http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-PRECEDENCE-TABLE[表
SELECT 3 OPERATOR(pg_catalog.+) 4;
```
-`OPERATOR`结构被用来为“任意其他操作符”获得 http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-PRECEDENCE-TABLE[表 4.2] 中默认的优先级。不管出现在`OPERATOR()`中的是哪个指定操作符,这都是真的。
+`OPERATOR`结构被用来为“任意其他操作符”获得 http://www.postgresql.org/docs/17/sql-syntax-lexical.html#SQL-PRECEDENCE-TABLE[表 4.2]中默认的优先级。不管出现在`OPERATOR()`中的是哪个指定操作符,这都是真的。
.注意
****
-版本 9.5 之前的IvorySQL使用的操作符优先级 规则略有不同。特别是,`<=`、`>=` 和 `<>` 习惯于被当作普通操作符,`IS` 测试习惯于具有较高的优先级。并且在一些认为 `NOT` 比 `BETWEEN` 优先级高的情况下,`NOT BETWEEN` 和相关的结构的行为不一致。为了更好地兼容 SQL 标准并且减少对 逻辑上等价的结构不一致的处理,这些规则也得到了修改。在大部分情况下, 这些变化不会导致行为上的变化,或者可能会产生“no such operator” 错误,但可以通过增加圆括号解决。不过在一些极端情况中,查询可能在 没有被报告解析错误的情况下发生行为的改变。
+版本9.5之前的PostgreSQL使用的操作符优先级规则略有不同。特别是,`<=`、`>=` 和 `<>`习惯于被当作普通操作符,`IS`测试习惯于具有较高的优先级。并且在一些认为`NOT`比`BETWEEN`优先级高的情况下,`NOT BETWEEN`和相关的结构的行为不一致。为了更好地兼容SQL标准并且减少对 逻辑上等价的结构不一致的处理,这些规则也得到了修改。在大部分情况下,这些变化不会导致行为上的变化,或者可能会产生“no such operator”错误,但可以通过增加圆括号解决。不过在一些极端情况中,查询可能在没有被报告解析错误的情况下发生行为的改变。
****
=== 值表达式
-值表达式被用于各种各样的环境中,例如在 `SELECT` 命令的目标列表中、作为 `INSERT` 或 `UPDATE` 中的新列值或者若干命令中的搜索条件。为了区别于一个表表达式(是一个表)的结果,一个值表达式的结果有时候被称为一个 *标量*。值表达式因此也被称为 *标量表达式*(或者甚至简称为 *表达式*)。表达式语法允许使用算数、逻辑、集合和其他操作从原始部分计算值。
+值表达式被用于各种各样的环境中,例如在`SELECT`命令的目标列表中、作为`INSERT`或`UPDATE`中的新列值或者若干命令中的搜索条件。为了区别于一个表表达式(是一个表)的结果,一个值表达式的结果有时候被称为一个 *标量*。值表达式因此也被称为 *标量表达式*(或者甚至简称为 *表达式*)。表达式语法允许使用算数、逻辑、集合和其他操作从原始部分计算值。
一个值表达式是下列之一:
@@ -1271,9 +1254,9 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
- 一个行构造器
- 另一个在圆括号(用来分组子表达式以及重载优先级)中的值表达式
-在这个列表之外,还有一些结构可以被分类为一个表达式,但是它们不遵循任何一般语法规则。这些通常具有一个函数或操作符的语义并且在 http://www.postgres.cn/docs/14/functions.html[第 9 章] 中的合适位置解释。一个例子是 `IS NULL` 子句。
+在这个列表之外,还有一些结构可以被分类为一个表达式,但是它们不遵循任何一般语法规则。这些通常具有一个函数或操作符的语义并且在 http://www.postgresql.org/docs/17/functions.html[第 9 章]中的合适位置解释。一个例子是`IS NULL`子句。
-我们已经在 http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS[第 4.1.2 节] 中讨论过常量。下面的小节会讨论剩下的选项。
+我们已经在 http://www.postgresql.org/docs/17/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS[第 4.1.2 节]中讨论过常量。下面的小节会讨论剩下的选项。
==== 列引用
@@ -1284,20 +1267,18 @@ correlation.columnname
```
-
-*`correlation`* 是一个表(有可能以一个模式名限定)的名字,或者是在 `FROM` 子句中为一个表定义的别名。如果列名在当前索引所使用的表中都是唯一的,关联名称和分隔用的句点可以被忽略(另见 http://www.postgres.cn/docs/14/queries.html[第 7 章])。
+*`correlation`* 是一个表(有可能以一个模式名限定)的名字,或者是在`FROM`子句中为一个表定义的别名。如果列名在当前索引所使用的表中都是唯一的,关联名称和分隔用的句点可以被忽略(另见 http://www.postgresql.org/docs/17/queries.html[第 7 章])。
==== 位置参数
-一个位置参数引用被用来指示一个由 SQL 语句外部提供的值。参数被用于 SQL 函数定义和预备查询中。某些客户端库还支持独立于 SQL 命令字符串来指定数据值,在这种情况中参数被用来引用那些线外数据值。一个参数引用的形式是:
+一个位置参数引用被用来指示一个由SQL语句外部提供的值。参数被用于SQL函数定义和预备查询中。某些客户端库还支持独立于SQL命令字符串来指定数据值,在这种情况中参数被用来引用那些线外数据值。一个参数引用的形式是:
```
$number
```
-
-例如,考虑一个函数 `dept` 的定义:
+例如,考虑一个函数`dept`的定义:
```
CREATE FUNCTION dept(text) RETURNS dept
@@ -1332,11 +1313,11 @@ $1[10:42]
(arrayfunction(a,b))[42]
```
-最后一个例子中的圆括号是必需的。详见 http://www.postgres.cn/docs/14/arrays.html[第 8.15 节]。
+最后一个例子中的圆括号是必需的。详见 http://www.postgresql.org/docs/17/arrays.html[第 8.15 节]。
==== 域选择
-如果一个表达式得到一个组合类型(行类型)的值,那么可以抽取该行的指定域
+如果一个表达式得到一个组合类型(行类型)的值,那么可以抽取该行的指定域:
```
expression.fieldname
@@ -1367,7 +1348,7 @@ $1.somecolumn
(compositecol).*
```
-这种记法的行为根据上下文会有不同,详见 http://www.postgres.cn/docs/14/rowtypes.html#ROWTYPES-USAGE[第 8.16.5 节]。
+这种记法的行为根据上下文会有不同,详见 http://www.postgresql.org/docs/17/rowtypes.html#ROWTYPES-USAGE[第 8.16.5 节]。
==== 操作符调用
@@ -1377,13 +1358,13 @@ $1.somecolumn
| *`operator`* *`expression`*(一元前缀操作符)
|====
-其中 *`operator`* 记号遵循 http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-SYNTAX-OPERATORS[第 4.1.3 节] 的语法规则,或者是关键词`AND`、`OR`和`NOT`之一,或者是一个如下形式的受限定操作符名:
+其中 *`operator`* 记号遵循 http://www.postgresql.org/docs/17/sql-syntax-lexical.html#SQL-SYNTAX-OPERATORS[第 4.1.3 节] 的语法规则,或者是关键词`AND`、`OR`和`NOT`之一,或者是一个如下形式的受限定操作符名:
```
OPERATOR(schema.operatorname)
```
-哪个特定操作符存在以及它们是一元的还是二元的取决于由系统或用户定义的那些操作符。 http://www.postgres.cn/docs/14/functions.html[第 9 章] 描述了内建操作符。
+哪个特定操作符存在以及它们是一元的还是二元的取决于由系统或用户定义的那些操作符。 http://www.postgresql.org/docs/17/functions.html[第 9 章] 描述了内建操作符。
==== 函数调用
@@ -1394,7 +1375,6 @@ function_name ([expression [, expression ... ]] )
```
-
例如,下面会计算 2 的平方根:
```
@@ -1402,12 +1382,11 @@ sqrt(2)
```
+当在一个某些用户不信任其他用户的数据库中发出查询时,在编写函数调用时应遵守 http://www.postgresql.org/docs/17/typeconv-func.html[第 10.3 节] 中的安全防范措施。
-当在一个某些用户不信任其他用户的数据库中发出查询时,在编写函数调用时应遵守 http://www.postgres.cn/docs/14/typeconv-func.html[第 10.3 节] 中的安全防范措施。
-
-内建函数的列表在 http://www.postgres.cn/docs/14/functions.html[第 9 章] 中。其他函数可以由用户增加。
+内建函数的列表在 http://www.postgresql.org/docs/17/functions.html[第 9 章] 中。其他函数可以由用户增加。
-参数可以有选择地被附加名称。详见 http://www.postgres.cn/docs/14/sql-syntax-calling-funcs.html[第 4.3 节]。
+参数可以有选择地被附加名称。详见 http://www.postgresql.org/docs/17/sql-syntax-calling-funcs.html[第 4.3 节]。
.注意
****
@@ -1435,14 +1414,13 @@ aggregate_name ( [ expression [ , ... ] ] ) WITHIN GROUP ( order_by_clause ) [ F
例如,`count(*)` 得到输入行的总数。 `count(f1)` 得到输入行中 `f1` 为非空的数量,因为 `count` 忽略空值。而 `count(distinct f1)` 得到 `f1` 的非空可区分值的数量。
-一般地,交给聚集函数的输入行是未排序的。在很多情况中这没有关系,例如不管接收到什么样的输入, `min` 总是产生相同的结果。但是,某些聚集函数(例如 `array_agg` 和 `string_agg` )依据输入行的排序产生结果。当使用这类聚集时,可选的 *`order_by_clause`* 可以被用来指定想要的顺序。*`order_by_clause`* 与查询级别的 `ORDER BY` 子句(如 http://www.postgres.cn/docs/14/queries-order.html[第 7.5 节] 所述)具有相同的语法,除非它的表达式总是仅有表达式并且不能是输出列名称或编号。例如:
+一般地,交给聚集函数的输入行是未排序的。在很多情况中这没有关系,例如不管接收到什么样的输入, `min` 总是产生相同的结果。但是,某些聚集函数(例如 `array_agg` 和 `string_agg` )依据输入行的排序产生结果。当使用这类聚集时,可选的 *`order_by_clause`* 可以被用来指定想要的顺序。*`order_by_clause`* 与查询级别的 `ORDER BY` 子句(如 http://www.postgresql.org/docs/17/queries-order.html[第 7.5 节] 所述)具有相同的语法,除非它的表达式总是仅有表达式并且不能是输出列名称或编号。例如:
```
SELECT array_agg(a ORDER BY b DESC) FROM table;
```
-
在处理多参数聚集函数时,注意 `ORDER BY` 出现在所有聚集参数之后。例如,要这样写:
```
@@ -1488,11 +1466,11 @@ FROM generate_series(1,10) AS s(i);
(1 row)
```
-预定义的聚集函数在 http://www.postgres.cn/docs/14/functions-aggregate.html[第 9.21 节] 中描述。其他聚集函数可以由用户增加。
+预定义的聚集函数在 http://www.postgresql.org/docs/17/functions-aggregate.html[第 9.21 节] 中描述。其他聚集函数可以由用户增加。
一个聚集表达式只能出现在 `SELECT` 命令的结果列表或是 `HAVING` 子句中。在其他子句(如 `WHERE` )中禁止使用它,因为那些子句的计算在逻辑上是在聚集的结果被形成之前。
-当一个聚集表达式出现在一个子查询中(见 http://www.postgres.cn/docs/14/sql-expressions.html#SQL-SYNTAX-SCALAR-SUBQUERIES[第 4.2.11 节] 和 http://www.postgres.cn/docs/14/functions-subquery.html[第 9.23 节]),聚集通常在该子查询的行上被计算。但是如果该聚集的参数(以及 *`filter_clause`*,如果有)只包含外层变量则会产生一个异常:该聚集则属于最近的那个外层,并且会在那个查询的行上被计算。该聚集表达式从整体上则是对其所出现于的子查询的一种外层引用,并且在那个子查询的任意一次计算中都作为一个常量。只出现在结果列表或 `HAVING` 子句的限制适用于该聚集所属的查询层次。
+当一个聚集表达式出现在一个子查询中(见 http://www.postgresql.org/docs/17/sql-expressions.html#SQL-SYNTAX-SCALAR-SUBQUERIES[第 4.2.11 节] 和 http://www.postgresql.org/docs/17/functions-subquery.html[第 9.23 节]),聚集通常在该子查询的行上被计算。但是如果该聚集的参数(以及 *`filter_clause`*,如果有)只包含外层变量则会产生一个异常:该聚集则属于最近的那个外层,并且会在那个查询的行上被计算。该聚集表达式从整体上则是对其所出现于的子查询的一种外层引用,并且在那个子查询的任意一次计算中都作为一个常量。只出现在结果列表或 `HAVING` 子句的限制适用于该聚集所属的查询层次。
==== 窗口函数调用
@@ -1544,7 +1522,7 @@ EXCLUDE NO OTHERS
这里,*`expression`* 表示任何自身不含有窗口函数调用的值表达式。
-*`window_name`* 是对定义在查询的 `WINDOW` 子句中的一个命名窗口声明的引用。还可以使用在 `WINDOW` 子句中定义命名窗口的相同语法在圆括号内给定一个完整的 *`window_definition`*,详见 http://www.postgres.cn/docs/14/sql-select.html[SELECT] 参考页。值得指出的是,`OVER wname` 并不严格地等价于 `OVER (wname ...)`,后者表示复制并修改窗口定义,并且在被引用窗口声明包括一个帧子句时会被拒绝。
+*`window_name`* 是对定义在查询的 `WINDOW` 子句中的一个命名窗口声明的引用。还可以使用在 `WINDOW` 子句中定义命名窗口的相同语法在圆括号内给定一个完整的 *`window_definition`*,详见 http://www.postgresql.org/docs/17/sql-select.html[SELECT] 参考页。值得指出的是,`OVER wname` 并不严格地等价于 `OVER (wname ...)`,后者表示复制并修改窗口定义,并且在被引用窗口声明包括一个帧子句时会被拒绝。
`PARTITION BY` 选项将查询的行分组成为 *分区*,窗口函数会独立地处理它们。`PARTITION BY` 工作起来类似于一个查询级别的 `GROUP BY` 子句,不过它的表达式总是只是表达式并且不能是输出列的名称或编号。如果没有 `PARTITION BY`,该查询产生的所有行被当作一个单一分区来处理。`ORDER BY` 选项决定被窗口函数处理的一个分区中的行的顺序。它工作起来类似于一个查询级别的 `ORDER BY` 子句,但是同样不能使用输出列的名称或编号。如果没有 `ORDER BY`,行将被以未指定的顺序被处理。
@@ -1572,13 +1550,13 @@ EXCLUDE NO OTHERS
如果指定了 `FILTER` ,那么只有对 *`filter_clause`* 计算为真的输入行会被交给该窗口函数,其他行会被丢弃。只有是聚集的窗口函数才接受 `FILTER` 。
-内建的窗口函数在 http://www.postgres.cn/docs/14/functions-window.html#FUNCTIONS-WINDOW-TABLE[表 9.60] 中介绍。用户可以加入其他窗口函数。此外,任何内建的或者用户定义的通用聚集或者统计性聚集都可以被用作窗口函数(有序集和假想集聚集当前不能被用作窗口函数)。
+内建的窗口函数在 http://www.postgresql.org/docs/17/functions-window.html#FUNCTIONS-WINDOW-TABLE[表 9.60] 中介绍。用户可以加入其他窗口函数。此外,任何内建的或者用户定义的通用聚集或者统计性聚集都可以被用作窗口函数(有序集和假想集聚集当前不能被用作窗口函数)。
使用 `\*` 的语法被用来把参数较少的聚集函数当作窗口函数调用,例如 `count(*) OVER (PARTITION BY x ORDER BY y)`。星号(`*`)通常不被用于窗口相关的函数。窗口相关的函数不允许在函数参数列表中用 `DISTINCT` 或 `ORDER BY`。
只有在 `SELECT` 列表和查询的 `ORDER BY` 子句中才允许窗口函数调用。
-更多关于窗口函数的信息可以在 http://www.postgres.cn/docs/14/tutorial-window.html[第 3.5 节]、 http://www.postgres.cn/docs/14/functions-window.html[第 9.22 节] 以及 http://www.postgres.cn/docs/14/queries-table-expressions.html#QUERIES-WINDOW[第 7.2.5 节] 中找到。
+更多关于窗口函数的信息可以在 http://www.postgresql.org/docs/17/tutorial-window.html[第 3.5 节]、 http://www.postgresql.org/docs/17/functions-window.html[第 9.22 节] 以及 http://www.postgresql.org/docs/17/queries-table-expressions.html#QUERIES-WINDOW[第 7.2.5 节] 中找到。
==== 类型转换
@@ -1591,7 +1569,7 @@ expression::type
`CAST` 语法遵从 SQL,而用 `::` 的语法是IvorySQL的历史用法。
-当一个造型被应用到一种未知类型的值表达式上时,它表示一种运行时类型转换。只有已经定义了一种合适的类型转换操作时,该造型才会成功。注意这和常量的造型(如 http://www.postgres.cn/docs/14/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS-GENERIC[第 4.1.2.7 节] 中所示)使用不同。应用于一个未修饰串文字的造型表示一种类型到一个文字常量值的初始赋值,并且因此它将对任意类型都成功(如果该串文字的内容对于该数据类型的输入语法是可接受的)。
+当一个造型被应用到一种未知类型的值表达式上时,它表示一种运行时类型转换。只有已经定义了一种合适的类型转换操作时,该造型才会成功。注意这和常量的造型(如 http://www.postgresql.org/docs/17/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS-GENERIC[第 4.1.2.7 节] 中所示)使用不同。应用于一个未修饰串文字的造型表示一种类型到一个文字常量值的初始赋值,并且因此它将对任意类型都成功(如果该串文字的内容对于该数据类型的输入语法是可接受的)。
如果一个值表达式必须产生的类型没有歧义(例如当它被指派给一个表列),通常可以省略显式类型造型,在这种情况下系统会自动应用一个类型造型。但是,只有对在系统目录中被标记为“OK to apply implicitly”的造型才会执行自动造型。其他造型必须使用显式造型语法调用。这种限制是为了防止出人意料的转换被无声无息地应用。
@@ -1605,7 +1583,7 @@ typename ( expression )
.注意
****
-函数风格的语法事实上只是一次函数调用。当两种标准造型语法之一被用来做一次运行时转换时,它将在内部调用一个已注册的函数来执行该转换。简而言之,这些转换函数具有和它们的输出类型相同的名字,并且因此“函数风格的语法”无非是对底层转换函数的一次直接调用。显然,一个可移植的应用不应当依赖于它。详见 http://www.postgres.cn/docs/14/sql-createcast.html[CREATE CAST]。
+函数风格的语法事实上只是一次函数调用。当两种标准造型语法之一被用来做一次运行时转换时,它将在内部调用一个已注册的函数来执行该转换。简而言之,这些转换函数具有和它们的输出类型相同的名字,并且因此“函数风格的语法”无非是对底层转换函数的一次直接调用。显然,一个可移植的应用不应当依赖于它。详见 http://www.postgresql.org/docs/17/sql-createcast.html[CREATE CAST]。
****
==== 排序规则表达式
@@ -1632,7 +1610,7 @@ SELECT a, b, c FROM tbl WHERE ... ORDER BY a COLLATE "C";
SELECT * FROM tbl WHERE a > 'foo' COLLATE "C";
```
-注意在后一种情况中,`COLLATE` 子句被附加到我们希望影响的操作符的一个输入参数上。`COLLATE` 子句被附加到该操作符或函数调用的哪个参数上无关紧要,因为被操作符或函数应用的排序规则是考虑所有参数得来的,并且一个显式的 `COLLATE` 子句将重载所有其他参数的排序规则(不过,附加非匹配 `COLLATE` 子句到多于一个参数是一种错误。详见 http://www.postgres.cn/docs/14/collation.html[第 24.2 节])。因此,这会给出和前一个例子相同的结果:
+注意在后一种情况中,`COLLATE` 子句被附加到我们希望影响的操作符的一个输入参数上。`COLLATE` 子句被附加到该操作符或函数调用的哪个参数上无关紧要,因为被操作符或函数应用的排序规则是考虑所有参数得来的,并且一个显式的 `COLLATE` 子句将重载所有其他参数的排序规则(不过,附加非匹配 `COLLATE` 子句到多于一个参数是一种错误。详见 http://www.postgresql.org/docs/17/collation.html[第 24.2 节])。因此,这会给出和前一个例子相同的结果:
```
SELECT * FROM tbl WHERE a COLLATE "C" > 'foo';
@@ -1648,7 +1626,7 @@ SELECT * FROM tbl WHERE (a > 'foo') COLLATE "C";
==== 标量子查询
-一个标量子查询是一种圆括号内的普通 `SELECT` 查询,它刚好返回一行一列(关于书写查询可见 http://www.postgres.cn/docs/14/queries.html[第 7 章])。`SELECT`查询被执行并且该单一返回值被使用在周围的值表达式中。将一个返回超过一行或一列的查询作为一个标量子查询使用是一种错误(但是如果在一次特定执行期间该子查询没有返回行则不是错误,该标量结果被当做为空)。该子查询可以从周围的查询中引用变量,这些变量在该子查询的任何一次计算中都将作为常量。对于其他涉及子查询的表达式还可见 http://www.postgres.cn/docs/14/functions-subquery.html[第 9.23 节]。
+一个标量子查询是一种圆括号内的普通 `SELECT` 查询,它刚好返回一行一列(关于书写查询可见 http://www.postgresql.org/docs/17/queries.html[第 7 章])。`SELECT`查询被执行并且该单一返回值被使用在周围的值表达式中。将一个返回超过一行或一列的查询作为一个标量子查询使用是一种错误(但是如果在一次特定执行期间该子查询没有返回行则不是错误,该标量结果被当做为空)。该子查询可以从周围的查询中引用变量,这些变量在该子查询的任何一次计算中都将作为常量。对于其他涉及子查询的表达式还可见 http://www.postgresql.org/docs/17/functions-subquery.html[第 9.23 节]。
例如,下列语句会寻找每个州中最大的城市人口:
@@ -1669,7 +1647,7 @@ SELECT ARRAY[1,2,3+4];
(1 row)
```
-默认情况下,数组元素类型是成员表达式的公共类型,使用和 `UNION` 或 `CASE` 结构(见 http://www.postgres.cn/docs/14/typeconv-union-case.html[第 10.5 节])相同的规则决定。你可以通过显式将数组构造器造型为想要的类型来重载,例如:
+默认情况下,数组元素类型是成员表达式的公共类型,使用和 `UNION` 或 `CASE` 结构(见 http://www.postgresql.org/docs/17/typeconv-union-case.html[第 10.5 节])相同的规则决定。你可以通过显式将数组构造器造型为想要的类型来重载,例如:
```
SELECT ARRAY[1,2,22.7]::integer[];
@@ -1679,7 +1657,7 @@ SELECT ARRAY[1,2,22.7]::integer[];
(1 row)
```
-这和把每一个表达式单独地造型为数组元素类型的效果相同。关于造型的更多信息请见 http://www.postgres.cn/docs/14/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS[第 4.2.9 节]。
+这和把每一个表达式单独地造型为数组元素类型的效果相同。关于造型的更多信息请见 http://www.postgresql.org/docs/17/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS[第 4.2.9 节]。
多维数组值可以通过嵌套数组构造器来构建。在内层的构造器中,关键词 `ARRAY` 可以被忽略。例如,这些语句产生相同的结果:
@@ -1745,7 +1723,7 @@ SELECT ARRAY(SELECT ARRAY[i, i*2] FROM generate_series(1,5) AS a(i));
子查询必须返回一个单一列。如果子查询的输出列是非数组类型, 结果的一维数组将为该子查询结果中的每一行有一个元素, 并且有一个与子查询的输出列匹配的元素类型。如果子查询的输出列 是一种数组类型,结果将是同类型的一个数组,但是要高一个维度。 在这种情况下,该子查询的所有行必须产生同样维度的数组,否则结果 就不会是矩形形式。
-用 `ARRAY` 构建的一个数组值的下标总是从一开始。更多关于数组的信息,请见 http://www.postgres.cn/docs/14/arrays.html[第 8.15 节]。
+用 `ARRAY` 构建的一个数组值的下标总是从一开始。更多关于数组的信息,请见 http://www.postgresql.org/docs/17/arrays.html[第 8.15 节]。
==== 行构造器
@@ -1757,7 +1735,7 @@ SELECT ROW(1,2.5,'this is a test');
当在列表中有超过一个表达式时,关键词 `ROW` 是可选的。
-一个行构造器可以包括语法 *`rowvalue`* `.\*`,它将被扩展为该行值的元素的一个列表,就像在一个顶层 `SELECT` 列表(见 http://www.postgres.cn/docs/14/rowtypes.html#ROWTYPES-USAGE[第 8.16.5 节])中使用 `.*` 时发生的事情一样。例如,如果表 `t` 有列 `f1` 和 `f2`,那么这些是相同的:
+一个行构造器可以包括语法 *`rowvalue`* `.\*`,它将被扩展为该行值的元素的一个列表,就像在一个顶层 `SELECT` 列表(见 http://www.postgresql.org/docs/17/rowtypes.html#ROWTYPES-USAGE[第 8.16.5 节])中使用 `.*` 时发生的事情一样。例如,如果表 `t` 有列 `f1` 和 `f2`,那么这些是相同的:
```
SELECT ROW(t.*, 42) FROM t;
@@ -1766,7 +1744,7 @@ SELECT ROW(t.f1, t.f2, 42) FROM t;
.注意
****
-在IvorySQL 8.2 以前,`.\*` 语法不会在行构造器中被扩展,这样写 `ROW(t.*, 42)` 会创建一个有两个域的行,其第一个域是另一个行值。新的行为通常更有用。如果你需要嵌套行值的旧行为,写内层行值时不要用 `.*`,例如 `ROW(t, 42)`。
+在PostgreSQL 8.2 以前,`.\*` 语法不会在行构造器中被扩展,这样写 `ROW(t.*, 42)` 会创建一个有两个域的行,其第一个域是另一个行值。新的行为通常更有用。如果你需要嵌套行值的旧行为,写内层行值时不要用 `.*`,例如 `ROW(t, 42)`。
****
默认情况下,由一个 `ROW` 表达式创建的值是一种匿名记录类型。如果必要,它可以被造型为一种命名的组合类型 — 或者是一个表的行类型,或者是一种用 `CREATE TYPE AS` 创建的组合类型。为了避免歧义,可能需要一个显式造型。例如:
@@ -1814,7 +1792,7 @@ SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same');
SELECT ROW(table.*) IS NULL FROM table; -- detect all-null rows
```
-详见 http://www.postgres.cn/docs/14/functions-comparisons.html[第 9.24 节]。如 http://www.postgres.cn/docs/14/functions-subquery.html[第 9.23 节] 中所讨论的,行构造器也可以被用来与子查询相连接。
+详见 http://www.postgresql.org/docs/17/functions-comparisons.html[第 9.24 节]。如 http://www.postgresql.org/docs/17/functions-subquery.html[第 9.23 节] 中所讨论的,行构造器也可以被用来与子查询相连接。
==== 表达式计算规则
@@ -1836,7 +1814,7 @@ SELECT somefunc() OR true;
因此,在复杂表达式中使用带有副作用的函数是不明智的。在 `WHERE` 和 `HAVING` 子句中依赖副作用或计算顺序尤其危险,因为在建立一个执行计划时这些子句会被广泛地重新处理。这些子句中布尔表达式( `AND` / `OR` / `NOT` 的组合)可能会以布尔代数定律所允许的任何方式被重组。
-当有必要强制计算顺序时,可以使用一个 `CASE` 结构(见 http://www.postgres.cn/docs/14/functions-conditional.html[第 9.18 节])。例如,在一个 `WHERE` 子句中使用下面的方法尝试避免除零是不可靠的:
+当有必要强制计算顺序时,可以使用一个 `CASE` 结构(见 http://www.postgresql.org/docs/17/functions-conditional.html[第 9.18 节])。例如,在一个 `WHERE` 子句中使用下面的方法尝试避免除零是不可靠的:
```
SELECT ... WHERE x > 0 AND y/x > 1.5;
@@ -1850,7 +1828,7 @@ SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;
一个以这种风格使用的 `CASE` 结构将使得优化尝试失败,因此只有必要时才这样做(在这个特别的例子中,最好通过写 `y > 1.5*x` 来回避这个问题)。
-不过,`CASE` 不是这类问题的万灵药。上述技术的一个限制是, 它无法阻止常量子表达式的提早计算。如 http://www.postgres.cn/docs/14/xfunc-volatility.html[第 38.7 节] 中所述,当查询被规划而不是被执行时,被标记成 `IMMUTABLE` 的函数和操作符可以被计算。因此
+不过,`CASE` 不是这类问题的万灵药。上述技术的一个限制是, 它无法阻止常量子表达式的提早计算。如 http://www.postgresql.org/docs/17/xfunc-volatility.html[第 38.7 节] 中所述,当查询被规划而不是被执行时,被标记成 `IMMUTABLE` 的函数和操作符可以被计算。因此
```
SELECT CASE WHEN x > 0 THEN x ELSE 1/0 END FROM tab;
@@ -1873,7 +1851,7 @@ SELECT CASE WHEN min(employees) > 0
=== 调用函数
-IvorySQL允许带有命名参数的函数被使用 *位置* 或 *命名* 记号法调用。命名记号法对于有大量参数的函数特别有用,因为它让参数和实际参数之间的关联更明显和可靠。在位置记号法中,书写一个函数调用时,其参数值要按照它们在函数声明中被定义的顺序书写。在命名记号法中,参数根据名称匹配函数参数,并且可以以任何顺序书写。对于每一种记法,还要考虑函数参数类型的效果,这些在 http://www.postgres.cn/docs/14/typeconv-func.html[第 10.3 节] 有介绍。
+IvorySQL允许带有命名参数的函数被使用 *位置* 或 *命名* 记号法调用。命名记号法对于有大量参数的函数特别有用,因为它让参数和实际参数之间的关联更明显和可靠。在位置记号法中,书写一个函数调用时,其参数值要按照它们在函数声明中被定义的顺序书写。在命名记号法中,参数根据名称匹配函数参数,并且可以以任何顺序书写。对于每一种记法,还要考虑函数参数类型的效果,这些在 http://www.postgresql.org/docs/17/typeconv-func.html[第 10.3 节] 有介绍。
在任意一种记号法中,在函数声明中给出了默认值的参数根本不需要在调用中写出。但是这在命名记号法中特别有用,因为任何参数的组合都可以被忽略。而在位置记号法中参数只能从右往左忽略。
@@ -1894,7 +1872,7 @@ $$
LANGUAGE SQL IMMUTABLE STRICT;
```
-函数 `concat_lower_or_upper` 有两个强制参数,`a` 和 `b`。此外,有一个可选的参数 `uppercase`,其默认值为 `false`。`a` 和 `b` 输入将被串接,并且根据 `uppercase` 参数被强制为大写或小写形式。这个函数的剩余细节对这里并不重要(详见 http://www.postgres.cn/docs/14/extend.html[第 38 章])。
+函数 `concat_lower_or_upper` 有两个强制参数,`a` 和 `b`。此外,有一个可选的参数 `uppercase`,其默认值为 `false`。`a` 和 `b` 输入将被串接,并且根据 `uppercase` 参数被强制为大写或小写形式。这个函数的剩余细节对这里并不重要(详见 http://www.postgresql.org/docs/17/extend.html[第 38 章])。
==== 使用位置记号
@@ -1985,9 +1963,9 @@ SELECT concat_lower_or_upper('Hello', 'World', uppercase => true);
参数设置采用与原生 PostgreSQL 相同的方法。 所有参数名称都不区分大小写。每个参数都采用以下五种类型之一的值:布尔值、字符串、整数、浮点数或枚举 (enum)。
-==== `compatible_mode (enum)`
+==== `ivorysql.compatible_mode (enum)`
-此参数控制数据库服务器的行为。 默认值为 `postgres`,表示它是原生安装,服务器将作为原生 PG 安装。 如果它设置为“oracle”,那么查询的输出和系统行为整体会发生变化,因为它会更像 Oracle。
+此参数控制数据库服务器的行为。 如果它设置为`pg`,表示它是原生安装,服务器将作为原生 PG 安装。 如果它设置为“oracle”,那么查询的输出和系统行为整体会发生变化,因为它会更像 Oracle。
当设置为 `oracle` 时,此参数会隐式地将同样名字的Schema添加到 `search_path`。 以便可以定位 Oracle 兼容对象。
@@ -2001,405 +1979,6 @@ SELECT concat_lower_or_upper('Hello', 'World', uppercase => true);
- https://www.ivorysql.org/zh-CN/docs/tags/compatibility-parameters[Compatibility Parameters]
-=== 包
-
-本节将介绍PostgreSQL的“Oracle风格包”。根据定义,包是一个对象或一组对象打包在一起。就数据库而言,这将转换为一个命名的模式对象,该对象将过程、函数、变量、游标、用户定义的记录类型和引用记录的逻辑分组集合打包在自己内部。希望用户熟悉PostgreSQL,并且对SQL语言有很好的理解,以便更好地理解这些包并更有效地使用它们。
-
-==== 对软件包的需求
-
-与其他各种编程语言中的类似构造一样,将包与SQL一起使用有很多好处。在本节中,我们将要讲几个。
-
-1.代码包的可靠性和可复用性::
-
- Packages使您能够创建封装代码的模块化对象。这使得总体设计和实现更加简单。通过封装变量和相关类型、存储过程/函数以及游标,它允许您创建一个简单、易于理解、易于维护和使用的独立的模块。封装通过公开包接口而不是包体的实现细节发挥作用。因此,这在许多方面都有好处。它允许应用程序和用户引用一致的界面,而不必担心其主体的内容。此外,它还防止用户根据代码实现做出任何决策,因为代码实现从来没有向他们公开过。
-
-2.易用性::
-
- 在PostgreSQL中创建一致的功能接口的能力有助于简化应用程序开发,因为它允许在没有主体的情况下编译包。在开发阶段之后,包允许用户管理整个包的访问控制,而不是单个对象。这非常有价值,尤其是当包包含许多模式对象时。
-
-3.性能::
-
- 包是加载到内存中进行维护,因此使用的I/O资源最少。重新编译很简单,仅限于更改的对象;不重新编译从属对象。
-
-4.附加功能::
-
- 除了性能和易用性之外,软件包还为变量和游标提供了会话范围的持久性。这意味着变量和游标与数据库会话具有相同的生存期,并在会话被销毁时被销毁。
-
-==== 包组件
-
-包有一个接口和一个主体,这是组成包的主要组件。
-
-1.包规格
-
-包规格指定了包内从外部使用的任何对象。这指的是可公开访问的接口。它不包含它们的定义或实现,即功能和程序。它只定义了标题,而没有正文定义。可以初始化变量。以下是可在规范中列出的对象列表:
-
- - Functions
- - Procedures
- - Cursors
- - Types
- - Variables
- - Constants
- - Record types
-
-2.包体
-
-包体包含包的所有实现代码,包括公共接口和私有对象。如果规范不包含任何子程序或游标,则包体是可选的。
-
-它必须包含规范中声明的子程序的定义,并且相应的定义必须匹配。
-
-包体可以包含其自己的子程序和规范中未指定的任何内部对象的类型声明。这些对象被认为是私有的。无法在包外部访问私有对象。
-
-除了子程序定义外,它还可以选择性地包含一个初始化程序块,用于初始化规范中声明的变量,并且在会话中首次调用包时仅执行一次。
-
-.**注意**
-****
-如果规范更改,则包体将失效。在标识公共接口和私有接口时,必须小心,以避免将关键函数和变量暴露在包之外。
-****
-
-==== 包语法
-
-===== 包规范语法
-
-```SQL
-CREATE [ OR REPLACE ] PACKAGE [schema.] *package_name* [invoker_rights_clause] [IS | AS]
- item_list[, item_list ...]
-END [*package_name*];
-
-
-invoker_rights_clause:
- AUTHID [CURRENT_USER | DEFINER]
-
-item_list:
-[
- function_declaration |
- procedure_declaration |
- type_definition |
- cursor_declaration |
- item_declaration
-]
-
-
-function_declaration:
- FUNCTION function_name [(parameter_declaration[, ...])] RETURN datatype;
-
-procedure_declaration:
- PROCEDURE procedure_name [(parameter_declaration[, ...])]
-
-type_definition:
- record_type_definition |
- ref_cursor_type_definition
-
-cursor_declaration:
- CURSOR name [(cur_param_decl[, ...])] RETURN rowtype;
-
-item_declaration:
- cursor_declaration |
- cursor_variable_declaration |
- record_variable_declaration |
- variable_declaration |
-
-record_type_definition:
- TYPE record_type IS RECORD ( variable_declaration [, variable_declaration]... ) ;
-
-ref_cursor_type_definition:
- TYPE type IS REF CURSOR [ RETURN type%ROWTYPE ];
-
-cursor_variable_declaration:
- curvar curtype;
-
-record_variable_declaration:
- recvar { record_type | rowtype_attribute | record_type%TYPE };
-
-variable_declaration:
- varname datatype [ [ NOT NULL ] := expr ]
-
-parameter_declaration:
- parameter_name [IN] datatype [[:= | DEFAULT] expr]
-```
-
-===== 包体语法
-
-```SQL
-CREATE [ OR REPLACE ] PACKAGE BODY [schema.] package_name [IS | AS]
- [item_list[, item_list ...]] |
- item_list_2 [, item_list_2 ...]
- [initialize_section]
-END [package_name];
-
-
-initialize_section:
- BEGIN statement[, ...]
-
-item_list:
-[
- function_declaration |
- procedure_declaration |
- type_definition |
- cursor_declaration |
- item_declaration
-]
-
-item_list_2:
-[
- function_declaration
- function_definition
- procedure_declaration
- procedure_definition
- cursor_definition
-]
-
-function_definition:
- FUNCTION function_name [(parameter_declaration[, ...])] RETURN datatype [IS | AS]
- [declare_section] body;
-
-procedure_definition:
- PROCEDURE procedure_name [(parameter_declaration[, ...])] [IS | AS]
- [declare_section] body;
-
-cursor_definition:
- CURSOR name [(cur_param_decl[, ...])] RETURN rowtype IS select_statement;
-
-body:
- BEGIN statement[, ...] END [name];
-
-statement:
- [<