PostgreSQL + hasura + Apollo + GraphQL + React + Antd
技术栈
PostgreSQL + hasura + Apollo + GraphQL + React + Antd
适用于复杂的查询,快速开发
环境安装
安装PostgreSQL + hasura,使用docker安装
使用 Docker Compose 部署时,它会同时启动两个容器PostgreSQL和 Hasura GraphQL ,如下
version: "3.6"
services:postgres:image: postgres:latestcontainer_name: postgresrestart: alwaysvolumes:- ~/data/postgres:/var/lib/postgresql/dataports:- "5432:5432"environment:POSTGRES_PASSWORD: postgrespasswordgraphql-engine:image: hasura/graphql-engine:latestcontainer_name: hasuraports:- "23333:8080"depends_on:- "postgres"restart: alwaysenvironment:HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgresHASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable consoleHASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log## uncomment next line to set an admin secret# HASURA_GRAPHQL_ADMIN_SECRET: myadminsecretkey
创建一个新文件夹,创建文件docker-compose.yaml复制上面内容,然后运行下面指令以安装
docker-compose up -d
安装完成后使用下面指令查看正在运行的docker
docker ps -a
在浏览器中输入localhost:23333/console
可以进入Hasura的控制界面,根据上面的配置,会自动连接上数据库
PostgreSQL
数据层次
- Cluster (集群)
- 集群是 PostgreSQL 实例的最高级别概念。一个集群包含多个数据库,并且所有这些数据库共享同一组配置文件、后台进程和存储区域。集群由一个特定版本的 PostgreSQL 服务器管理。
- Database (数据库)
- 每个集群可以包含多个独立的数据库。每个数据库都是一个逻辑单元,拥有自己的模式(schema)、表、索引等对象。用户连接到特定的数据库进行操作,不同数据库中的对象默认情况下是隔离的。
- Schema (模式)
- 模式是数据库内的命名空间,用于组织数据库对象如表、视图、函数等。每个数据库至少有一个名为
public
的默认模式,但你可以创建额外的模式来更好地组织你的数据和代码。模式有助于避免名称冲突,并允许你对数据库对象进行逻辑分组。
- 模式是数据库内的命名空间,用于组织数据库对象如表、视图、函数等。每个数据库至少有一个名为
- Table (表)
- 表是存储实际数据的地方。每个表都有一个唯一的名称(在同一模式内),并且由一组列定义,每列有其类型和约束。表可以包含零条或多条记录(行)。
创建实例数据库
CREATE SCHEMA test;
CREATE TABLE test.users (id SERIAL PRIMARY KEY,name VARCHAR(100) NOT NULL,email VARCHAR(150) UNIQUE NOT NULL
);
CREATE TABLE test.orders (id SERIAL PRIMARY KEY,user_id INT REFERENCES test.users(id) ON DELETE CASCADE,product VARCHAR(100) NOT NULL,quantity INT NOT NULL,order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);-- 插入用户
INSERT INTO test.users (name, email)
VALUES ('Alice', 'alice@example.com'),('Bob', 'bob@example.com');-- 插入订单
INSERT INTO test.orders (user_id, product, quantity)
VALUES (1, 'Laptop', 1),(1, 'Mouse', 2),(2, 'Keyboard', 1);
hasura
然后hasura会对schema的每个表建立以下的查询方法
分别是批量查询,聚合查询以及单体查询
test_users
test_users_aggragate
test_users_by_pk
然后我们可以通过点击需要的数据,生成对应的graphQL查询语句,如下,然后在前端使用
query MyQuery {test_users {emailnameid}
}
react
创建项目
创建新项目
npx create-react-app user-orders-app
cd user-orders-app
启动项目
npm start
appollo
安装依赖
npm install @apollo/client graphql
配置Hasura GraphQL服务器
// src/apollo-client.js
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client';const client = new ApolloClient({link: new HttpLink({uri: 'http://localhost:23333/v1/graphql', // 你的 Hasura GraphQL 端点}),cache: new InMemoryCache(),
});export default client;
GraphiQL
编写graphql以直接操作数据库
// src/graphql.js
import { gql } from '@apollo/client';// 获取所有用户
export const GET_USERS = gql`query GetUsers {test_users {idnameemail}}
`;// 获取指定用户的订单
export const GET_USER_ORDERS = gql`query GetUserOrders($userId: Int!) {test_orders(where: { user_id: { _eq: $userId } }) {idproductquantityorder_date}}
`;// 创建用户
export const CREATE_USER = gql`mutation CreateUser($name: String!, $email: String!) {insert_test_users(objects: { name: $name, email: $email }) {returning {idnameemail}}}
`;// 删除用户
export const DELETE_USER = gql`mutation DeleteUser($id: Int!) {delete_test_users(where: { id: { _eq: $id } }) {returning {id}}}
`;// 更新用户
export const UPDATE_USER = gql`mutation UpdateUser($id: Int!, $name: String, $email: String) {update_test_users(where: { id: { _eq: $id } }, _set: { name: $name, email: $email }) {returning {idnameemail}}}
`;
react
编写react前端页面
// src/UserOrders.js
import React, { useState } from 'react';
import { useQuery, useMutation } from '@apollo/client';
import { GET_USERS, GET_USER_ORDERS, CREATE_USER, DELETE_USER, UPDATE_USER } from './graphql';const UserOrders = () => {const [newName, setNewName] = useState('');const [newEmail, setNewEmail] = useState('');const [updateName, setUpdateName] = useState('');const [updateEmail, setUpdateEmail] = useState('');const [selectedUserId, setSelectedUserId] = useState(null);// 获取用户列表const { loading, error, data } = useQuery(GET_USERS);// 获取指定用户的订单const { loading: ordersLoading, data: ordersData } = useQuery(GET_USER_ORDERS, {skip: !selectedUserId,variables: { userId: selectedUserId },});// 调试信息:查看获取的数据console.log('User Data:', data);console.log('Orders Data:', ordersData);// 创建用户const [createUser] = useMutation(CREATE_USER, {refetchQueries: [{ query: GET_USERS }],});// 删除用户const [deleteUser] = useMutation(DELETE_USER, {refetchQueries: [{ query: GET_USERS }],});// 更新用户const [updateUser] = useMutation(UPDATE_USER, {refetchQueries: [{ query: GET_USERS }],});const handleCreateUser = () => {createUser({ variables: { name: newName, email: newEmail } });setNewName('');setNewEmail('');};const handleDeleteUser = (id) => {deleteUser({ variables: { id } });};const handleUpdateUser = (id) => {updateUser({variables: { id, name: updateName, email: updateEmail },});setUpdateName('');setUpdateEmail('');};return (<div><h2>Create User</h2><inputtype="text"value={newName}onChange={(e) => setNewName(e.target.value)}placeholder="Name"/><inputtype="email"value={newEmail}onChange={(e) => setNewEmail(e.target.value)}placeholder="Email"/><button onClick={handleCreateUser}>Create</button><h2>Users</h2>{loading && <p>Loading users...</p>}{error && <p>Error: {error.message}</p>}{data && (<ul>{data.test_users.map((user) => (<li key={user.id}>{user.name} ({user.email})<button onClick={() => setSelectedUserId(user.id)}>View Orders</button><button onClick={() => handleDeleteUser(user.id)}>Delete</button><buttononClick={() => {setUpdateName(user.name);setUpdateEmail(user.email);handleUpdateUser(user.id);}}>Update</button></li>))}</ul>)}{selectedUserId && ordersData && (<div><h3>Orders for {data.test_users.find((user) => user.id === selectedUserId).name}</h3>{ordersLoading ? (<p>Loading orders...</p>) : (<ul>{ordersData.test_orders && ordersData.test_orders.length > 0 ? (ordersData.test_orders.map((order) => (<li key={order.id}>{order.product} - {order.quantity} (Ordered on {new Date(order.order_date).toLocaleString()})</li>))) : (<p>No orders found for this user.</p>)}</ul>)}</div>)}</div>);
};export default UserOrders;
然后再App.js中使用
// src/App.js
import React from 'react';
import { ApolloProvider } from '@apollo/client';
import client from './apollo-client';
import UserOrders from './UserOrders';function App() {return (<ApolloProvider client={client}><div className="App"><h1>Users and Orders</h1><UserOrders /></div></ApolloProvider>);
}export default App;
antd
ant design 蚂蚁组件库,爱来自阿里,组件库,用于美化前端页面
安装
npm install antd@^4.24.2
npm install @ant-design/icons
先在index.js中引入
import 'antd/dist/antd.css';
然后对react页面应用样式
// src/UserList.js
import React, { useEffect, useState } from 'react';
import { Table, Button, Space, Modal, Form, Input, message } from 'antd';
import { useQuery, useMutation } from '@apollo/client';
import { GET_USERS, DELETE_USER, CREATE_USER, UPDATE_USER, GET_USER_ORDERS } from './graphql';// 用户列表组件
const UserList = () => {const { loading, error, data, refetch } = useQuery(GET_USERS);const [deleteUser] = useMutation(DELETE_USER);const [createUser] = useMutation(CREATE_USER);const [updateUser] = useMutation(UPDATE_USER);const [isModalVisible, setIsModalVisible] = useState(false);const [isOrdersModalVisible, setIsOrdersModalVisible] = useState(false);const [form] = Form.useForm();const [editingUser, setEditingUser] = useState(null);const [selectedUser, setSelectedUser] = useState(null);const [orders, setOrders] = useState([]);const { data: ordersData, loading: ordersLoading, error: ordersError } = useQuery(GET_USER_ORDERS, {variables: { userId: selectedUser?.id },skip: !selectedUser, // 如果没有选择用户,则跳过该查询onCompleted: (data) => setOrders(data?.test_orders || []),});// 显示删除用户的确认对话框const handleDelete = async (userId) => {try {await deleteUser({ variables: { id: userId } });message.success('User deleted successfully');refetch(); // 刷新列表} catch (err) {message.error('Failed to delete user');}};// 显示/隐藏模态框const showModal = (user) => {setEditingUser(user);form.setFieldsValue(user || { name: '', email: '' });setIsModalVisible(true);};const handleOk = async () => {try {const values = await form.validateFields();if (editingUser) {// 更新用户await updateUser({variables: { id: editingUser.id, name: values.name, email: values.email },});message.success('User updated successfully');} else {// 创建新用户await createUser({variables: { name: values.name, email: values.email },});message.success('User created successfully');}setIsModalVisible(false);refetch(); // 刷新列表} catch (err) {message.error('Failed to save user');}};const handleCancel = () => {setIsModalVisible(false);setIsOrdersModalVisible(false);};const handleUserClick = (user) => {setSelectedUser(user);setIsOrdersModalVisible(true);};const handleOrdersModalClose = () => {setSelectedUser(null);setIsOrdersModalVisible(false);};const columns = [{title: 'Name',dataIndex: 'name',key: 'name',},{title: 'Email',dataIndex: 'email',key: 'email',},{title: 'Actions',key: 'actions',render: (text, record) => (<Space size="middle"><Button type="link" onClick={() => showModal(record)}>Edit</Button><Button type="link" danger onClick={() => handleDelete(record.id)}>Delete</Button><Button type="link" onClick={() => handleUserClick(record)}>View Orders</Button></Space>),},];const orderColumns = [{title: 'Product',dataIndex: 'product',key: 'product',},{title: 'Quantity',dataIndex: 'quantity',key: 'quantity',},{title: 'Order Date',dataIndex: 'order_date',key: 'order_date',render: (date) => new Date(date).toLocaleString(),},];if (loading) return <div>Loading...</div>;if (error) return <div>Error loading users</div>;return (<div><Button type="primary" onClick={() => showModal(null)} style={{ marginBottom: 16 }}>Add User</Button><Tablecolumns={columns}dataSource={data.test_users}rowKey="id"/><Modaltitle={editingUser ? 'Edit User' : 'Create User'}visible={isModalVisible}onOk={handleOk}onCancel={handleCancel}confirmLoading={loading}><Formform={form}layout="vertical"name="userForm"><Form.Itemlabel="Name"name="name"rules={[{ required: true, message: 'Please input the name!' }]}><Input /></Form.Item><Form.Itemlabel="Email"name="email"rules={[{ required: true, message: 'Please input the email!' }, { type: 'email', message: 'Please input a valid email!' }]}><Input /></Form.Item></Form></Modal><Modaltitle={`${selectedUser?.name}'s Orders`}visible={isOrdersModalVisible}onCancel={handleOrdersModalClose}footer={null}>{ordersLoading ? (<div>Loading orders...</div>) : ordersError ? (<div>Error loading orders</div>) : (<Tablecolumns={orderColumns}dataSource={orders}rowKey="id"/>)}</Modal></div>);
};export default UserList;
相关文章:
PostgreSQL + hasura + Apollo + GraphQL + React + Antd
技术栈 PostgreSQL hasura Apollo GraphQL React Antd 适用于复杂的查询,快速开发 环境安装 安装PostgreSQL hasura,使用docker安装 使用 Docker Compose 部署时,它会同时启动两个容器PostgreSQL和 Hasura GraphQL ,如下 version: "3.6" serv…...
Android笔记【10】
一、前言 学习课程时,对于自己不懂的点的记录。 二、内容 学习一段代码: val drawerState rememberDrawerState(DrawerValue.Closed)val scope rememberCoroutineScope()Scaffold (topBar{TopAppBar(navigationIcon {IconButton(onClick {scope.lau…...
Leetcode打卡:N皇后
执行结果:通过 题目:51 N皇后 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#…...
Linux内核4.14版本——ccf时钟子系统(3)——ccf一些核心结构体
目录 1. struct clk_hw 2. struct clk_ops 3. struct clk_core 4. struct clk_notifier 5. struct clk 6. struct clk_gate 7. struct clk_divider 8. struct clk_mux 9. struct clk_fixed_factor 10. struct clk_fractional_divider 11. struct clk_multiplier 12…...
[Deep Learning] 深度学习中常用函数的整理与介绍(pytorch为例)
文章目录 深度学习中常用函数的整理与介绍常见损失函数1. L2_loss | nn.MSELoss()公式表示:特点:应用:缺点:主要参数:示例用法:注意事项: 2. L1 Loss | nn.L1Loss数学定义:特点&…...
【ETCD】etcd简单入门之单节点部署etcd
etcd 是一个分布式可靠的键值存储系统,用于分布式系统中最关键的数据,主要特点包括: 简单:具有明确的、面向用户的 API(gRPC) 安全:自动 TLS 支持,并可选的客户端证书认证 快速&am…...
Cadence基础语法
03-Cadence基础语法 0 Cadence基础语法入门:流程编排语言的新星 Cadence是由Uber开发的一种领域特定语言(Domain-Specific Language,DSL),专门用于编写可扩展的长时间运行的业务流程。它是Temporal工作流引擎的核心组…...
GAMES101虚拟机使用教程与探讨
写在前面 环境配置请参考作业0的pdf,本文章主要对于配置好环境后怎么使用以及遇到的问题进行探讨(要是有更方便的使用方式欢迎在评论区讨论),自己刚开始用的时候也折腾了好久,希望能为后来学习的小伙伴节约一点工具使…...
王道考研编程题总结
我还在完善中,边复习边完善(这个只是根据我自身总结的) 一、 线性表 1. 结构体 #define MaxSize 40 typedef struct{ElemType data[MaxSize];int length; }SqList 2. 编程题 1. 删除最小值 题意 :从顺序表中删除…...
算法2--滑动窗口
滑动窗口 滑动窗口经典例题长度最小的子数组无重复字符的最长子串[最大连续1的个数 III](https://leetcode.cn/problems/max-consecutive-ones-iii/description/)[将 x 减到 0 的最小操作数](https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/description…...
pycharm或conda中配置镜像源
文章目录 1. 为什么要配置镜像源2. pycharm配置2.1使用pip配置国内镜像源2.2 Pycharm中更改镜像源 3.conda配置镜像源3.1 使用conda命令3.2 文件所在位置(进行增删)3.3 conda常用的几个命令 参考文献 1. 为什么要配置镜像源 由于Python在下载包时&#…...
C#基础之方法
文章目录 1 方法1.1 定义方法1.2 参数传递1.2.1 按值传递参数1.2.2 按引用传递参数1.2.3 按输出传递参数1.2.4 可变参数 params1.2.5 具名参数1.2.6 可选参数 1.3 匿名方法1.3.1 Lambda 表达式1.3.1.1 定义1.3.1.2 常用类型1.3.1.3 Lambda 表达式与 LINQ1.3.1.4 Lambda 表达式的…...
JVM 性能调优 -- JVM常用调优工具【jps、jstack、jmap、jstats 命令】
前言: 前面我们分析怎么去预估系统资源,怎么去设置 JVM 参数以及怎么去看 GC 日志,本篇我们分享一些常用的 JVM 调优工具,我们在进行 JVM 调优的时候,通常需要借助一些工具来对系统的进行相关分析,从而确定…...
PostgreSQL 三种关库模式
PostgreSQL 三种关库模式 基础信息 OS版本:Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本:16.2 pg软件目录:/home/pg16/soft pg数据目录:/home/pg16/data 端口:5777PostgreSQL 提供了三种关库模式&…...
《运放秘籍》第二部:仪表放大器专项知识点总结
一、差分放大器与仪表放大器的讨论 1.1. 仪放的前世今生——差分放大器原理? 1.2. 差分放大的原理 1.3. 差分放大器检测电流 1.4. 差分放大器端一:输入阻抗 1.5. 差分放大器端二:共模抑制比 1.6. 为什么关注输入阻抗?共模抑…...
C++STL之vector(超详细)
CSTL之vector 1.vector基本介绍2.vector重要接口2.1.构造函数2.2.迭代器2.3.空间2.3.1.resize2.3.2.capacity 2.4.增删查找 3.迭代器失效4.迭代器分类 🌟🌟hello,各位读者大大们你们好呀🌟🌟 🚀Ὠ…...
ubuntu环境下安装electron环境,并快速打包
1.配置镜像源 关闭防火墙,命令:sudo ufw disable 1.1配置国内镜像源: vim /etc/apt/source.list deb https://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiversedeb-src https://mirrors.aliyun.com/ubuntu/ jammy main…...
【Pytorch】优化器(Optimizer)模块‘torch.optim’
torch.optim 是 PyTorch 中提供的优化器(Optimizer)模块,用于优化神经网络模型的参数,更新网络权重,使得模型在训练过程中最小化损失函数。它提供了多种常见的优化算法,如 梯度下降法(SGD&#…...
API平台建设之路:从0到1的实践指南
在这个互联网蓬勃发展的时代,API已经成为连接各个系统、服务和应用的重要纽带。搭建一个优质的API平台不仅能为开发者提供便利,更能创造可观的商业价值。让我们一起探讨如何打造一个成功的API平台。 技术架构是API平台的根基。选择合适的技术栈对平台的…...
【Flink-scala】DataStream编程模型之窗口计算-触发器-驱逐器
DataStream API编程模型 1.【Flink-Scala】DataStream编程模型之数据源、数据转换、数据输出 2.【Flink-scala】DataStream编程模型之 窗口的划分-时间概念-窗口计算程序 文章目录 DataStream API编程模型前言1.触发器1.1 代码示例 2.驱逐器2.1 代码示例 总结 前言 本小节我想…...
信号灯集以及 P V 操作
一、信号灯集 1.1 信号灯集的概念 信号灯集是进程间同步的一种方式。 信号灯集创建后,在信号灯集内部会有很多个信号灯。 每个信号灯都可以理解为是一个信号量。 信号灯的编号是从0开始的。 比如A进程监视0号灯,B进程监视1号灯。 0号灯有资源&…...
在 Flutter app 中,通过视频 URL 下载视频到手机相册
在 Flutter app 中,通过视频 URL 下载视频到手机相册可以通过以下步骤实现: 1. 添加依赖 使用 dio 下载文件,结合 path_provider 获取临时存储路径,以及 gallery_saver 将文件保存到相册。 在 pubspec.yaml 中添加以下依赖&…...
Nature Methods | 人工智能在生物与医学研究中的应用
Nature Methods | 人工智能在生物与医学研究中的应用 生物研究中的深度学习 随着人工智能(AI)技术的迅速发展,尤其是深度学习和大规模预训练模型的出现,AI在生物学研究中的应用正在经历一场革命。从基因组学、单细胞组学到癌症生…...
Axure PR 9 随机函数 设计交互
大家好,我是大明同学。 这期内容,我们将深入探讨Axure中随机函数的用法。 随机函数 创建随机函数所需的元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.在元件库中拖出一个矩形元件。 3.选中矩形元件,样式窗格中,将…...
【人工智能基础05】决策树模型
文章目录 一. 基础内容1. 决策树基本原理1.1. 定义1.2. 表示成条件概率 2. 决策树的训练算法2.1. 划分选择的算法信息增益(ID3 算法)信息增益比(C4.5 算法)基尼指数(CART 算法)举例说明:计算各个…...
【人工智能基础03】机器学习(练习题)
文章目录 课本习题监督学习的例子过拟合和欠拟合常见损失函数,判断一个损失函数的好坏无监督分类:kmeans无监督分类,Kmeans 三分类问题变换距离函数选择不同的起始点 重点回顾1. 监督学习、半监督学习和无监督学习的定义2. 判断学习场景3. 监…...
HarmonyOS(60)性能优化之状态管理最佳实践
状态管理最佳实践 1、避免在循环中访问状态变量1.1 反例1.2 正例 2、避免不必要的状态变量的使用3、建议使用临时变量替换状态变量3.1 反例3.2 正例 4、参考资料 1、避免在循环中访问状态变量 在应用开发中,应避免在循环逻辑中频繁读取状态变量,而是应该…...
数据库课程设计报告 超市会员管理系统
一、系统简介 1.1设计背景 受到科学技术的推动,全球计算机的软硬件技术迅速发展,以计算机为基础支撑的信息化如今已成为现代企业的一个重要标志与衡量企业综合实力的重要标准,并且正在悄无声息的影响与改变着国内外广泛的中小型企业的运营模…...
C++算法练习-day54——39.组合总和
题目来源:. - 力扣(LeetCode) 题目思路分析 题目:给定一个整数数组 candidates 和一个目标数 target,找出所有独特的组合,这些组合中的数字之和等于 target。每个数字在每个组合中只能使用一次。 思路&a…...
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
物流建设网站总结/百度网盘资源搜索
点蓝字关注我们大胆热爱Hello Everybody【火影秘术小课堂】开课了本期的主题【c盘满了怎么办】火粉们赶紧搬好小板凳,准备上课吧1c盘为什么会满在如今这个信息爆炸增长的时代,我们要看的信息越来越多,也就意味着在电脑里有意无意留存的资料也…...
日照网站建设全58长/seo的中文意思
牡丹灵通卡 (中国工商银行)异地ATM取款:异地本行ATM跨行取款每笔取款金额的1%,最低1元,最高50元;异地跨行ATM取款每笔手续费为2元取款金额的1%,1%部分最低1元,最高50元; …...
什么网站可以做数据调查/企业品牌推广方案
package code.test;import java.util.Comparator; import java.util.Iterator; import java.util.PriorityQueue; import java.util.Queue;/*** 实验表明,在java中:* 1.toString()方法或迭代元素:优先级队列打印或者迭代,得到的输…...
兴仁企业建站公司/谷歌手机版下载安装
01. ip address show/ip a 检查网卡地址配置02. ping 测试网络连通性03. nmtui 图形界面修改网卡地址信息04. exit 注销05. shutdown 关机命令shutdown -h 5 指定关机时间 (推荐)shutdown -r 5 重启主机时间 (推荐)shutdown -…...
澳门网站建设运营app/yandex搜索引擎
count是一种最简单的聚合函数,一般也是我们第一个开始学习的聚合函数.很多人认为count(1)执行的效率会比count()高,原因是count()会存在全表扫描,而count(1)可以针对一个字段进行查询。其实不然,count(1)和count(*)都会对全表进行…...
网站开发的最后五个阶段/什么是优化师
Git中删除文件可不太一样哦,我们一起来学习一下在Git中如果你想要删除文件,比平时我们删除文件要麻烦那么一点点,毕竟Git有两个地方:工作区、版本库,平时我们删除文件的方式,只是把工作区的文件给删除了&am…...