5.1-使用Query Builder查询

使用 Query Builder 查询

什么是QueryBuilder

QueryBuilder是 TypeORM 最强大的功能之一 ,它允许你使用优雅便捷的语法构建 SQL 查询,执行并获得自动转换的实体。

QueryBuilder的简单示例:

const firstUser = await connection
  .getRepository(User)
  .createQueryBuilder("user")
  .where("user.id = :id", { id: 1 })
  .getOne();

它将生成以下 SQL 查询:

SELECT
    user.id as userId,
    user.firstName as userFirstName,
    user.lastName as userLastName
FROM users user
WHERE user.id = 1

然后返回一个 User 实例:

User {
    id: 1,
    firstName: "Timber",
    lastName: "Saw"
}

如何创建和使用QueryBuilder

有几种方法可以创建Query Builder

  • 使用 connection:

    import { getConnection } from "typeorm";
    
    const user = await getConnection()
      .createQueryBuilder()
      .select("user")
      .from(User, "user")
      .where("user.id = :id", { id: 1 })
      .getOne();
    
  • 使用 entity manager:

    import { getManager } from "typeorm";
    
    const user = await getManager()
      .createQueryBuilder(User, "user")
      .where("user.id = :id", { id: 1 })
      .getOne();
    
  • 使用 repository:

    import { getRepository } from "typeorm";
    
    const user = await getRepository(User)
      .createQueryBuilder("user")
      .where("user.id = :id", { id: 1 })
      .getOne();
    

有 5 种不同的QueryBuilder类型可用:

  • SelectQueryBuilder - 用于构建和执行SELECT查询。 例如:

    import { getConnection } from "typeorm";
    
    const user = await getConnection()
      .createQueryBuilder()
      .select("user")
      .from(User, "user")
      .where("user.id = :id", { id: 1 })
      .getOne();
    
  • InsertQueryBuilder - 用于构建和执行INSERT查询。 例如:

    import { getConnection } from "typeorm";
    
    await getConnection()
      .createQueryBuilder()
      .insert()
      .into(User)
      .values([{ firstName: "Timber", lastName: "Saw" }, { firstName: "Phantom", lastName: "Lancer" }])
      .execute();
    
  • UpdateQueryBuilder - 用于构建和执行UPDATE查询。 例如:

    import { getConnection } from "typeorm";
    
    await getConnection()
      .createQueryBuilder()
      .update(User)
      .set({ firstName: "Timber", lastName: "Saw" })
      .where("id = :id", { id: 1 })
      .execute();
    
  • DeleteQueryBuilder - 用于构建和执行DELETE查询。 例如:

    import { getConnection } from "typeorm";
    
    await getConnection()
      .createQueryBuilder()
      .delete()
      .from(User)
      .where("id = :id", { id: 1 })
      .execute();
    
  • RelationQueryBuilder - 用于构建和执行特定于关系的操作[TBD]。

你可以在其中切换任何不同类型的查询构建器,一旦执行,则将获得一个新的查询构建器实例(与所有其他方法不同)。

使用QueryBuilder获取值

要从数据库中获取单个结果,例如通过 id 或 name 获取用户,必须使用getOne

const timber = await getRepository(User)
  .createQueryBuilder("user")
  .where("user.id = :id OR user.name = :name", { id: 1, name: "Timber" })
  .getOne();

要从数据库中获取多个结果,例如,要从数据库中获取所有用户,请使用getMany

const users = await getRepository(User)
  .createQueryBuilder("user")
  .getMany();

使用查询构建器查询可以获得两种类型的结果:entitiesraw results
大多数情况下,你只需要从数据库中选择真实实体,例如 users。
为此,你可以使用getOnegetMany
但有时你需要选择一些特定的数据,比方说所有sum of all user photos
此数据不是实体,它称为原始数据。
要获取原始数据,请使用getRawOnegetRawMany
例如:

const { sum } = await getRepository(User)
  .createQueryBuilder("user")
  .select("SUM(user.photosCount)", "sum")
  .where("user.id = :id", { id: 1 })
  .getRawOne();
const photosSums = await getRepository(User)
  .createQueryBuilder("user")
  .select("user.id")
  .addSelect("SUM(user.photosCount)", "sum")
  .where("user.id = :id", { id: 1 })
  .getRawMany();

// 结果会像这样: [{ id: 1, sum: 25 }, { id: 2, sum: 13 }, ...]

什么是别名?

我们使用createQueryBuilder("user")。 但什么是"user"?
它只是一个常规的 SQL 别名。
我们在任何地方都使用别名,除非我们处理选定的数据。

createQueryBuilder("user") 相当于:

createQueryBuilder()
  .select("user")
  .from(User, "user");

这会生成以下 sql 查询:

SELECT ... FROM users user

在这个 SQL 查询中,users是表名,user是我们分配给该表的别名。

稍后我们使用此别名来访问表:

createQueryBuilder()
  .select("user")
  .from(User, "user")
  .where("user.name = :name", { name: "Timber" });

以上代码会生成如下 SQL 语句:

SELECT ... FROM users user WHERE user.name = 'Timber'

看到了吧,我们使用了在创建查询构建器时分配的user别名来使用 users 表。

一个查询构建器不限于一个别名,它们可以有多个别名。
每个选择都可以有自己的别名,你可以选择多个有自己别名的表,你可以使用自己的别名连接多个表。
你也可以使用这些别名来访问选择的表(或正在选择的数据)。

使用参数来转义数据

我们使用了where("user.name = :name", { name: "Timber" }).
{name:“Timber”}代表什么? 这是我们用来阻止 SQL 注入的参数。
我们可以写:where("user.name ='"+ name +"'),但是这不安全,因为有可能被 SQL 注入。
安全的方法是使用这种特殊的语法:where("user.name =name",{name:"Timber"}),其中name是参数名,值在对象中指定: {name:"Timber"}

.where("user.name = :name", { name: "Timber" })

是下面的简写:

.where("user.name = :name")
.setParameter("name", "Timber")

注意:不要在查询构建器中为不同的值使用相同的参数名称。如果多次设置则后值将会把前面的覆盖。

还可以提供一组值,并使用特殊的扩展语法将它们转换为SQL语句中的值列表:

.where("user.name IN (:...names)", { names: [ "Timber", "Cristal", "Lina" ] })

该语句将生成:

WHERE user.name IN ('Timber', 'Cristal', 'Lina')

添加WHERE表达式

添加 WHERE 表达式就像:

createQueryBuilder("user").where("user.name = :name", { name: "Timber" });

将会生成以下 SQL 语句:

SELECT ... FROM users user WHERE user.name = 'Timber'

你可以将 AND 添加到现有的 WHERE 表达式中:

createQueryBuilder("user")
  .where("user.firstName = :firstName", { firstName: "Timber" })
  .andWhere("user.lastName = :lastName", { lastName: "Saw" });

将会生成以下 SQL 语句:

SELECT ... FROM users user WHERE user.firstName = 'Timber' AND user.lastName = 'Saw'

你也可以添加 OR 添加到现有的 WHERE 表达式中:

createQueryBuilder("user")
  .where("user.firstName = :firstName", { firstName: "Timber" })
  .orWhere("user.lastName = :lastName", { lastName: "Saw" });

将会生成以下 SQL 语句:

SELECT ... FROM users user WHERE user.firstName = 'Timber' OR user.lastName = 'Saw'

你可以使用Brackets将复杂的WHERE表达式添加到现有的WHERE中:

createQueryBuilder("user")
    .where("user.registered = :registered", { registered: true })
    .andWhere(new Brackets(qb => {
        qb.where("user.firstName = :firstName", { firstName: "Timber" })
          .orWhere("user.lastName = :lastName", { lastName: "Saw" })

将会生成以下 SQL 语句:

SELECT ... FROM users user WHERE user.registered = true AND (user.firstName = 'Timber' OR user.lastName = 'Saw')

你可以根据需要组合尽可能多的ANDOR表达式。
如果你多次使用.where,你将覆盖所有以前的WHERE表达式。
注意:小心orWhere - 如果你使用带有ANDOR表达式的复杂表达式,请记住他们将无限制的叠加。
有时你只需要创建一个 where 字符串,避免使用orWhere

添加HAVING表达式

添加HAVING表达式很简单:

createQueryBuilder("user").having("user.name = :name", { name: "Timber" });

将会生成以下 SQL 语句:

SELECT ... FROM users user HAVING user.name = 'Timber'

你可以添加 AND 到已经存在的 HAVING 表达式中:

createQueryBuilder("user")
  .having("user.firstName = :firstName", { firstName: "Timber" })
  .andHaving("user.lastName = :lastName", { lastName: "Saw" });

将会生成以下 SQL 语句:

SELECT ... FROM users user HAVING user.firstName = 'Timber' AND user.lastName = 'Saw'

你可以添加 OR 到已经存在的 HAVING 表达式中:

createQueryBuilder("user")
  .having("user.firstName = :firstName", { firstName: "Timber" })
  .orHaving("user.lastName = :lastName", { lastName: "Saw" });

将会生成以下 SQL 语句:

SELECT ... FROM users user HAVING user.firstName = 'Timber' OR user.lastName = 'Saw'

你可以根据需要组合尽可能多的ANDOR表达式。
如果使用多个.having,后面的将覆盖所有之前的HAVING表达式。

添加ORDER BY表达式

添加 ORDER BY 很简单:

createQueryBuilder("user").orderBy("user.id");

将会生成一下 SQL 语句:

SELECT ... FROM users user ORDER BY user.id

你可以将排序方向从升序更改为降序(或反之亦然):

createQueryBuilder("user").orderBy("user.id", "DESC");

createQueryBuilder("user").orderBy("user.id", "ASC");

也可以添加多个排序条件:

createQueryBuilder("user")
  .orderBy("user.name")
  .addOrderBy("user.id");

还可以使用排序字段作为一个 map:

createQueryBuilder("user").orderBy({
  "user.name": "ASC",
  "user.id": "DESC"
});

如果你使用了多个.orderBy,后面的将覆盖所有之前的ORDER BY表达式。

添加GROUP BY表达式

添加 GROUP BY 表达式很简单:

createQueryBuilder("user").groupBy("user.id");

将会生成以下 SQL 语句:

SELECT ... FROM users user GROUP BY user.id

如果要使用更多 group-by, 则可以使用 caddGroupBy:

createQueryBuilder("user")
  .groupBy("user.name")
  .addGroupBy("user.id");

如果使用了多个.groupBy ,则后面的将会覆盖之前所有的 ORDER BY 表达式。

添加LIMIT表达式

添加 LIMIT 表达式很简单:

createQueryBuilder("user").limit(10);

将会生成以下 SQL 语句:

SELECT ... FROM users user LIMIT 10

生成的 SQL 查询取决于数据库的类型(SQL,mySQL,Postgres 等)。
注意:如果你使用带有连接或子查询的复杂查询,LIMIT 可能无法正常工作。
如果使用分页,建议使用take代替。

添加OFFSET表达式

添加 SQLOFFSET表达式很简单:

createQueryBuilder("user").offset(10);

将会生成以下 SQL 语句:

SELECT ... FROM users user OFFSET 10

生成的 SQL 查询取决于数据库的类型(SQL,mySQL,Postgres 等)。
注意:如果你使用带有连接或子查询的复杂查询,OFFSET 可能无法正常工作。
如果使用分页,建议使用skip代替。

联查

假设有以下实体:

import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
import { Photo } from "./Photo";

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @OneToMany(type => Photo, photo => photo.user)
  photos: Photo[];
}
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
import { User } from "./User";

@Entity()
export class Photo {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  url: string;

  @ManyToOne(type => User, user => user.photos)
  user: User;
}

现在让我们假设你要用用户"Timber"加载他所有的 photos:

const user = await createQueryBuilder("user")
  .leftJoinAndSelect("user.photos", "photo")
  .where("user.name = :name", { name: "Timber" })
  .getOne();

你将会得到以下结果:

{
    id: 1,
    name: "Timber",
    photos: [{
        id: 1,
        url: "me-with-chakram.jpg"
    }, {
        id: 2,
        url: "me-with-trees.jpg"
    }]
}

你可以看到leftJoinAndSelect自动加载了所有 Timber 的 photos。
第一个参数是你要加载的关系,第二个参数是你为此关系的表分配的别名。
你可以在查询构建器中的任何位置使用此别名。
例如,让我们获得所有未删除的 Timber 的 photos。

const user = await createQueryBuilder("user")
  .leftJoinAndSelect("user.photos", "photo")
  .where("user.name = :name", { name: "Timber" })
  .andWhere("photo.isRemoved = :isRemoved", { isRemoved: false })
  .getOne();

将会生成以下 SQL 查询:

SELECT user.*, photo.* FROM users user
    LEFT JOIN photos photo ON photo.user = user.id
    WHERE user.name = 'Timber' AND photo.isRemoved = FALSE

你还可以向连接表达式添加条件,而不是使用"where":

const user = await createQueryBuilder("user")
  .leftJoinAndSelect("user.photos", "photo", "photo.isRemoved = :isRemoved", { isRemoved: false })
  .where("user.name = :name", { name: "Timber" })
  .getOne();

这将生成以下 sql 查询:

SELECT user.*, photo.* FROM users user
    LEFT JOIN photos photo ON photo.user = user.id AND photo.isRemoved = FALSE
    WHERE user.name = 'Timber'

内联和左联

如果你想使用INNER JOIN而不是LEFT JOIN,只需使用innerJoinAndSelect

const user = await createQueryBuilder("user")
  .innerJoinAndSelect("user.photos", "photo", "photo.isRemoved = :isRemoved", { isRemoved: false })
  .where("user.name = :name", { name: "Timber" })
  .getOne();

This will generate:

SELECT user.*, photo.* FROM users user
    INNER JOIN photos photo ON photo.user = user.id AND photo.isRemoved = FALSE
    WHERE user.name = 'Timber'

LEFT JOININNER JOIN之间的区别在于,如果没有任何 photos,INNER JOIN将不会返回 user。
即使没有 photos,LEFT JOIN也会返回 user。
要了解有关不同连接类型的更多信息,请参阅 SQL 文档.

不使用条件的联查

你可以在不使用条件的情况下联查数据。
要做到这一点,使用leftJoininnerJoin

const user = await createQueryBuilder("user")
  .innerJoin("user.photos", "photo")
  .where("user.name = :name", { name: "Timber" })
  .getOne();

将会生成如下 SQL 语句:

SELECT user.* FROM users user
    INNER JOIN photos photo ON photo.user = user.id
    WHERE user.name = 'Timber'

这将会返回 Timber 如果他有 photos,但是并不会返回他的 photos。

联查任何实体或表

你不仅能联查关系,还能联查任何其他实体或表。

例如:

const user = await createQueryBuilder("user")
  .leftJoinAndSelect(Photo, "photo", "photo.userId = user.id")
  .getMany();
const user = await createQueryBuilder("user")
  .leftJoinAndSelect("photos", "photo", "photo.userId = user.id")
  .getMany();

联查和映射功能

profilePhoto添加到User实体,你可以使用QueryBuilder将任何数据映射到该属性:

export class User {
  /// ...
  profilePhoto: Photo;
}
const user = await createQueryBuilder("user")
  .leftJoinAndMapOne("user.profilePhoto", "user.photos", "photo", "photo.isForProfile = TRUE")
  .where("user.name = :name", { name: "Timber" })
  .getOne();

这将加载 Timber 的个人资料照片并将其设置为user.profilePhoto
如果要加载并映射单个实体,请使用leftJoinAndMapOne
如果要加载和映射多个实体,请使用leftJoinAndMapMany

获取生成的sql查询语句

有时你可能想要获取QueryBuilder生成的 SQL 查询。
为此,请使用getSql

const sql = createQueryBuilder("user")
  .where("user.firstName = :firstName", { firstName: "Timber" })
  .orWhere("user.lastName = :lastName", { lastName: "Saw" })
  .getSql();

出于调试目的,你也可以使用printSql

const users = await createQueryBuilder("user")
  .where("user.firstName = :firstName", { firstName: "Timber" })
  .orWhere("user.lastName = :lastName", { lastName: "Saw" })
  .printSql()
  .getMany();

此查询将返回 users 并将使用的 sql 语句打印到控制台。

获得原始结果

使用选择查询构建器可以获得两种类型的结果:entitiesraw results
大多数情况下,你只需要从数据库中选择真实实体,例如 users。
为此,你可以使用getOnegetMany
但是,有时需要选择特定数据,例如 sum of all user photos
这些数据不是实体,它被称为原始数据。
要获取原始数据,请使用getRawOnegetRawMany
例如:

const { sum } = await getRepository(User)
  .createQueryBuilder("user")
  .select("SUM(user.photosCount)", "sum")
  .where("user.id = :id", { id: 1 })
  .getRawOne();
const photosSums = await getRepository(User)
  .createQueryBuilder("user")
  .select("user.id")
  .addSelect("SUM(user.photosCount)", "sum")
  .where("user.id = :id", { id: 1 })
  .getRawMany();

// 结果将会像这样: [{ id: 1, sum: 25 }, { id: 2, sum: 13 }, ...]

流数据

你可以使用stream来返回流。
Streaming 返回原始数据,必须手动处理实体转换:

const stream = await getRepository(User)
  .createQueryBuilder("user")
  .where("user.id = :id", { id: 1 })
  .stream();

使用分页

大多数情况下,在开发应用程序时,你可能需要分页功能。
如果你的应用程序中有分页,page slider 或无限滚动组件,则使用此选项。

const users = await getRepository(User)
  .createQueryBuilder("user")
  .leftJoinAndSelect("user.photos", "photo")
  .take(10)
  .getMany();

将会返回前 10 个 user 的 photos。

const users = await getRepository(User)
  .createQueryBuilder("user")
  .leftJoinAndSelect("user.photos", "photo")
  .skip(10)
  .getMany();

将返回除了前 10 个 user 以外的所有 user 的 photos。

你可以组合这些方法:

const users = await getRepository(User)
  .createQueryBuilder("user")
  .leftJoinAndSelect("user.photos", "photo")
  .skip(5)
  .take(10)
  .getMany();

这将跳过前 5 个 users,并获取他们之后的 10 个 user。

takeskip可能看起来像我们正在使用limitoffset,但它们不是。
一旦你有更复杂的连接或子查询查询,limitoffset可能无法正常工作。
使用takeskip可以防止这些问题。

加锁

QueryBuilder 支持 optimistic 和 pessimistic 锁定。
要使用 pessimistic 读锁定,请使用以下方式:

const users = await getRepository(User)
  .createQueryBuilder("user")
  .setLock("pessimistic_read")
  .getMany();

要使用 pessimistic 写锁定,请使用以下方式:

const users = await getRepository(User)
  .createQueryBuilder("user")
  .setLock("pessimistic_write")
  .getMany();

要使用 optimistic 读锁定,请使用以下方式:

const users = await getRepository(User)
  .createQueryBuilder("user")
  .setLock("optimistic", existUser.version)
  .getMany();

要使用 dirty 读锁定,请使用以下方式:

const users = await getRepository(User)
    .createQueryBuilder("user")
    .setLock("dirty_read")
    .getMany();

Optimistic 锁定与@Version@UpdatedDate装饰器一起使用。

查询部分字段

如果只想选择实体的某些属性,可以使用以下语法:

const users = await getRepository(User)
  .createQueryBuilder("user")
  .select(["user.id", "user.name"])
  .getMany();

这只会选择Useridname

使用子查询

你可以轻松创建子查询。 FROMWHEREJOIN表达式都支持子查询。
例如:

const qb = await getRepository(Post).createQueryBuilder("post");
const posts = qb
  .where(
    "post.title IN " +
      qb
        .subQuery()
        .select("user.name")
        .from(User, "user")
        .where("user.registered = :registered")
        .getQuery()
  )
  .setParameter("registered", true)
  .getMany();

使用更优雅的方式来做同样的事情:

const posts = await connection
  .getRepository(Post)
  .createQueryBuilder("post")
  .where(qb => {
    const subQuery = qb
      .subQuery()
      .select("user.name")
      .from(User, "user")
      .where("user.registered = :registered")
      .getQuery();
    return "post.title IN " + subQuery;
  })
  .setParameter("registered", true)
  .getMany();

或者,你可以创建单独的查询构建器并使用其生成的 SQL:

const userQb = await connection
  .getRepository(User)
  .createQueryBuilder("user")
  .select("user.name")
  .where("user.registered = :registered", { registered: true });

const posts = await connection
  .getRepository(Post)
  .createQueryBuilder("post")
  .where("post.title IN (" + userQb.getQuery() + ")")
  .setParameters(userQb.getParameters())
  .getMany();

你可以在FROM中创建子查询,如下所示:

const userQb = await connection
  .getRepository(User)
  .createQueryBuilder("user")
  .select("user.name", "name")
  .where("user.registered = :registered", { registered: true });

const posts = await connection
  .createQueryBuilder()
  .select("user.name", "name")
  .from("(" + userQb.getQuery() + ")", "user")
  .setParameters(userQb.getParameters())
  .getRawMany();

或使用更优雅的语法:

const posts = await connection
  .createQueryBuilder()
  .select("user.name", "name")
  .from(subQuery => {
    return subQuery
      .select("user.name", "name")
      .from(User, "user")
      .where("user.registered = :registered", { registered: true });
  }, "user")
  .getRawMany();

如果想添加一个子查询做为"second from",请使用addFrom

你也可以在SELECT语句中使用子查询:

const posts = await connection
  .createQueryBuilder()
  .select("post.id", "id")
  .addSelect(subQuery => {
    return subQuery
      .select("user.name", "name")
      .from(User, "user")
      .limit(1);
  }, "name")
  .from(Post, "post")
  .getRawMany();

隐藏列

如果要查询的模型具有"select:false"的列,则必须使用addSelect函数来从列中检索信息。

假设你有以下实体:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column({ select: false })
  password: string;
}

使用标准的find或查询,你将不会接收到模型的password属性。 但是,如果执行以下操作:

const users = await connection
  .getRepository(User)
  .createQueryBuilder()
  .select("user.id", "id")
  .addSelect("user.password")
  .getMany();

你将在查询中获得属性password

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一.数据仓库发展的商业驱动力 3 1.1 企业生存环境的变化 3 1.2 企业如何迎接市场变化带来的挑战 4 1.2.1 开拓市场:理解市场 4 1.2.2 提高企业运作绩效:理解业务 5 1.2.3 平衡市场发展目标和企业运作 5 1.3 基于数据仓库的有效的商务解决方案的要求 6 1.4 ORACLE数据仓库:被证明是有实力的商务解决方案 6 二、ORACLE数据仓库的体系结构 7 2.1 数据仓库的平台:数据库和决策分析工具 11 2.1.1 Oracle8i的数据仓库新特性 11 2.1.2 Oracle OLAP产品的新发展 13 2.1.3 Oracle 集成的决策支持产品工具集 16 2.2 市场发展分析应用 17 2.3 企业运作分析应用 18 2.4 平衡市场和企业运作目标的应用 18 2.5 ORACLE商业智能系统 19 2.6 ORACLE数据仓库实施咨询服务 19 2.7 ORACLE数据仓库合作伙伴计划 20 三、ORACLE数据仓库的平台--ORACLE8I 21 3.1 丰富查询处理技术(RICH QUERY PROCESSING TECHNIQUES) 22 3.2 高级SQL优化器(SOPHISTICATED SQL OPTIMIZER) 23 3.3 高端数据仓库技术和OLTP 24 3.4 资源管理 24 3.5 分区表(PARTIONED TABLES)与索引 24 3.6 摘要管理 25 3.7 透明的表空间 25 3.8 直接的路径装载API 26 3.9 数据仓库的增强功能 26 3.10 先进的查询技术与业务事件 26 3.11 ORACLE8I并行服务器改进 27 3.12 扩展的备份与恢复子系统 28 3.13 ORACLE开放式网关提供异种数据源访问技术 28 3.14 增强的多媒体信息处理能力ORACLE 8I INTERMEDIA 30 3.15 数据库管理工具ORACLE ENTERPRISE MANAGER 31 四、ORACLE数据仓库设计和建立工具--WAREHOUSE BUILDER 34 五、ORACLE集成的决策分析工具集 36 5.1 ORACLE的联机分析处理(OLAP)工具--ORACLE EXPRESS 36 5.1.1 Oracle Express服务器 36 5.1.2 Oracle OLAP的强大的开发工具 42 5.2 ORACLE即席查询分析工具--ORACLE DISCOVERER 48 5.3 ORACLE 企业级的报表工具--ORACLE REPORTS 57 5.4 ORACLE的数据挖掘工具--DATA MINING SUITE 60 5.5 ORACLE应用服务器—INTERNET APPLICATION SERVER 61 六、数据仓库的发展趋势:与电子商务的融合 64
### 回答1: Understand是一种功能强大的软件开发工具,它提供了多种语言和平台的静态代码分析功能,用于帮助开发人员理解和改进他们的代码质量。 5.1是Understand的一个特定版本号,它表示 Understad软件的第5个大版本中的一个小更新。 Windows64表示这个Understand版本适用于运行在Windows操作系统的64位机器上。 通过使用Understand 5.1-windows64,开发人员可以对代码进行全面的分析和评估,以确保代码的质量和可维护性。它可以帮助开发人员识别潜在的代码缺陷、冗余代码和性能问题,并提供解决方案来改善代码质量。 该版本还具备了适用于Windows 64位机器的优化和兼容性,以确保在这样的机器上能够运行和运行分析任务的平稳性。 总之,Understand 5.1-windows64是一款适用于在Windows 64位操作系统上运行的强大的软件开发工具,它为开发人员提供了全面的代码分析功能,帮助他们提高代码质量和可维护性。 ### 回答2: understand 5.1-windows64 指的是一个软件的版本和系统要求。Understand 是一款用于源代码分析的软件工具,用于帮助开发人员理解和浏览复杂的代码。5.1 是这个软件的版本号,表示该软件经过一系列的更新和改进。windows64 表示该软件支持 64 位的 Windows 操作系统。 对于开发人员来说,使用 Understand 5.1-windows64 有几个优势。首先,它可以帮助他们更好地理解和分析源代码。该软件提供了多种功能,如交互式图表、图形视图和搜索功能,可以帮助开发人员深入了解代码的结构和关系,从而更高效地调试和优化代码。 其次,Understand 5.1-windows64 具有良好的兼容性,可以在 Windows 64 位系统上正常运行。64 位操作系统相比于32位操作系统具有更大的内存容量和更快的处理速度,这对于处理大型代码库和复杂的分析任务非常重要。使用 64 位系统可以提高软件工具的性能和效率。 此外,Understand 5.1-windows64 的更新版本可能还会解决了一些 bug,增加了新功能或提高了软件的稳定性。开发人员可以从该软件的版本迭代中获益。 总之,Understand 5.1-windows64 是一款功能强大的源代码分析工具,适用于 Windows 64 位系统。它可以帮助开发人员更好地理解和分析源代码,提高开发效率,并且与 64 位操作系统相对应,能够更好地支持大型代码库和复杂的分析任务。 ### 回答3: understand5.1-windows64是一款用于软件开发的工具,它是在Windows操作系统下工作的64位版本。Understand是一个功能强大的代码理解工具,它可以帮助程序员对代码进行深入的分析和理解。 使用understand5.1-windows64,程序员可以对源代码进行静态分析,了解代码的结构、功能和相互关系。它支持多种编程语言,包括C、C++、C#、Java等。程序员可以快速地浏览代码,并通过各种视图和图表来可视化分析结果。 此外,understand5.1-windows64还提供了全面的代码检查和度量功能,帮助程序员评估代码的质量和健壮性。它可以检测潜在的错误、重复的代码和性能问题,并生成报告供程序员参考和改进。 另外,understand5.1-windows64还支持代码重构和搜索功能。程序员可以通过重构工具对代码进行重构,提高代码的可读性和可维护性。搜索功能可以帮助程序员快速定位特定的代码片段,提高开发效率。 总而言之,understand5.1-windows64是一款功能强大且易于使用的代码理解工具。它提供了丰富的分析和度量功能,帮助程序员更好地理解和改进源代码。无论是初学者还是经验丰富的开发人员,都可以从中受益并提高代码开发的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值